DDD - Совокупность - Следует ли действительно избегать добытчиков? - PullRequest
0 голосов
/ 03 февраля 2019

Доброе утро,

Я много раз читал, что в AR следует избегать как сеттеров, так и геттеров.Хотя я могу понять причину сеттеров, я немного не согласен с геттерами, когда они явно являются частью бизнеса.

Давайте представим следующее Пользователь 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;
    ...
}

По сути, у меня есть несколько искателей, которые позволяют получить User с помощьюего идентификатор, имя пользователя или адрес электронной почты.

Теперь давайте представим следующую в памяти реализацию этого 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 голосов
/ 03 февраля 2019

Геттер в порядке.Случай «не писать геттеры» состоит в том, чтобы не раскрывать внутреннее состояние вне агрегата: когда ваши сервисы берут агрегат, извлекают его состояние и принимают какое-то решение на основе этого.Это то, чего вы хотите избежать.

Вы можете следовать указаниям Закона Деметры и стремиться к этому.Строго не избегайте добытчиков, но помните о них.

Наличие getId или getUsername совершенно нормально.Наличие getCollection вида метода, который возвращает изменяемую коллекцию, отсутствует.Агрегат теряет контроль над внутренними деталями, деталями реализации.Когда вы предоставляете что-то вроде getFriends(), ваши сервисы могут вызывать это, добавлять или удалять вещи вне агрегата, и вы в основном теряете способность реорганизовать агрегат, не нарушая ничего.addFriend() и deleteFriend() в этом случае решат это.И если getFriends() возвращает неизменяемую коллекцию, это тоже хорошо.

Не пишите получатели не является жестким правилом, старайтесь не показывать слишком многосостояние вне совокупности, но не излишне усложняйте свою жизнь, не имея каких-либо добытчиков вообще.Используйте их, если это имеет смысл.

...