2013-12-01 4 views
0

Я читал много онлайн/офлайн о том, где поставить правила валидации и бизнес-правила в целом для управляемого доменом дизайна. Я не мог понять, каким образом сущность может предоставлять методы, которые выполняют валидацию и бизнес-правила, не прибегая к статическим методам или услугам? Это особенно важно для случаев, когда объект домена еще не нужно создавать, но нам нужно проверить значение, которое в конечном итоге будет использоваться для установки атрибута объекта.доменный дизайн зависит от статических методов?

Я заметил, что блог-сообщения, такие как http://lostechies.com/jimmybogard/2007/10/24/entity-validation-with-visitors-and-extension-methods/, основаны на специальном методе расширения .NET, который недоступен на языках программирования, таких как Java. Мне лично не нравятся статические методы, они не могут быть переопределены и трудно тестировать.

В любом случае я мог бы сделать это без статических методов или создать экземпляр ненужного объекта домена, чтобы использовать его методы проверки и бизнес-правил. Если нет, значит ли это, что проект, управляемый доменом, очень зависит от статических методов?

Благодаря

+0

Не могли бы вы опубликовать пример или два? – Hippoom

+0

Давайте просто возьмем пример регистрации сайта. – user3054039

+0

Давайте просто возьмем пример регистрации сайта электронной коммерции. Если регистрация клиента потребовала от клиента указать имя пользователя для учетной записи веб-сайта. Клиент будет уведомлен по электронной почте, если регистрация будет успешной (сведения о членах должны быть пересмотрены вместе с другой информацией, предоставленной во время шагов регистрации). Поскольку согласно DDD, объект Customer (представленный классом клиента) должен содержать метод проверки имени пользователя , как вызывать этот метод, если объект Customer не создается до тех пор, пока регистрация не будет рассмотрена? – user3054039

ответ

2

Использование ValueObjects Не Entity.

В регистрационном случае может быть введен объект значения UserName. Создайте объект Username при регистрации. Внедрить проверку в конструкторе UserName.

См. Это question и этот presentation для более подробной информации.

Edit1:
1.How обрабатывать случаи, когда различные правила проверки, применяемые для различного контекста.
Например: имя пользователя не должно содержать номера для определенного типа членов, но это необходимо для других типов участников?

Возможно, это могут быть разные методы фабрики. например UserName.forGoldenCardMember (...) или UserName.forPlainMember (...). Или введите MemberType (возможно, hierachy) для проверки UserName.

Другим альтернативным решением является использование AggregateFactory (AccountFactory в этом случае).

2.Is конструктор - единственное место, где можно поставить код проверки? Я читал онлайн о двух точках зрения: объект всегда должен быть действительным, а не всегда. Оба представляют хорошие аргументы, но любой другой подход?

Я предпочитаю действительный подход лично. Передача объекта с недопустимым значением приводит к повреждению encapsulabilty.

Edit2:
Требовать а) правила проверки бизнеса на основе контекста (различные правила пользователя для типов членов) б) держать проверки всех бизнес-правил, даже если один из них не

Палка с одноместным ответственностью с помощью Value Object (MemberType в этом случае). AggregateFactory может быть введен для упрощения прикладного уровня (более грубая гранулярность).

class AccoutFactory { 
    Account registerWith(Username username, MemberType type, ....) { 
     List<String> errors = new ArrayList<String>(); 
     errors.addAll(type.listErrorsWith(username)); 
     errors.add(//other error report... 

     if (CollectionUtils.isEmpty(errors)) { 
      return new Account(username,....); 
     } else { 
      throw new CannotRegisterAccountException(errors); 
     } 
    } 
} 

Edit3: Для вопросов в комментариях
а) Не следует ли Имя пользователя объект будет один, который имеет метод, который возвращает ошибку, как listErrorsWith()? В конце концов, это имя пользователя имеет разные правила для разных типов членов?

Мы можем проверить этот вопрос с другой точки зрения: у членов-членов есть разные правила для имени пользователя. Это может заменить if/else block в Username.listErrosWith (String, MemeberType) с полиморфизмом;

b) Если у нас есть метод в MemberType, знания не будут инкапсулированы в Username. Также мы говорим о том, чтобы убедиться, что имя пользователя всегда действительное.

Мы можем определить правильность имени пользователя без правил MemberType. Предположим, что «[email protected]» является действительным именем пользователя, он является хорошим кандидатом для члена GoldenCard, но не подходит для члена SilverCard.

c) Я все еще не вижу, как выполняется проверка, которая возвращает список ошибок, не получая список из исключения, созданного конструктором или статическим методом. Оба не выглядят идеально ИМХО.

Да, подпись listErrorsWith(): List выглядит вслепую, я бы предпочел использовать validate (имя пользователя) без возвращаемого значения (исключение throw при неудаче). Но это заставит цилтор поймать каждый шаг валидации, чтобы запустить проверки всего сразу.

+0

Я прочитал ответы на вопрос и посмотрел презентацию. Я вижу, почему вводится объект Username. Однако, несколько вопросов:
1. Как обрабатывать случаи, когда разные правила проверки применяются для разных контекстов.
Например: имя пользователя не должно содержать номера для определенного типа членов, но это необходимо для других типов участников?
2. Является ли конструктор единственным местом для размещения кода проверки? Я читал онлайн о двух точках зрения: объект всегда должен быть действительным, а не всегда. Оба представляют хорошие аргументы, но любой другой подход? – user3054039

+0

@ user3054039 обновленный ответ на вопросы в вашем комментарии. – Hippoom

+0

для 1) не означает, что фабричные методы должны быть статическими методами? Я не очень люблю статические методы, так как переопределение и тестирование сложнее. Я на самом деле думал, если мы должны передать что-то вроде ChangeEmailCommand в вопросе, который вы упомянули ранее, для конструктора. Он также содержит дополнительные параметры времени выполнения, необходимые для проверки имени пользователя рядом с именем контекста (например, тип члена). Однако, как-то странно передавать такой объект. Это одна из проблем, которые возникают у меня, когда речь идет о DDD-интерфейсе и уровне обслуживания. Может быть, вы просветили меня еще? – user3054039

1

Если вы решили использовать DDD в своем приложении, вам необходимо построить более сложное решение. Я согласен с @Hippoom, вы не должны использовать Entity для этой цели.

Я хотел бы предложить это решение:

DTO -> Service Layer (ValidationService -> Конвертер) -> Persistence Layer (Repository)

Некоторые пояснения: Когда вы получили DTO со стороны клиента с все необходимые параметры, вы должны проверить его на своем уровне обслуживания (например, использовать другую услугу, например ValidationService), которая может генерировать исключение, если что-то не так. Если все ОК, вы можете создать Entity из своего DTO в Конвертер и сохранить его в Репозиторий.

Если вы хотите гибкое решение для ValidationService я предлагаю Drools

+0

Я много читал об уровне обслуживания и объектах домена (DDD). Концептуально я согласен с подходом к объектам домена. Однако мне кажется, что DDD требует больше усилий, чем использование подхода уровня обслуживания. Обе эти сильные и слабые стороны. Я предполагаю, что это больше зависит от предпочтений групп разработчиков, которые определят, какой из них будет принят. Как вы думаете? – user3054039

+0

@ user3054039 Да, полностью зависит от вас, какой подход следует выбирать. Я считаю, что использование сервисного уровня более удобно с огромным приложением, которое должно быть гибким, обеспечивает общее решение для множества проблем и может быть переконфигурировано без создания новых двоичных файлов. – Andrew

Смежные вопросы