Чи слід створювати інтерфейси для об’єктів передачі даних?


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

Sidenote: будь ласка, уникайте використання терміна "об'єкт значення" для опису бобів Java лише з тривіальними геттерами та сеттерами - це суперечить більш загальному визначенню об'єкта значення як щось, що не має ідентичності, яка зазвичай незмінна. Кращим терміном буде DTO або клас моделі - хоча в останньому випадку зауважте, що анемічні доменні моделі вважаються антипатерном.


3
"Анемічні моделі доменів вважаються антипатерном" - Мартін Фаулер, який в PEAA зізнається, що знає людей, які десятиліттями працювали так "дуже успішно". Таким чином, я пропоную, менше анти-візерунок і більше не так, як Фаулер любить працювати. Тим не менше, хороша відповідь, +1.
пдр

4
@pdr: Фаулер, можливо, придумав цей термін, але він аж ніяк не єдиний, хто вважає їх антипатерном. Я не думаю, що хтось, хто насправді зрозумів ОО, не вважає, що це гарна ідея не допускати доменної логіки поза доменною моделлю.
Майкл Боргвардт

Дякую за виправлення терміну, DTO - це слово, яке я шукав минулої ночі, але не міг запам'ятати все життя. Змінивши назву навколо, речі зробили більш розумним дизайн.
Архімед Траяно

@pdr Я думаю, що найкращим способом є те, що це антипаттерн в контексті програмування ОО. Існує багато інших парадигм, де це прекрасно, і ви навіть можете успішно працювати таким чином на мові ОО (вона просто не буде особливо орієнтована на об'єкти).
Даніель Б

3
@MichaelBorgwardt: Я згоден, він не один у цьому. Але також не погоджуються люди. Якби ви сказали, що "анемічні доменні моделі вважаються деякими анти-зразком", я б нічого не сказав. Чесно кажучи, я думаю, що вся ваша відповідь все-таки була б кращою без останнього абзацу. Перший тайм зробив би кращий коментар; друга половина нічого не пропонує до цього питання.
пдр

2

Створення інтерфейсу нормально, але НЕ так, як працює ваш приклад. Вам слід видалити сетер із інтерфейсу, і все буде добре:

interface ValueObject {
  String getName();
};

Це дозволяє безліч різних його реалізацій, наприклад, ім'я можна отримати з бази даних ... Setter повинен знаходитися в іншому інтерфейсі.


2

Інтерфейси визначають договір між класами, що реалізують інтерфейси, та їх клієнтами. Вони використовуються як механізм абстрагування, щоб клієнти могли маніпулювати "речами, що мають задану поведінку".

Тож загальна відповідь на питання "чи слід створити та використовувати цей інтерфейс?" є: Так, якщо ви можете пов’язати концепцію (єдину), яка має семантичне значення для ваших клієнтів.

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

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

Якщо ви хочете мати справу з об'єктами, які мають усі їх змінні значення, доступні за допомогою декількох методів, ознайомтеся з поняттям Java bean та способом, як ви можете змусити ваші класи приймати їхні умови.


2

Як сказав Майкл, не додайте інтерфейс, якщо у вас немає конкретної потреби в ньому.

Тестування - приклад вагомої причини. Хоча я вважаю за краще використовувати справжніх співпрацівників, якщо вони просто "об'єкти цінності", як ви їх називаєте, для істинної ізоляції тестування вам може знадобитися створити підроблений об'єкт для тестування, і в цьому випадку інтерфейс є дуже корисним.


1
Інтерфейси не потрібні для використання глузуючих фреймворків у віках.
Майкл Боргвардт

Здається, що ви виступаєте за дотримання мавп. Я пройшов цей шлях з Молем в C #, і це не дуже. Краще передати своїх співробітників, якщо можливо.
jhewlett

1
Незважаючи на те, що два глузливі рамки, які я використовую, Mockito та easyMock не можуть знущатися над заключними класами, роблячи їх незмінними.
Архімед Траяно

1

Якщо ви хочете, щоб цей об’єкт мав певну перевірку полів у майбутньому, вам слід їх інкапсулювати на ранніх етапах.


0

"Інтерфейс об'єкта значення" - це те, що я використовував для виклику доступу.

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

Деякі параметри доступу до аксесуарів (або використання прямого значення) є такими:

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

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


0

Цей тип ціннісного об’єкта досить низький. Я б запропонував просунути його в одному з двох напрямків: (1) зробити об'єкт значення непорушним, тобто як справжнє значення , або (2) підняти змінність до ділової функції, орієнтованої на домен більш високого рівня, тобто ми повинні піддавати інтерфейси з точки зору доменних одиниць функціональності.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.