Domain driven design ddd-我的ValueObject实现正确吗?

Domain driven design ddd-我的ValueObject实现正确吗?,domain-driven-design,value-objects,Domain Driven Design,Value Objects,我正在尽力创建一个web应用程序,以熟悉DDD和ValueObjects。到目前为止,一切都很顺利,我只是在问自己,我是否正确地实现了我的价值目标。以下是我的当前状态(代码从非必要部分剥离): 因此,每当我想更新我的用户密码时,我必须执行$user->credentials=$user->credentials->changePassword(“newPassword”) 这是正确的吗?我应该为我的用户类的$credentials属性创建一个getter和setter吗?我应该将changePa

我正在尽力创建一个web应用程序,以熟悉DDD和ValueObjects。到目前为止,一切都很顺利,我只是在问自己,我是否正确地实现了我的价值目标。以下是我的当前状态(代码从非必要部分剥离):

因此,每当我想更新我的用户密码时,我必须执行
$user->credentials=$user->credentials->changePassword(“newPassword”)

这是正确的吗?我应该为我的用户类的
$credentials
属性创建一个getter和setter吗?我应该将
changePassword()
方法放在用户类中吗


非常感谢您的帮助

我会说差不多。值对象的关键是它是一个值。也就是说,您可以将其与相同类型的另一个对象进行比较,并可以确定其值是否不同。在这种情况下,我希望能够看到username=x和password=x的凭证将“等于”具有相同值的另一凭证

这并不一定意味着您需要字段的getter

我在我的博客上找到了关于这个话题的有趣代码。你可以在这里找到它


值对象kata位于底部附近。希望这能有所帮助。

我想说差不多。值对象的关键是它是一个值。也就是说,您可以将其与相同类型的另一个对象进行比较,并可以确定其值是否不同。在这种情况下,我希望能够看到username=x和password=x的凭证将“等于”具有相同值的另一凭证

$user->credentials = $user->credentials->changePassword("newPassword");
这并不一定意味着您需要字段的getter

我在我的博客上找到了关于这个话题的有趣代码。你可以在这里找到它

值对象kata位于底部附近。希望有帮助

$user->credentials = $user->credentials->changePassword("newPassword");
这是正确的想法

在此实现中,$username和$password是凭据状态的一部分。你希望这种状态是不可变的;构造函数完成后,不应该有任何代码更改该状态

但是,您需要以某种方式暴露该状态;不可变的只写对象不能提供太多的业务价值。将值类型实现为不可变公共属性的集合是一种常见的习惯用法。关于如何在PHP中实现这一点的老讨论。或者,您可以实现允许凭据对象将该状态的副本传递给其他对象的调用

我应该为我的用户类的$credentials属性创建一个getter和setter吗

通常情况下,用户的实现有一个Id属性,这使它看起来像一个实体。实体很少允许其内部状态转义。特别是,setter有很多个9,几乎从来都不是一个好主意——实体的要点是它们可以强制执行自己的数据约束;他们负责确保对其状态的所有更改满足业务需求

提供对不可变状态的访问的getter不太可能导致问题;允许调用方导航到可变状态的getter令人担忧

但是:getter并不是特别有表现力——查询(可能由域服务支持)通常是更灵活的选择

比较:

password = user.password
strength = calulatatePasswordStrength(password.toString)

我应该将changePassword()方法放在User类中吗

假设您支持该用例,是的。凭证值知道如何从旧凭证计算凭证的新状态;用户实体知道如何验证当前状态的用户是否可以通过这种方式更改凭据

(示例:简单的安全实现可能会跟踪凭据上次更改的时间,并具有限制密码更改的策略,其中要使用的正确策略取决于用户的其他属性。对于凭据对象来说,这太多的工作无法单独完成。)

特别是,用户的密码实际上是凭证值对象中的一组状态,这是一个实现细节,不应该向调用用户的代码公开。换句话说,如果用户正在实现接口IUser(隔离实现细节),那么我希望IUser承诺可以使用changePassword($password)方法

这是正确的想法

在此实现中,$username和$password是凭据状态的一部分。你希望这种状态是不可变的;构造函数完成后,不应该有任何代码更改该状态

但是,您需要以某种方式暴露该状态;不可变的只写对象不能提供太多的业务价值。将值类型实现为不可变公共属性的集合是一种常见的习惯用法。关于如何在PHP中实现这一点的老讨论。或者,您可以实现允许凭据对象将该状态的副本传递给其他对象的调用

我应该为我的用户类的$credentials属性创建一个getter和setter吗

通常情况下,用户的实现有一个Id属性,这使它看起来像一个实体。实体很少允许其内部状态转义。特别是,setter有很多个9,几乎从来都不是一个好主意——实体的要点是它们可以强制执行自己的数据约束;他们负责确保对其状态的所有更改满足业务需求

提供对不可变状态的访问的getter不太可能导致问题;允许调用方导航到可变状态的getter令人担忧

但是:getter并不是特别有表现力——查询(可能由域服务支持)通常是更灵活的选择

比较:

password = user.password
strength = calulatatePasswordStrength(password.toString)

我应该将changePassword()方法放在User类中吗

假设您支持该用例,是的。凭据值知道如何计算新的sta
strength = user.passwordStrength(calculator)