如果我有一个User
类,并且可以通过在suspensions
表中添加一个条目来暂停其帐户,那么您认为哪个类/方法签名更合适?
User::suspend($reason, $expiryDate);
Suspension::add($userid, $reason, $expiryDate);
这是一个简单的例子,但我在整个应用程序中到处都有这种情况。一方面,我想让它成为User对象的一个方法,因为执行的动作与该用户对象本身直接相关,但另一方面使它成为暂停对象上的方法似乎更清晰。 / p>
您怎么看?
答案 0 :(得分:10)
您暂停用户。
User.Suspend()
在User.Suspend
方法中,您实际上可以将它们添加到“暂停”表中,或者调用暂停对象。这将导致更清晰的界面,因为你所要做的就是调用一种方法。
答案 1 :(得分:3)
它绝对取决于你。 OO设计非常主观。在这里,它取决于您是将暂停视为名词(暂停)还是动词(暂停)。如果是前者,它很可能成为具有适当方法和属性的自己的对象。如果是后者,它将成为User对象的一组相关方法和属性。
这带来了另一个问题:你是一个极简主义者吗?有些人试图保留许多轻型课程而不是一些重型课程。
就个人而言,我认为凝聚力/耦合超过所有这些因素的数量级。基本上,对我来说,它取决于其他系统实体是否需要知道暂停而没有用户对象进行查询。如果是这样,那么Suspension类就会诞生。如果没有,我会将其作为User类的一部分。
答案 2 :(得分:2)
如果添加暂停是唯一真正的操作,我会选择第一个选项并将其作为User类执行的操作。
但是,如果您打算为Suspensions创建更多功能,我会考虑创建一个类:
class SuspensionManager
suspendUser(....)
getSuspendedUser(...)
....
答案 3 :(得分:2)
*鉴于我不知道您的整个代码库/意图
,这是我的意见是100%有争议的我不会说。但这实际上取决于你如何看待OOAD。我认为User和Suspension类都有一个目的。 User类具有保存与User(用户表)直接关联的信息的责任,而Suspension类负责保存与Suspension(暂停表)直接关联的信息。我建议创建一个负责暂停用户的UserSuspention类。
这种OOAD方法与 SOLID 设计原则有关。让User或Suspension类负责暂停用户将违反 SRP(单一责任主体) ......因为每个类已经负责维护各自表中的信息。
您的潜在API可能如下所示:
public class UserSuspension
{
public void SuspendUser(User user, Suspension suspension) { ... }
public void SuspendUser(Guid userId, string reason, DateTime expiryDate) { ... }
}
答案 4 :(得分:1)
根据这两个选项,我会投票给Suspension::add()
,如果实际上此调用将一个条目添加到暂停表。这样代码中的这个调用就代码本身而言(即不是代码所代表的概念)的影响很明显:如果我看到代码User::suspend()
,我希望它能够修改用户对象的"suspended"
标志,不修改其他对象中的其他内容。
另一方面,在这个特定的例子中,我认为User::suspend()
一般来说更清楚,所以如果它意味着为该用户设置suspended
标志,我会投票支持它对象,或者它是否会从接口看起来如此,即如果您不必关心暂停存储的位置,因为User
类的接口会使其看起来像如果它是它的一个属性。
答案 5 :(得分:0)
这种情况在Web应用程序设计中非常典型。将对象作为断开连接的实体处理通常变得更容易,因为它使您不必检索对象来执行您不需要该对象的操作。
前者比OOP意义更好,问题是这对性能的影响是否会打扰你:
User user = GetUser($userId); // unnecessary database hit?
user.suspend(reason, expiryDate);
答案 6 :(得分:0)
我倾向于有Account
关联User
和Suspension
答案 7 :(得分:0)
取决于。
这可能是不是肯定正确答案的情况之一。这取决于数据在系统中的移动方式,以及在以数据为中心或以用户为中心的模型中查看此关系是否更有利。
当您尝试对事物进行建模时,一个古老的经验法则是将对象视为名词,将方法视为动词。这通常表示用户是对象,暂停是您可能执行的操作。
简单吗? 不是。
其他人可能会争辩说将暂停描述为“AccountAction”以及将暂停作为动词应用更为有意义。这可能会引导您进入一个模型,其中 AccountAction 的各个子类都有一个 applyTo 方法,该方法可以作用于其他对象类型。
您可能需要将对象应用于现有数据库模式,在这种情况下,您必须考虑您的持久层或ORM如何与现有记录结构进行交互。
有时这取决于技术。 OO可以在不同语言系列中以微妙的不同方式实现,这也可以影响设计。有些系统支持更实体的继承图,其他语言则强调更松散地互连的对象,传递信息。
您需要根据自己想要与数据和州进行互动的方式来考虑您的设计。如果您考虑对象,作为类的实例,表示数据状态,以及您希望调用的行为,您可能会发现名词和动词模式不在用于描述系统的句子中。
答案 8 :(得分:0)
正如其他人所说,这是非常主观的。
就个人而言,我更喜欢User :: suspend()替代方案,因为它允许我随时实现(或更改实现)暂停。它将所有挂起逻辑隐藏在用户界面后面。
答案 9 :(得分:0)
我经常在同样的问题上挣扎,我所做的就是问自己这是否在编程世界之外有意义。在现实生活中,你会问一个用户暂停他/她自己吗?您会要求贷款申请批准吗?如果答案是否定的,那么需要一个专门的权限/组件/服务来处理这个和类似的场景。在申请贷款的情况下,批准最好是贷款审批服务或贷款专家的一部分。如果在您的情况下,要求用户暂停自己在您正在建模的域中有意义,那么它应该属于用户。如果没有,那么处理用户帐户暂停和类似用户帐户级服务的服务可能是更好的地方。