Существует ли шаблон для использования DTO без дублирования свойств объекта домена?
Я бы хотел использовать DTO в моих моделях взглядов вместо моих объектов домена, однако мне тяжело оправдывать расходы на обслуживание, связанные с необходимостью поддерживать два набора свойств для каждого объекта домена.
Мне было интересно, если кто-либо реализовал или знает шаблон, в котором свойства объекта домена отделены от действий объекта без необходимости поддерживать два набора свойств.
Я думал, что мой объект домена будет только свойствами и добавит действия в качестве подкласса:
public class Person{
private String firstName;
private String lastName;
public String getFirstName(){
return this.firstName;
}
public String setFirstName(string firstName){
this.firstName = firstName;
}
...
}
public class PersonActions extends Person{
public void save(){
...
}
public Person get(){
}
}
Этот способ по-прежнему кажется немного клочковым, поскольку мне нужно будет пройти класс PersonAction, если я хочу получить полное представление объекта домена.
Ответы
Ответ 1
Вы можете использовать интерфейс, отображающий только ваши данные объекта, без каких-либо методов домена. Вам все равно нужно поддерживать два класса, но это было бы намного проще, поскольку большинство изменений можно было бы реорганизовать с помощью вашей среды IDE (например, Eclipse). Вот пример:
public interface PersonView {
String getFirstName();
String setFirstName();
}
public void Person implements PersonView {
private String firstName;
@Override // This annotation guarantees the interface is correct
public String getFirstName() {
return firstName;
}
...domain methods...
}
Не идеальное решение, но оно довольно чистое.
Что касается самой проблемы, то я для одного не против, не подвергая весь объект слою представления. ИМХО, я не думаю, что скрывать некоторые методы стоит накладных расходов. У команды должна быть дисциплина, чтобы использовать объекты с умом, но это только мое мнение.
Ответ 2
Вот еще одна идея:
Используйте объект домена и только аннотируйте методы, которые вы хотите открыть. Вы можете сделать это так, чтобы они требовали явного изложения с помощью типа Квалификационного доступа как NONE, так что у вас нет случайной экспозиции данных.
Пример:
@Entity // hibernate
@XmlAccessorType(XmlAccessType.NONE) // for DTO
@XmlRootElement
public class Survey {
@Column(name = "Title") // hibernate
@Basic // hibernate
@XmlElement // for use as DTO
private String title;
@XmlElement(name = "report")
public SurveyReport getSurveyReport() {
// ... do some stuff here
}
}
Используя этот подход, вы получаете лучшее из обоих миров. Кроме того, вы можете разоблачить "мета" информацию с помощью методов, а затем аннотировать метод (доступный из-за XmlAccessType.NONE).
Самые большие недостатки, которые я вижу:
-
Взрыв аннотации, приводящий к сложному поддержанию кода
-
Монолитный объект со многими методами
- Что может быть полезно для просмотра, но не подходит для внутреннего кода.
- Превращение в путаницу API
- см. # 1
-
В конце дня вы не сможете представить представление, которое хотите, без объединения информации из нескольких доменных объектов; оставляя вас прямо назад, нуждаясь в явном DTO в любом случае
Ответ 3
Просто сделайте свою модель (Person
) свойством вашего контроллера (PersonActions
):
public class PersonActions {
private Person person;
public PersonActions() {
person = new Person(); // Or get existing one from DAO in case of edit.
}
public void save() {
somePersonDAO.save(person);
}
public Person getPerson() {
return person;
}
}
Основываясь на истории вопроса, я понимаю, что вы используете Struts. В этом случае хорошо знать, что JSP EL поддерживает вложенные свойства объекта, что-то вроде этого, чтобы получить значения:
${personActions.person.firstName}
${personActions.person.lastName}
Нет необходимости сглаживать их, дублируя свойства в контроллере.
Ответ 4
Один из подходов состоит в том, чтобы иметь свойство в вашей модели просмотра, которое является вашим объектом DTO.
Другим подходом является дублирование свойств, но для сопоставления между объектами используйте что-то похожее на AutoMapper.
В нашем последнем проекте у нас есть объект DTO как свойство, но мы также раскрываем индивидуальные свойства в Model View, которые ссылаются на свойства объекта DTO.