Должен ли я создавать интерфейсы для объектов передачи данных?

19

Это хорошая идея или плохая идея создать интерфейс для объектов передачи данных? Предполагая, что объект обычно изменчив.

Хотя мой пример на Java, он должен быть применим к любому другому языку с похожими понятиями.

interface DataTransferObject  {
    String getName();
    void setName(String name);
}

class RealDataTransferObject  implements DataTransferObject {

    String name;
    String getName() {
        return name;
    } 
    void setName(String name) {
        this.name = name;
    }
}

Конечно, это упрощенный пример, в реальной жизни может быть больше полей.

Архимед Траяно
источник

Ответы:

24

Общий ответ - нет , потому что вы никогда не должны добавлять код, не имея конкретной, конкретной причины для этого, и нет общей причины для такого интерфейса.

Это, как говорится, иногда может быть веская причина. Но во всех случаях, которые я видел, эти интерфейсы были частичными, охватывающими только одно или несколько свойств, совместно используемых несколькими классами, которые я хотел использовать полиморфно, не давая им общего суперкласса. Типичные кандидаты - это Idсвойство для использования в каком-либо реестре или Nameсвойство для отображения пользователю. Но это может быть полезно в любом случае, когда вы хотите, чтобы некоторый код обрабатывал все, что имеет X - просто создайте XSourceинтерфейс, который содержит getX(и, только если требуется, setX) методы.

Но отдельный интерфейс для каждого модельного класса, содержащий все свойства? Я не могу представить себе вескую причину сделать это. Плохая причина - плохо спроектированная структура, которая требует этого; Entity EJB сделали именно это, если я правильно помню. К счастью, они были настолько плохи, что никогда не набирали обороты и устарели с EJB 3.0

Примечание: пожалуйста, избегайте использования термина «объект-значение» для описания Java-бинов только с тривиальными геттерами и сеттерами - это конфликтует с более распространенным определением объекта-значения как объекта без идентичности, который обычно неизменен. Лучшим термином будет DTO или класс модели - хотя в последнем случае обратите внимание, что модели анемичных доменов считаются антипаттернами.

Майкл Боргвардт
источник
3
«Модели анемичных доменов считаются антипаттернами» - Мартин Фаулер, который в PEAA признает, что он знает людей, которые работали таким образом десятилетиями, «очень успешно». Таким образом, я предлагаю меньше анти-паттерна и больше-не-как-Фаулер любит работать. Тем не менее, хороший ответ +1.
фунтовые
4
@pdr: Фаулер, возможно, придумал этот термин, но он ни в коем случае не единственный, кто считает их антипаттернами. Я не думаю, что кто-то, кто действительно понимает ОО, считает, что было бы неплохо не допускать предметно-ориентированную логику вне доменной модели.
Майкл Боргвардт
Спасибо за исправление термина, DTO было словом, которое я искал прошлой ночью, но не мог вспомнить для меня. Меняя название, все стало более разумным в дизайне.
Архимед Траяно
@pdr Я думаю, что лучший способ сказать, что это антипаттерн в контексте ОО-программирования. Есть много других парадигм, где это совершенно нормально, и вы могли бы даже успешно работать таким образом на языке OO (он просто не был бы особенно объектно-ориентированным).
Даниэль Б
3
@MichaelBorgwardt: согласен, он не одинок в этом. Но не люди, которые не согласны. Если бы вы сказали, что «анемичные доменные модели рассматриваются некоторыми как анти-паттерн», я бы ничего не сказал. Честно говоря, я думаю, что весь ваш ответ был бы лучше без последнего абзаца в любом случае. Первая половина сделала бы лучший комментарий; вторая половина ничего не предлагает к этому вопросу.
фунтовые
2

Создание интерфейса - это нормально, но НЕ так, как работает ваш пример. Вы должны удалить сеттер из интерфейса, и все будет в порядке:

interface ValueObject {
  String getName();
};

Это позволяет использовать много разных реализаций, например, имя можно получить из базы данных ... Сеттер должен находиться в другом интерфейсе.

ТР1
источник
2

Интерфейсы определяют контракт между классами, реализующими интерфейсы, и их клиентами. Они используются в качестве механизма абстракции, так что клиенты могут манипулировать «вещами, имеющими заданное поведение».

Таким образом, общий ответ на вопрос "должен ли я создавать и использовать этот интерфейс?" Это: Да, если вы можете связать (единую) концепцию с семантической значимостью для ваших клиентов.

Например, Comparable - хороший интерфейс, потому что он объясняет, что вещи можно сравнивать благодаря одному из их методов, и как клиент я заинтересован в работе с сопоставимыми объектами (например, для их сортировки). Напротив , CoolStuff не является хорошим интерфейсом, если вы признаете, что классные объекты не имеют определенного поведения (на самом деле, вы можете представить себе программное обеспечение, в котором имеет смысл работать с классными объектами, потому что они имеют общее поведение, такое как beCool метод).

В вашем конкретном случае я считаю, что ваш интерфейс бесполезен. Кто будет его использовать, как и когда? Вы не можете создать интерфейс для каждого из изменяемых значений. Так что спросите себя, что является подходящим и интересным свойством за ваши методы.

Если вам нужно иметь дело с объектами, у которых все их изменяемые значения доступны через пару методов, взгляните на понятие Java bean-компонента и то, как вы можете заставить свои классы принять их соглашения.

mgoeminne
источник
2

Как сказал Майкл, не добавляйте интерфейс, если в этом нет особой необходимости.

Тестирование является примером веской причины. Хотя я предпочитаю использовать реальных соавторов, если они являются просто «объектами значения», как вы их называете, для истинной изоляции модульного теста вам может понадобиться создать поддельный объект для тестирования, и в этом случае интерфейс весьма полезен.

jhewlett
источник
1
Интерфейсы не были необходимы для использования фальшивых фреймворков в течение веков.
Майкл Боргвардт
Похоже, вы выступаете за мартышки. Я был на том пути с Кротами в C #, и это не красиво. Лучше передать ваших сотрудников, если это возможно.
Jhewlett
1
Несмотря на то, что я использую Mockito и easyMock, две насмешливые среды не могут насмехаться над конечными классами, делая их неизменяемыми.
Архимед Траяно,
1

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

Goodfella
источник
0

«Интерфейс для объекта значения» - это то, что я использую для вызова метода доступа.

Я испытал различные политики относительно необходимости доступа. Некоторые люди рекомендуют, когда, насколько это возможно, другие запрещают уменьшать количество кода для записи.

Ниже перечислены некоторые рациональные ссылки для методов доступа (или прямого использования стоимости):

  • Аксессоры позволяют позже изменить способ хранения значения
  • Accessors позволяет добавлять журнал доступа, когда вы хотите отладить свое программное обеспечение (при добавлении вызова журнала одним методом вы фиксируете каждое изменение значения)
  • Средства доступа более соответствуют объектному программированию, каждая переменная инкапсулируется методами
  • Аксессоры уменьшают выразительность кода (больше SLOC для того же результата)
  • Accessors занимает немного процессора

Я лично рекомендую сократить число методов доступа и использовать их, когда вы ожидаете, что установщик (setName) станет более чем простым влиянием позже.

Марк-Эммануэль Купе де Гра
источник
0

Этот тип объекта ценности довольно низкого уровня. Я бы посоветовал подтолкнуть его в одном из двух направлений: (1) сделать объект значения неизменным, то есть, как реальное значение , или (2) поднять изменчивость до бизнес-функции, ориентированной на домен более высокого уровня, что означает, что мы должны раскрыть интерфейсы с точки зрения предметно-ориентированных единиц функциональности.

Эрик Эйдт
источник