#spring #spring-mvc #domain-driven-design #immutability
#spring #spring-mvc #дизайн, управляемый доменом #неизменность
Вопрос:
У меня есть несколько тщательно протестированных и тщательно обработанных классов моделей DDD, с окончательными неизменяемыми инвариантами и проверками целостности. Создание экземпляра объекта происходит с помощью соответствующих конструкторов, статических фабричных методов и даже с помощью конструкторов.
Теперь я должен предоставить форму Spring MVC для создания новых экземпляров некоторых классов.
Мне кажется (я не эксперт), что я должен предоставить пустые конструкторы и установщики атрибутов для всех вспомогательных классов формы, которые я хочу привязать.
Итак, что мне делать?
Создание анемичных объектов, предназначенных для поддержки формы, и передача информации в мою модель предметной области (так много для принципа DRY …) вызывает соответствующие методы / конструктор?
Или есть механизмы, которые я пропустил, которые могут спасти мой день? 🙂
Заранее благодарю вас за вашу мудрость!
Ответ №1:
Объекты, которые используются для привязки к слоям представления, обычно называются моделями представления, и они представляют собой DTO, предназначенные для отображения данных, отображаемых из объектов домена, а затем отображения пользовательского ввода обратно в объекты домена. Модели представления обычно выглядят очень похожими на объекты домена, которые они представляют, однако есть некоторые важные различия:
-
Данные из объектов домена могут быть сглажены или иным образом преобразованы в соответствии с требованиями данного представления. Управление отображением в простых объектах проще, чем отображениями в среде представления, такой как MVC. Так проще отлаживать и обнаруживать ошибки.
-
Для данного представления могут потребоваться данные из нескольких объектов домена — может не быть ни одного объекта домена, который соответствует требованиям представления. Модель представления может быть заполнена несколькими объектами домена.
-
Модель представления обычно разрабатывается с учетом конкретной среды представления и, как таковая, может использовать атрибуты, специфичные для среды, для привязки и проверки на стороне клиента. Как вы заявили, типичным требованием является конструктор без параметров, который подходит для модели представления. Опять же, гораздо проще тестировать и управлять моделью представления, чем каким-то сложным механизмом отображения.
Модели представлений, по-видимому, нарушают принцип DRY, однако после более пристального взгляда ответственность модели представления отличается, поэтому с учетом принципа единой ответственности целесообразно иметь два класса. Кроме того, взгляните на эту статью, в которой обсуждается ошибка повторного использования, часто приводящая к принципу DRY.
Кроме того, модели представлений действительно анемичны, хотя у них может быть конструктор, принимающий объект домена в качестве параметра, и метод для создания и обновления объекта домена с использованием значений в модели представления в качестве входных данных. По опыту я нахожу, что хорошей практикой является создание класса модели представления для каждого объекта домена, который будет отображаться на уровне представления. Управлять двойной иерархией классов объектов домена и моделей представлений проще, чем управлять сложными механизмами отображения.
Также обратите внимание, что существуют библиотеки, которые пытаются упростить сопоставление между моделями представлений и объектами домена, например AutoMapper для .NET Framework.
Комментарии:
1. Хотя я не слишком забочусь о DRY, мне также не нравятся ненужные слои, и было бы неплохо, если бы я мог привязываться к объекту домена, когда объект достаточно хорошо напоминает структуру представления. Даже для умеренно сложных сценариев неплохо отделить модели представления от объектов домена, но для очень простых сценариев («FirstName», «MiddleName», «LastName» с очень простым объектом Name, доступным в домене) наличие дополнительного класса модели представления просто кажется расточительной работой / шаблоном. К сожалению, я не вижу особой альтернативы.
Ответ №2:
Да, вам нужно будет создать объекты, чтобы форма принимала все входные данные, и обновить вашу модель с помощью этих объектов за одну операцию.
Но я не буду называть эти объекты анемичными (особенно, если вы выполняете DDD). Эти объекты представляют собой одну единицу работы. Так что это тоже концепции домена!
Ответ №3:
Я решил это, создав интерфейс DTO:
public interface DTO<T> {
T getDomainObject();
void loadFromDomainObject(T domainObject);
}
public class PersonDTO implements DTO<Person> {
private String firstName;
private String lastName;
public PersonDTO() {
super();
}
// setters, getters ...
@Override
public Person getDomainObject() {
return new Person(firstName, lastName);
}
@Override
public void loadFromDomainObject(Person person) {
this.firstName = person.getFirstName();
this.lastName = person.getLastName();
}
// validation methods, view formatting methods, etc
}
Это также предотвращает утечку информации о проверке представления и форматировании в модель домена. Мне действительно не нравится наличие специфичных для Spring (или других специфичных для фреймворка) аннотаций (@Value и т. Д.) И аннотаций javax.validation в объектах моего домена.