DDD-汇总-是否应避免使用吸气剂?

时间:2019-02-03 18:39:47

标签: php domain-driven-design aggregate getter ddd-repositories

早上好

我已经读过很多次了,在AR中应该避免使用setter和getter。虽然我可以理解安装者的原因,但对于那些明显属于企业的吸气剂,我有些不同意。

让我们想象以下 User AR:

namespace vendor\Domain\Model;

class User
{
    private $userId;
    private $username;
    private $password;
    private $email;

    static public register(...): User { ... } // Ubiquitous Language
    public function unregister(...) { ... } // Ubiquitous Language
    public function changePassword(...) { ... } // Ubiquitous Language
    public function changeEmail(...) { ... } // Ubiquitous Language
    public function getAggregateId(): UserId { ... } // A getter
    public function getUsername(): UserName { ... } // A getter
    public function getEmail(): UserEmail { ... } // A getter
    ...
}

现在让我们想象以下 UserRepository 界面:

namespace vendor\Domain;

interface UserRepository
{
    public function userOfId(UserId $userId):? User;
    public function userOfname(UserName $userName):? User;
    public function userOfEmail(UserEmail $userEmail):? User;
    ...
}

基本上在这里,我有一些查找器,通过它的ID,用户名或电子邮件地址可以检索用户

现在,让我们想象一下该 UserRepository 的以下内存中实现:

namespace vendor\Infrastructure\Persistence;

use vendor\Domain\UserRepository;

class InMemoryUserRepository implements UserRepository
{
    /** User[] */
    private $users;

    public function userOfId(UserId $userId):? User
    {
        if(!isset($this->users[$userId->tostring()]) {
            return null;
        }

        $this->users[$userId->tostring()];
    }

    public function userOfEmail(UserEmail $userEmail):? User
    {
        foreach($users as $user) {
            if($user->getEmail()->sameValueAs($userEmail) {
                return $user;
            }
        }

        return null;
    }
    ...
}

如您所见,在该内存实现中,我需要通过电子邮件过滤用户,并访问其电子邮件属性。这必然意味着用户 AR需要提供 getEmail() getter。真的不好吗?允许具有必须访问的属性的吸气剂?我是否应该简单地认为 getEmail()吸气剂具有商业意义,在这种情况下,它是完全有效的吗?

1 个答案:

答案 0 :(得分:2)

凯特很好。 “不要写吸气剂”的情况是为了避免将内部状态暴露在聚合之外:当您的服务采用聚合时,获取其状态并基于此做出一些决定。那就是你要避免的事情。

您可以遵循Demeter法则的指南,并为此而努力。不要严格避免使用吸气剂,但要注意它们。

拥有getIdgetUsername很好。 没有getCollection类方法可返回可变集合。总体上失去了对内部细节,实施细节的控制。当暴露类似getFriends()之类的东西时,您的服务可以调用它,在聚合之外添加或删除东西,并且您基本上失去了重构聚合而不破坏所有内容的能力。在这种情况下,addFriend()deleteFriend()可以解决。而且,如果getFriends()返回一个不可变集合,那也很好。

不要写吸气剂并不是硬性规定,不要在集合之外暴露过多的状态,但是不要因没有任何吸气剂。合理使用它们。