2009-04-08 8 views
7

У меня есть следующий класс: «Бог класс»Что такое лучший дизайн?

class User { 

    public function setName($value) { ... } 
    public function setEmailAddress($value) { ... } 
    public function setUsername($value) { ... } 
    public function getName() { ... } 
    public function getEmailAddress() { ... } 
    public function getUsername() { ... } 

    public function isGroupAdministrator($groupId) { ... } 
    public function isMemberOfGroup($groupId) { ... } 
    public function isSiteAdministrator() { ... } 
    public function isRoot() { ... } 
    public function hasModulePermission($moduleId, $recordId, $permissionCode) { ... } 
    public function hasGroupPermission($groupId, $permissionCode) { ... } 
    public function hasContentPermission($recordId, $permissionCode) { ... } 
    public function hasModulePermission($moduleId, $recordId, $permissionCode) { ... } 
    public function canLogIn() { ... } 
    public function isLoggedIn() { ... } 
    public function setCanLogIn($canLogIn) { ... } 

} 

Это становится

Я не уверен, должен ли я разбить этот класс. Проблема в том, что методы этого класса используются его доменом для определения того, показывать ли данные элементы пользовательского интерфейса на веб-страницах, поэтому в классе нет никакого поведения.

Я полагаю, что я мог бы использовать связанные с разрешением методы в некотором классе Permission, делая эти методы статическими (например. :: userIsGroupAdministrator (...), :: userIsMemberOfGroup (...) :: userHasGroupPermission (...), :: userHasContentPermission (...))

Любые предложения о том, как этот класс может быть лучше?

+0

I предложить пометку как «php» или «language-agnostic» для улучшения видимости. –

ответ

8

Да, я думаю, что ваш пользовательский класс делает слишком много.

Разделить некоторые связанные с группой функции в классе группы и связанные с модулем функции в класс модуля. Или, возможно, разделять разрешения на свой собственный набор классов.

+0

Какие методы вы бы создали в этих классах? –

+0

Группа может иметь getMembers и getAdministrators. Аналогичные вещи идут для модулей. Однако, вероятно, это хорошая идея, чтобы централизовать проверку прав доступа. Определенная центральная функция isPermission(). – Kalium

4

Сложно сказать по имени метода. Одна эвристика, которую я использую, чтобы разбить класс, - это посмотреть на переменные состояния. Есть ли части состояния, которые, как правило, используются вместе? Могут ли они быть разбиты на отдельный класс?

0

Я хотел бы создать класс Permissions и сделать его членом класса User.

+0

Делегирование и скрытие информации. Мне это нравится. –

0

Я бы разделил аспект «пользователь» и «групповой» подход к управлению классом.

0

Я бы по крайней мере убрал функцию setCanLogIn($canLogIn). Это должно действительно определяться внутри класса в зависимости от того, предоставил ли пользователь правильные учетные данные и прошел ли аутентификация.

В зависимости от того, насколько велик этот проект или является ли это частью структуры, будет определено, требуется ли больше абстракции.

+0

Причина, по которой у меня этот метод, заключается в том, что я храню логический флаг для того, может ли пользователь войти в систему. –

0

Кажется, вам нужны отдельные объекты ACL и Role из объекта User.
http://en.wikipedia.org/wiki/Role-based_access_control

Вы также можете увидеть how it's done in ZF.

Для удобства чтения вы можете рассмотреть возможность использования __get() and __set() вместо:

public function setName($value) { ... } 
    public function setEmailAddress($value) { ... } 
    public function setUsername($value) { ... } 
    public function getName() { ... } 
    public function getEmailAddress() { ... } 
    public function getUsername() { ... } 
+0

Определенно на повестке дня. –

1

Это поможет, если вы могли бы описать, как ваш User объект ведет себя, кто все это взаимодействует, что это среда и т.д.

Я полагаю, что я мог бы использовать методы, связанные с разрешением, в некоторых классах разрешений [...]

Да, вы можете взглянуть на политический дизайн.

Я также предлагаю вам вынуть фиксированное состояние адреса электронной почты User.e. и т. Д. И поместить его в отдельный класс.

0

Это выглядит разумно правдоподобным.Конечно, я не знаю приложения. Я думаю, что имеет смысл разделить класс Permissions.

В идеале, тогда вы подумаете о том, что означает иметь класс разрешений - что он знает, каковы его действительные действия? Кроме того, поскольку «разрешения» множественны, вы можете задаться вопросом, действительно ли вы хотите собрать отдельные объекты Permission, но если они действительно являются аксессуарами к простому булевому, который может быть переполнен.

0

До тех пор, пока методы класса возвращают данные экземпляра или изменяют только внутреннее состояние, в классе нет ничего плохого.

Но, например, если метод canLogIn() ищет некоторую внешнюю службу (репозиторий, членский сервис и т. д.), возникает проблема простоты и возможности тестирования. Если это так, вы должны иметь некоторый класс обслуживания и иметь на нем эти методы. Как

new SomeFactory().GetUserService().canLogIn(user); 
9

Если у вас уже есть действующий код, тогда рефакторинг небольшими кусками. Если нет, я бы смотреть на следующее:


class User { 
    String username 
    String name 
    String emailAddress 
    Boolean active 
    Integer permission # A bitmask of the statics in the Permission class 
} 

class Group { 
    String name 
} 

class UserGroupMapping { 
    User user 
    Group group 
    Boolean administrator 
} 

class Permission { 
    static IS_ROOT = 1 
    static IS_SITE_ADMIN = 2 
} 

class Session { 
    User user 
    Boolean logged_in 
} 

Остальная часть этого действительно принадлежит в классе обслуживания:

 
class SecurityService { 
    static public function hasModulePermission($user, $module, $record, $permission) { ... } 
    static public function hasGroupPermission($user, $group, $permission) { ... } 
    static public function hasContentPermission($user, $record, $permission) { ... } 
    static public function hasModulePermission($user, $module, $record, $permission) { ... } 
} 

+0

Вы не можете тестировать эти статические методы. Это, безусловно, плохой дизайн с точки зрения проверяемости. –

+0

Нечего тестировать, кроме класса SecurityService. Все остальное - обертка вокруг атомной части данных. –

1

Насколько сложно теперь, чтобы добавить новые функциональные возможности или сохранить существующую функциональность в вашей заявке? Если у вас нет проблем в этом отношении, тогда вы, вероятно, хорошо держите вещи такими, какие они есть (по крайней мере, на некоторое время).

Да, ваш пользовательский класс имеет некоторые дублирующие обязанности, которые потенциально могут быть реорганизованы в систему Role-based access control.

Практический результат: вы действительно gonna need it?

0

Неплохо, но я думаю, что ваши механики разрешений могут использовать факторинг. Это случай, который явно требует агрегации, а не наследования. Если есть вероятность того, что с пользователем будет связана нетривиальная контактная информация, вам может потребоваться также указать адрес электронной почты, возможно, в Identity, в котором может быть загружена другая контактная информация, если это необходимо.

В общем, я мог бы порекомендовать думать о вашем пользователе как о центральном пункте для агрегации и составления (не наследующих) подразделений функциональности - подхода, который достигает статуса модного слова в разработке игр под рубрикой «система сущностей».

0

Оставьте эти ...они найти IMO:

public function isLoggedIn() { ... } 
public function getEmailAddress() { ... } 
public function setEmailAddress() { ... } 

Предлагаем Вам заменить эти Get/Set функций Имя, которые обрабатывают экземпляр TUserName:

public function getUsername() { ... } 
public function setUsername($value) { ... } 
public function getName() { ... } 
public function setName($value) { ... } 

TUserName бы:

.FirstName 
.LastName 
.MiddleName 
.UserName 

Предлагайте вас замените их функциями Get/Set Admin, которые обрабатывают экземпляр TUserGroup:

public function isGroupAdministrator($groupId) { ... } 
public function isMemberOfGroup($groupId) { ... } 
public function isSiteAdministrator() { ... } 
public function isRoot() { ... } 

TUserGroup бы:

.MemberOfGroup(GroupID) 
.AdminSite 
.Root 
.AdminGroup(GroupID) 

Предлагаем Вам заменить эти Get/Set функций разрешений, которые обрабатывают экземпляр TUserPermissions:

public function hasModulePermission($moduleId, $recordId, $permissionCode) 
public function hasGroupPermission($groupId, $permissionCode) 
public function hasContentPermission($recordId, $permissionCode) 
public function hasModulePermission($moduleId, $recordId, $permissionCode) 
public function canLogIn() 
public function setCanLogIn($canLogIn) 

TUserPermissions бы:

.ModulePermitted(ModuleID,RecordID,PermCode) 
.GroupPermitted(GroupID,PermCode) 
.ContentPermitted(RecordID,PermCode) 
.ModulePermitted(ModuleID,RecordID,PermCode) 
.CanLogIn 
+0

Я не знаком с «Т» или «.». нотации. Что это значит? – rick