Доменные объекты в DDD являются «самопроверяющимися».Другими словами, клиентский код не может нарушать правила домена, поскольку объекты применяют свои внутренние инварианты.Например:
public class Invoice {
private Money _amount;
private InvoiceState _state;
public void ChangeAmount(Money newAmount) {
if(_state == State.Booked) {
throw new InvalidOperationException(
"Unable to change amount for booked invoice.");
}
_amount = newAmount;
}
// Methods like this can be used by external code (UI) to check business
// rules upfront, to avoid InvalidOperationException.
public Boolean CanChangeAmount() {
if(_state == State.Booked) {
return false;
}
return true;
}
}
Еще один пример из Образец DDD :
public HandlingEvent(final Cargo cargo,
final Date completionTime,
final Date registrationTime,
final Type type,
final Location location,
final Voyage voyage) {
...
if (type.prohibitsVoyage()) {
throw new IllegalArgumentException(
"Voyage is not allowed with event type " + type);
}
Никогда не позволяйте своей структуре пользовательского интерфейса обрабатывать объект домена как контейнер данных.К сожалению, это поощряется множеством примеров в Интернете и акцентом C # на геттеры и сеттеры.Если вы измените состояние объекта без применения бизнес-правил, вы в конечном итоге получите «поврежденные» объекты.Это особенно верно для NHibernate, потому что его Сессия «запоминает» все объекты и с радостью сбросит их в базу данных при следующем коммите или сбросе.Но это всего лишь техническая составляющая, главная причина в том, что вам нужно иметь возможность рассуждать о бизнес-правилах, связанных со счетами, просто взглянув на класс Invoice.Также обратите внимание, что код должен быть основан на Ubiquitous Language .Вы должны видеть такие слова, как «Счет-фактура», «Забронировано», «Сумма», вместо общих «Поле», «Свойство», «Валидатор».
ОБНОВЛЕНИЕ: empi, спасибо за решение вашей проблемы.Возможно, вы захотите открыть новый вопрос.Это цитата с моим акцентом
Как я сказал в одном из моих комментариев - этот вопрос является частью более серьезной проблемы, с которой я сталкиваюсь.Я ищу стандартный способ определения логики и ограничений домена только в домене, а затем перевести его на графический интерфейс и другие уровни.Я не вижу какой-либо общей модели для следующего очень распространенного требования: домен заявляет, что поле не может быть отредактировано, и это правило автоматически преобразуется в графическую логику , которая отключает поле и делает его доступным только для чтения.Я ищу образец решения в стеке MVC.Мне кажется, что я заново изобретаю колесо, и большинство разработчиков просто сдаются и дублируют логику в графическом интерфейсе
Я думаю, что вы ищете способ указать все в домене, а затем «сгенерировать» пользовательский интерфейс.Что-то вроде Голые объекты для MVC ?Я никогда не использовал этот подход, но сомневаюсь, что сгенерированный пользовательский интерфейс когда-нибудь выиграет конкурс красоты или удобства использования.На мой взгляд, в пользовательском интерфейсе всегда будет некоторая «перестройка» бизнес-логики.Некоторые доменные инварианты слишком сложны, включают в себя несколько полей, требуют репозитория и, возможно, даже внешних сервисов.Я не уверен, что можно автоматически генерировать высококачественный пользовательский интерфейс.Я думаю, что попытки сделать это могут начать сгибать вашу модель для соответствия инфраструктуре пользовательского интерфейса.