简体   繁体   English

什么是更好的设计?

[英]What is a better design?

I have the following class: 我有以下课程:

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) { ... }

}

Is this becoming a "God Class?" 这会变成“神级吗?”

I am unsure whether I should split this class up. 我不确定我是否应该分开这门课。 The problem in doing so is that this class's methods are used by its domain to determine whether to show given UI elements on web pages, so there is not any behavior in the class. 这样做的问题是该类的方法被其域用于确定是否在网页上显示给定的UI元素,因此类中没有任何行为。

I suppose I could put the permission-related methods in some Permission class, making those methods static (eg. ::userIsGroupAdministrator(...), ::userIsMemberOfGroup(...) ::userHasGroupPermission(...), ::userHasContentPermission(...)) 我想我可以将权限相关的方法放在一些Permission类中,使这些方法保持静态(例如。:: userIsGroupAdministrator(...),:: userIsMemberOfGroup(...):: userHasGroupPermission(...),:: userHasContentPermission(...))

Any suggestions on how this class could be better? 关于这门课程如何更好的任何建议?

If you already have running code, then refactor in small pieces. 如果您已经运行了代码,那么重构一下就可以了。 If not I would look at the following: 如果不是,我会看以下内容:


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
}

The rest of this really belongs in a service class: 其余部分真正属于服务类:


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) { ... }
}

Yes, I think your User class is doing too much. 是的,我认为您的User类做得太多了。

Split some of the group-related functions into a Group class, and the module-related functions into a Module class. 将一些与组相关的函数拆分为一个Group类,并将与模块相关的函数拆分为一个Module类。 Or maybe split permissions into its own set of classes. 或者可能将权限拆分为自己的一组类。

Its hard to tell from method names alone. 很难从方法名称中分辨出来。 One heuristic I use to break a class up is to look at the state variables. 我用来打破课堂的一种启发式方法是查看状态变量。 Are there pieces of state that tend to be used together? 是否存在易于一起使用的州? Can they be broken out into a separate class? 他们可以分成一个单独的班级吗?

It will help if you could describe how your User object behaves, who all it interacts with, what is it's environment etc. 如果你可以描述你的User对象的行为方式,它与之交互的对象,它的环境是什么等,这将会有所帮助。

I suppose I could put the permission-related methods in some Permission class [...] 我想我可以将权限相关的方法放在一些Permission类中[...]

Yes, you can take a look at policy based design. 是的,您可以看看基于策略的设计。

I would also suggest that you take out the fixed-state of the User ie email/name etc and put it in a separate class. 我也建议你拿出的固定状态, User即电子邮件/名称等,并把它放在一个单独的类。

How difficult is it now to add new functionality or maintain existing functionality in your application? 现在添加新功能或维护应用程序中的现有功能有多难? If you're not having problems in that respect, then you're probably OK keeping things as they are (at least for awhile). 如果你在这方面没有遇到问题,那么你可能可以保持原样(至少暂时一段时间)。

Yes, your User class has some overlapping responsibilities that could potentially be refactored into a Role-based access control system. 是的,您的User类有一些重叠的职责,可能会重构为基于角色的访问控制系统。

The bottom line is: are you really gonna need it ? 底线是:你真的需要它吗?

我会考虑创建一个Permissions类,并使其成为User类的成员。

我会拆分该类的“用户”方面和“组”管理方面。

I would at least remove the setCanLogIn($canLogIn) function. 我至少会删除setCanLogIn($canLogIn)函数。 This should really be determined internally within the class based on if the user has supplied the correct credentials and has been authenticated. 这应该在类中内部确定,具体取决于用户是否提供了正确的凭据并且已经过身份验证。

Depending on how large this project is, or whether this is part of a framework will determine if more abstraction is needed. 根据此项目的大小,或者这是否是框架的一部分,将确定是否需要更多抽象。

You seem to need separate ACL and Role objects from the User object. 您似乎需要User对象中的单独ACL和Role对象。
http://en.wikipedia.org/wiki/Role-based_access_control http://en.wikipedia.org/wiki/Role-based_access_control

You can also see how it's done in ZF . 您还可以在ZF中看到它是如何完成的

For readability you might consider using __get() and __set() instead of: 为了便于阅读,您可以考虑使用__get()__set()代替:

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

It looks reasonably plausible. 看起来合情合理。 I don't know the application, of course. 当然,我不知道应用程序。 I think it might make sense to factor out a Permissions class. 我认为分解Permissions类是有意义的。

Ideally, then you'd think about what it means to have a Permissions class -- what does it know, what are its actual actions? 理想情况下,你会考虑拥有一个权限类意味着什么 - 它知道什么,它的实际行动是什么? Also, since "permissions" is plural, you might wonder if you really want a collection of individual Permission objects, but if those are effectively accessors to a simple boolean that might be overkill. 此外,由于“权限”是复数,您可能想知道您是否真的想要一个单独的Permission对象的集合,但如果它们实际上是一个可能过度的简单布尔值的访问者。

As long as the methods on the class return instance data or only modify internal state, there is nothing wrong with the class. 只要类上的方法返回实例数据或仅修改内部状态,该类就没有任何问题。

But, for eg if canLogIn() method looks for some external service (repository, membership service etc.), there is a problem of simplicity and testability. 但是,例如,如果canLogIn()方法寻找一些外部服务(存储库,成员服务等),则存在简单性和可测试性的问题。 If this is the case, you must have some service class and have those methods on it. 如果是这种情况,您必须拥有一些服务类并在其上具有这些方法。 Like 喜欢

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

It's not too bad, but I think your permissions mechanics could use factoring. 这不是太糟糕,但我认为你的权限机制可以使用因子分解。 That's a case that clearly calls for aggregation, not inheritance, as well. 这是一个明确要求聚合而不是继承的情况。 If there's a chance of non-trivial contact information being associated with the user, you might want to factor out email address as well, maybe into an Identity that can have other contact info loaded on if needed. 如果有可能将非平凡的联系信息与用户相关联,您可能还需要将电子邮件地址分解出来,也可以将其添加到可以根据需要加载其他联系信息的标识中。

In general, I could recommend thinking of your User as a central point for aggregating and composing (not inheriting) subunits of functionality -- an approach that's achieving buzzword status in game development under the rubric of 'entity system'. 一般来说,我可以建议将用户视为聚合和组合(而不是继承)功能子单元的中心点 - 这种方法在“实体系统”的标题下实现游戏开发中的流行语状态。

Leave these... they are find IMO: 离开这些...他们找到了IMO:

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

Suggest you replace these with Get/Set Name functions, which handle an instance of TUserName: 建议你用Get / Set Name函数替换它们,它们处理TUserName的一个实例:

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

TUserName would have: TUserName将具有:

.FirstName
.LastName
.MiddleName
.UserName

Suggest you replace these with Get/Set Admin functions, which handle an instance of TUserGroup: 建议你用Get / Set Admin函数替换它们,它们处理TUserGroup的一个实例:

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

TUserGroup would have: TUserGroup将拥有:

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

Suggest you replace these with Get/Set Permission functions, which handle an instance of TUserPermissions: 建议你用Get / Set Permission函数替换它们,它们处理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 would have: TUserPermissions将具有:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM