Как смоделировать доменную сущность в коде? - PullRequest
0 голосов
/ 10 мая 2018

Я знаком с DDD и концепцией Entity.

Согласно DDD, сущность - это объект, фундаментально определяемый своей идентичностью.

Скажем, в моем проекте я определил, что Account - это сущность. Таким образом, в коде это будет представлено классом с полем идентификатора, что-то вроде

class Account { 
  private Id id
  private AccountStatus status
  ...
}

Поскольку это сущность, все ее поля могут меняться в течение времени жизни, кроме Id.

Мой вопрос: как лучше всего смоделировать это в коде с точки зрения изменения состояния и равенства объектов.

  • Изменение состояния

Поскольку состояние объекта со временем меняется, должен ли класс моделироваться как изменяемый класс или он должен быть неизменным с новой ссылкой, создаваемой при каждом изменении состояния?

  • Равенство

Поскольку Account определяется исключительно на основе его Id, должен ли метод equals сравнивать только идентификатор объекта? Каковы потенциальные проблемы с учетом всех ИЛИ без полей.

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Я бы посоветовал вам ознакомиться с моделью эпохи времени Clojure. Доклад Стюарта Хэллоуэя 2010 года Восприятие и действие описывает модель эпохального времени .

Identities are successions of immutable states

Сущность в некотором смысле является изменяемой ссылкой на неизменное состояние .

В объектно-ориентированном стиле мы можем сделать что-то вроде

Entity {
    MutableRef<State> mutableRef;

    void change (...) {
        State current = mutableRef.get()
        State next = someFunction(current, ...)
        mutableRef.set(next)
    }
}

(Обычно мы этого не делаем, потому что в Java-линии ОО распространенной практикой является манипулирование изменяемыми значениями).

Мой вопрос: как лучше всего смоделировать это в коде? Я вижу два подхода,

  • Поскольку это объект, концептуально все его поля могут изменяться, поэтому модель должна поддерживать мутацию (сеттеры) и равенство, определенные только в поле Id.

  • Смоделируйте это как объект значения, то есть неизменяемые, конечные поля, равенство, определенное по всем полям и при мутации, создайте и верните новый объект.

Если на языке вашей компании вы описываете учетную запись как вещь, которая со временем меняется, вы, вероятно, захотите использовать модель сущности.

Это не обязательно означает "сеттеры"; более распространенным стилем является то, что мутаторы должны быть написаны на языке бизнеса. Мы говорим субъекту, что делать

account.close()

и задача организации понять, как это действие влияет на базовую структуру данных.

Что касается личности, вот более свежее замечание Эванс :

Я пришел к выводу, что у сущности даже не должно быть операции равенства

Видеоклип, похоже, взят из модуля курса Pluralsight 2014 года Основы проектирования на основе доменов , авторы Джули Лерман и Стив Смит.

0 голосов
/ 10 мая 2018

Обычно сущности и объекты ValueObject являются взаимоисключающими понятиями для данного случая.Различные домены также по-разному заботятся о разных концепциях, и одним из таких понятий может быть ValueObject в данном Домене и сущность в другом данном Домене.

Одним из таких примеров является Деньги как концепция.Для контекста электронной коммерции Money, вероятно, является ValueObject, поскольку домен будет заботиться только о своей стоимости, а не о своей постоянной идентичности (для такой системы 2 экземпляра по 10 долларов США будут одинаковыми, и вам не нужно будет называть их отдельно).,

Для Федерального банка (или какой-либо другой организации, которая печатает деньги) относится к деньгам совершенно по-другому.Этот Домен фактически маркирует отдельные счета серийными номерами и очень заботится об истории каждого отдельного счета (когда он был напечатан, какая была модель, возможно, также, где он был напечатан).Таким образом, этот домен, вероятно, будет моделировать Деньги как сущность.

Эти различия также влияют на то, как обрабатывается равенство.

Для объекта ValueObject равенство обычно определяется в «2 экземплярах, имеющих одинаковое значение», поэтому вам, вероятно, лучше сопоставить каждое поле значения, чтобы установить равенство.Экземпляр Money «10 USD» равен другому экземпляру Money «10 USD», но он отличается от экземпляра Money «10 EUR» (их свойство FaceValue такое же, но их валюта не совпадает, поэтому их нельзя использоватьвзаимозаменяемо).

Теперь для сущности вы заботитесь об идентичности данного экземпляра в течение всего его жизненного цикла (как концепции, а не как экземпляра).Таким образом, если у вас есть экземпляр Money с серийным номером 1234 и свойствами «10 / USD / NearMint», и он становится поврежденным, он меняет и сохраняет свой серийный номер 1234, но его свойства обновляются до «10 / USD / Stained».Это все тот же счет, и для всех учетных записей он должен реагировать на средства сравнения равенства как true.

Чтобы закончить этот длинный ответ, часть «setter» также зависит от домена.Обычно ValueObjects не должны изменять свои внутренние состояния.Но сущности должны изменять свои внутренние состояния только на основании правил домена.В примере с деньгами, вероятно, нет абсолютно никакого смысла иметь возможность выбирать FaceValue или валюту данного векселя, даже если он является сущностью.Однако его состояние NearMint -> Stained -> Damaged -> etc, вероятно, со временем может измениться.Кроме того, вам, вероятно, следует подумать о том, чтобы не использовать всегда прямые установщики и вместо этого создавать доменные осмысленные методы в ваших сущностях, чтобы лучше выразить вездесущий язык при обработке переходов состояний.

...