Подтвердить что ты не робот

Существует ли шаблон для использования 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, если я хочу получить полное представление объекта домена.

4b9b3361

Ответ 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.