Php DDD-聚合-是否应该真正避免使用getter?

Php DDD-聚合-是否应该真正避免使用getter?,php,domain-driven-design,aggregate,getter,ddd-repositories,Php,Domain Driven Design,Aggregate,Getter,Ddd Repositories,早上好 我已经读过很多次,在AR中应该避免使用二传手和接受者。虽然我可以理解二传手的原因,但对于接受者,我有点不同意,因为它们显然是业务的一部分 让我们想象一下以下用户AR: 名称空间供应商\域\模型; 类用户 { 私有$userId; 私有$username; 私人$password; 私人电子邮件; 静态公共寄存器(…):用户{…}//通用语言 公共函数注销(…){…}//通用语言 公共函数changePassword(…){…}//通用语言 公共函数changeMail(…){…}//通用

早上好

我已经读过很多次,在AR中应该避免使用二传手和接受者。虽然我可以理解二传手的原因,但对于接受者,我有点不同意,因为它们显然是业务的一部分

让我们想象一下以下用户AR:

名称空间供应商\域\模型;
类用户
{
私有$userId;
私有$username;
私人$password;
私人电子邮件;
静态公共寄存器(…):用户{…}//通用语言
公共函数注销(…){…}//通用语言
公共函数changePassword(…){…}//通用语言
公共函数changeMail(…){…}//通用语言
公共函数getAggregateId():UserId{…}//A getter
公共函数getUsername():用户名{…}//A getter
公共函数getEmail():UserEmail{…}//A getter
...
}
现在让我们想象一下下面的用户存储库界面:

名称空间供应商\域;
接口用户存储库
{
公共函数userOfId(UserId$UserId):?用户;
公共函数userOfname(UserName$UserName):?用户;
公用函数userOfEmail(UserEmail$UserEmail):?用户;
...
}
基本上在这里,我有一些查找工具,可以通过ID、用户名或电子邮件地址检索用户

现在,让我们想象一下该用户存储库的内存中的实现:

名称空间供应商\基础设施\持久性;
使用供应商\域\用户存储库;
类InMemoryUserRepository实现UserRepository
{
/**用户[]*/
私人用户;
公共函数userOfId(UserId$UserId):?用户
{
如果(!isset($this->users[$userId->tostring()){
返回null;
}
$this->users[$userId->tostring()];
}
公用函数userOfEmail(UserEmail$UserEmail):?用户
{
foreach($users作为$user){
如果($user->getEmail()->sameValueAs($userEmail){
返回$user;
}
}
返回null;
}
...
}

如您所见,在内存中的实现中,我需要通过电子邮件过滤用户,访问他们的电子邮件属性。这必然意味着用户AR需要提供getEmail()getter。这真的很糟糕吗?允许对必须访问的属性使用getter?我是否应该简单地考虑一下getEmail()getter具有商业意义,在这种情况下,它是完全有效的?

getter很好。“不要写getter”的情况避免将内部状态暴露在聚合之外:当您的服务获取聚合时,获取其状态,并基于此做出一些决策。这就是您想要避免的

你可以遵循得墨忒尔定律的指导方针,并以此为目标。不要严格地回避getter,但要注意它们

拥有
getId
getUsername
是非常好的。 拥有一个
getCollection
-返回可变集合的方法不是。聚合将失去对内部细节、实现细节的控制。当您公开类似
getFriends()的内容时
,您的服务可以调用它,添加或删除聚合之外的内容,而您基本上失去了在不破坏所有内容的情况下重构聚合的能力。在这种情况下,使用
addFriend()
deleteFriend()
可以解决问题。如果
getFriends()
返回不可变的集合,也可以


不要编写getter不是一条硬性规定,尽量不要在聚合之外暴露太多状态,但不要因为根本没有getter而不必要地使你的生活复杂化。如果有意义,就使用它们。

正是我的意思。我只是想确定一下。谢谢你的贡献。非常感谢。@Federkun,所以当我有发票时gregate,那有一个LineItemsCollection,我有一个InvoiceCalculator服务,我该如何实现呢?计算器需要从集合项目中读取数据,以便能够计算净值、总额和增值税,可能还有其他税费。还有,你将如何更新发票上的价格?我考虑过做invoice::Calculation(Calculator$Calculator)并使用calculators Calculator方法读取发票实例。听起来不错吗?