Чи порушує суб'єкт домену єдиний принцип відповідальності?


14

Єдиною відповідальністю (підставою для зміни) суб'єкта господарювання повинно бути унікальна ідентифікація себе, іншими словами, його відповідальність полягає у фіналізації.

Книга DDD Еріка Евана, стор. 93:

Основна відповідальність суб'єктів господарювання полягає у встановленні наступності, щоб поведінка була чіткою та передбачуваною. Вони роблять це найкраще, якщо їх залишають запасними. Замість того, щоб концентруватись на атрибутах чи навіть на поведінці, зніміть визначення об'єкта Entity до найбільш сутнісних характеристик, зокрема тих, що його ідентифікують або зазвичай використовуються для їх пошуку чи відповідності. Додайте лише поведінку, яка є суттєвою для поняття та атрибутів, які вимагаються від цієї поведінки.

Крім того, намагайтеся видалити поведінку та атрибути в інші об'єкти, пов'язані з основною сутністю. Окрім проблем із ідентичністю, суб'єкти, як правило, виконують свої обов'язки, координуючи операції об'єктів, якими вони володіють.

1.

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

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

2.

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

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

3.

Крім того, погляньте на видалення поведінки та атрибутів в інші об’єкти, пов’язані з основним ENTITY.

а) MyEntityделегує обов'язки A_respі B_respоб'єктам, aі bвідповідно.

Хоча більшість A_respі B_respробота виконується , aі bвипадки, клієнти по - , як і раніше служили A_respі B_respчерез MyEntity, що означає , що з точки зору клієнта дві обов'язки належать MyEntity. Таким чином, чи це не означає, що MyEntityтакож є A_respі B_respобов'язки, і як таке порушує СРП ?

б) Навіть якщо ми припустимо , що A_respі B_respне належать MyEntity, по- MyEntity, як і раніше несе відповідальність AB_respза координацію операцій об'єктів aі b. Тож не MyEntityпорушує СРП, оскільки як мінімум він несе два обов'язки - однозначно ідентифікувати себе, а також AB_resp?

class MyEntity
{
    private A a = ...
    private B b = ...


    public A GetA()
    { ... }

    public B GetB()
    { ... }

    /* coordinates operations of objects a and b */
    public int AworkB()
    { ... }
}

/* A encapsulates a single responsibility resp_A*/
/* A is value object */
class A
{ ... }

/* B encapsulates a single responsibility resp_B*/
/* B is value object */
class B
{ ... }

ОНОВЛЕННЯ:

1.

Поведінка в цьому контексті спрямована на смислову поведінку. Наприклад, властивість класу (тобто атрибут об’єкта домену), яка використовується для однозначної ідентифікації, має поведінку. Хоча це не представлено в коді безпосередньо. Очікувана поведінка полягає в тому, що для цього властивості не буде жодних повторюваних значень.

Тож у коді нам майже ніколи не потрібно реалізовувати поведінку (тобто операцію), яка б якось підтримувала ідентичність суб'єкта господарювання, оскільки, як ви пояснили, така поведінка існує лише як концепція в доменній моделі (у вигляді атрибута ID сутність), але коли ми переводимо цей атрибут ID у код, частина його семантики втрачається (тобто частина, яка неявно переконує, що значення ID унікальне втрачено)?

2.

Далі, така властивість, як Age, не має контексту поза особою особи, і, як така, не має сенсу переходити в інший об'єкт ... Однак ця інформація може легко зберігатися в окремому місці, яке є унікальним ідентифікатором, отже заплутане посилання на поведінку. Вік може бути лінивим значенням.

а) Якщо Ageвластивість ліниво завантажена, то ми можемо називати це поведінкою, хоча семантично Ageце лише атрибут?

3.

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

Хоча я погоджуюся, що ми втратили контекст, перемістившись Ageв інший об’єкт, контекст не був би втрачений, якби ми перенесли DateOfBirthвластивість в інший об’єкт, але ми зазвичай не переміщуємо його.

Яка головна причина того, що ми переїхали Addressв інший об’єкт, але ні DateOfBirth? Тому що DateOfBirthце більш суттєво для Personсутності або тому, що є менше шансів, що десь у майбутньому нам може знадобитися визначити конкретні операції DateOfBirth?

4. Я повинен сказати , що я до сих пір не знаю, MyEntityє також A_respі B_respобов'язки і чому MyEntityж то , AB_respне вважається порушенням SRP

EULERFX

1)

Поведінки, на які посилається автор, - це поведінка, пов'язана з сутністю. Це поведінка, яка модифікує стан сутності

а) Якщо я вас правильно зрозумів, ви говорите, що суб'єкт повинен містити лише ті поведінки, які змінюють його атрибути (тобто його стан )?

б) А як щодо поведінки, яка не обов'язково змінює стан сутності , але все ще вважається сутнісною характеристикою цього суб'єкта (наприклад: гавкання було б внутрішньою характеристикою Dogсуб'єкта, навіть якщо воно не змінювало Собачий стан )? Чи слід включати ці поведінки в сутність або вони повинні бути переміщені до інших об'єктів?

2)

Що стосується переміщення поведінки до інших об'єктів, то автор має на увазі конкретно цінні об'єкти.

Хоча моя цитата не включає її, але автор в тому ж параграфі зазначає, що в деяких випадках поведінка (та атрибути ) також перейде в інші сутності (хоча я розумію переваги переходу поведінки до ВО)

3) Якщо припустити MyEntity(див питання 3. в моїй посаді) чи не порушує SRP, б ми говоримо , що відповідальність в MyEntityце крім усього іншого , також складаються з:

а. A_resp + B_resp + AB_resp ( AB_respкоординує об'єкти aта b)

або

б. AB_resp + делегування A_respта B_respоб'єкти ( aта b), пов'язані з MyEntity?

4) Книга DDD Еріка Евана, стор. 94:

CustomerID - це єдиний ідентифікатор ENTITY Клієнта (рисунок 5.5), але телефонний номер та адреса часто використовуються для пошуку або відповідності Клієнту. Ім'я не визначає особу людини, але її часто використовують як частину засобів її визначення.

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

а)

CustomerID - це єдиний ідентифікатор ENTITY Клієнта (рисунок 5.5), але телефонний номер та адреса часто використовуються для пошуку або відповідності Клієнту. Ім'я не визначає особу людини, але її часто використовують як частину засобів її визначення.

Цитата зазначає, що лише атрибути, пов’язані з ідентичністю, повинні залишатися в сутності . Я припускаю, що автор означає, що сутність повинна містити лише ті атрибути , які часто використовуються для пошуку або відповідності цій сутності , тоді як ВСІ інші атрибути слід переміщувати?

б) Але як / куди слід переміщувати інші атрибути ? Наприклад (припущення тут полягає в тому, що атрибут адреси не використовується для пошуку або збігу, Customer і тому ми хочемо перемістити атрибут адреси з Customer):

якщо б замість того, щоб мати Customer.Address(тип string), ми створимо властивість Customer.Addressтипу Address, чи перенесли ми атрибут адреси в асоційований об'єкт VO (який є типу Address) чи скажемо, що він Customerвсе ще містить атрибут адреси ?

в)

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

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

5)

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

За темі, але я думав , що анемія моделі предметної області результатів від переміщення поведінки з - за суті , в той час як ваш приклад заповненням в об'єкт з великою кількістю атрибутів , які привели б Customerмати занадто багато поведінки (так як ми, ймовірно , також включаємо в Customerтих поведениях , які змінити ці додаткові атрибути ) і, таким чином, порушувати SRP?

Дякую


2
Я б дуже рекомендував Роберт Мартінс чистий код відео серіалу, cleancoders.com Він детально розглядає, як різні принципи можуть викликати проблеми або збалансувати один одного. інакше я думаю, що частина формули для вашого прикладу буде дивитися на проміжок часу, з яким стосується об'єкт Person. якщо його на короткий проміжок часу подібно до Покупки, то платіжна адреса, яка використовується для покупки, буде частиною цього і незмінною. якщо його для облікового запису Бібліотеки, то адресу потрібно змінити.
Картало

2
Я думаю, що це питання може порушити СРП ...;)
IntelliData

Відповіді:


7

Поведінка в цьому контексті спрямована на смислову поведінку. Наприклад, властивість класу (тобто атрибут об’єкта домену), яка використовується для однозначної ідентифікації, має поведінку. Хоча це не представлено в коді безпосередньо. Очікувана поведінка полягає в тому, що для цього властивості не буде жодних повторюваних значень. Щось таке, як Адреса, яка може мати власну ідентичність, але не існує поза контекстом Особистої особи, все ж слід перенести у власний об’єкт. Таким чином, просування об'єкта в об'єднаний корінь.

Далі, така власність, як Age, не має контексту за межами Особистої особи, і як така, немає сенсу переходити на інший об'єкт. Контекст буде втрачено, і тому ви можете сміливо визначити, що це значення, яке є суттєвим для Особистої особи. Ви не можете знайти значення в іншому випадку. Однак ця інформація може легко зберігатися в окремому місці, що є унікальним ідентифікатором, отже, заплутане посилання на поведінку . Вік може бути лінивим значенням.

Отже, щоб відповісти на ваше запитання. Ні, це не порушує Принцип єдиної відповідальності. Це просто кажучи, що Людина повинна мати лише особисті речі, а не те, як Адреса, яка є більш складною і пов'язаною з людиною, повинна існувати як її власна сутність.

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

Оновлення: 1) У більшості випадків перевірка ідентичності проводиться після збереження об'єкта у сховищі даних. Що означає, що код, що представляє перевірку сутності, існує, але він існує в іншому місці. Зазвичай він існує з кодом, який відповідає за видачу значення ідентичності. Тому я заявляю, що унікальність не представлена безпосередньо в коді для сутності.

2) Правильним буде твердження, що Ageце атрибут поведінки. Вам потрібно буде задокументувати той факт, що вік ліниво завантажений, щоб розробник, який споживає цю властивість, міг прийняти точне рішення щодо споживання цієї власності

3) DateOfBirthзазвичай це інший об’єкт; Об'єкт дати, у якого вже визначені операції над ним. У деяких мовах для об'єкта дати вже визначена ціла модель домену. Наприклад, в c # ви можете вказати часовий пояс, якщо дата - UTC, додайте та віднімайте дати, щоб отримати часовий пояс. Тож ваше припущення про переїзд DateOfBirthбуло б правильним.

4) Якщо єдине, що MyEntityробиться, - це делегування та узгодження, то ні, це не порушує СРП. Її єдиною відповідальністю є делегування та координація і вважається фасадною схемою


Не могли б ви подивитись на оновлення, яке я зробив?
EdvRusj

Оновлено мою відповідь
Чарльз Ламберт

4

Дуже гарне запитання. СРП не слід сприймати так літрально. Ідентифікація / пошук не є відповідальністю суб'єкта господарювання стосовно SRP. Хтось інший несе відповідальність за надання йому ідентифікатора (а саме магазину) і пошуку його (а саме сховища ).

Основна мета суб'єкта господарювання - представити поняття, розкриті моделлю. Єдина відмінність між об'єктом і об'єктом цінності полягає в тому, що суб'єкт має значення, що перевищує його атрибути, що не ідентифікують. Наприклад, якщо людина змінить своє Ім'я, він все одно та сама людина, просто з іншим ім’ям.


2

TL; DR: ти над цим думаєш. Однак мені було весело, передумуючи це разом з вами. Тож пряжі….

Єдиною відповідальністю (підставою для зміни) суб'єкта господарювання повинно бути унікальна ідентифікація себе, іншими словами, його відповідальність полягає у фіналізації.

Ні, це неправильно. Єдиною відповідальністю суб'єкта господарювання є наступність.

Ідентичність є наслідком наступності. Моделювання ідентичності як роздільної ідеї - це оптимізація продуктивності.

Ось приклад: меценат ресторану дає автомобіль до камердинера. Через годину меценат ресторану просить машину. Чи повинен давати камердинер?

Неважко сказати, що камердинер повинен дати машину, якщо покровитель "той самий". Але що це насправді означає? Правильний спосіб визначити це - почати з мецената "зараз" і провести пошук назад через історію цього мецената, щоб побачити, чи передача автомобіля камердинеру є частиною цієї історії.

Ми, звичайно, не можемо цього зробити. У нас є проблеми точно відслідковувати власну історію, не маючи на увазі історію того, чого не було з нами весь час. Тож замість того, щоб використовувати історію мецената, ми беремо короткі скорочення. Чи покровитель має заглушку квитка, яка має той самий номер, що і тег, який зараз прив’язаний до ключів? Чи посвідчує водійське посвідчення в гаманці покровителя ім'я, зазначене в назві на DMV, чи зображення на посвідченні водія нагадує обличчя покровителя. І т.д.

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

При моделюванні сутностей ми використовуємо аналогічну оптимізацію. Ми надаємо всім організаціям спільні обов'язки

  1. Забезпечення того, що початок історії включає призначення незмінного ідентифікатора стану об'єкта
  2. Забезпечення того, що наступний стан завжди включає вірну копію ідентифікатора попереднього стану.

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

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

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

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

Ви також, здається, переплутали Принцип єдиної відповідальності (що є дійсно хорошою ідеєю) з принципом атомної відповідальності. Розкладання відповідальності на менші, простіші, керовані частини сумісні з SRP.


1

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

Якщо особа встановлена, то так, суб'єкту господарювання більше нічого не потрібно ідентифікувати. Поведінки, на які посилається автор, - це поведінка, пов'язана з сутністю. Це поведінка, яка модифікує стан сутності. Наприклад, Customerсуб'єкт господарювання може мати MakePreferredповедінку. Причина, яку автор пропонує зняти суб'єкт господарювання, полягає в тому, що коли спочатку створюється Customerсутність, існує тенденція до заповнення його будь-яким атрибутом, який можна вважати асоційованим із замовником. Це підхід, орієнтований на даних, який не враховує поведінки, що в кінцевому рахунку призводить до анемічної моделі домену.

Що стосується переміщення поведінки до інших об'єктів, то автор має на увазі конкретно цінні об'єкти. Причина, по якій хороша ідея перейти до поведінки на VO, полягає в тому, що VO зазвичай «менші», ніж сутності, тим самим більш цілеспрямовані. Більше того, такі аспекти, як незмінність та закриття операцій, спрощують міркування про код, одночасно роблячи його більш твердим .

Разом з ВО суб'єкт господарювання служить своєрідним якорем, який координує різні ВО, які реалізують його поведінку.

Що стосується SRP, то ваша плутанина не є невиправданою. Однією із проблем стереотипної реалізації об'єднаних організацій ООП є співвідношення ідентичності та стану. Дійсно, з поведінкової точки зору, ідентичність не має нічого спільного з поведінкою. Іншими словами, особа суб'єкта господарювання не вимагає жодної його поведінки. Є реалізації, де це конфлікт усувається, наприклад AggregateSource або функціональний підхід, який я тут описую .

Інша проблема полягає в тому, що до певної міри СРП може бути якісним заходом. Будь-хто може придумати визначення єдиної відповідальності, яку порушує якийсь клас. Можна сказати, що відповідальність суб'єкта господарювання полягає у здійсненні поведінки, необхідної для цього суб'єкта. У цьому сенсі вона несе єдину відповідальність. Крім того, коли суб'єкт господарювання делегує поведінку до складових ВО, це не порушує ПДЧ. SRP не забороняє складу такого роду. Це дуже обережно, щоб звести зв'язок між об'єктами до абсолютного мінімуму, підтримувати інтерфейси максимально голими тощо.

ОНОВЛЕННЯ

а) Якщо я вас правильно зрозумів, ви говорите, що суб'єкт повинен містити лише ті поведінки, які змінюють його атрибути (тобто його стан)?

Так, хоча є винятки ...

б) А як щодо поведінки, яка не обов'язково змінює стан сутності, але все ще вважається сутнісною характеристикою цього утворення (наприклад: гавкання було б невід'ємною характеристикою суб'єкта Собаки, навіть якби це не було змінити стан Собаки)? Чи слід включати ці поведінки в сутність або вони повинні бути переміщені до інших об'єктів?

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

3) Якщо припустити, що MyEntity (див. Питання 3. у моєму первісному дописі) не порушує SRP, ми б сказали, що відповідальність MyEntity, серед іншого, також складається з:

Ви дивитесь на відповідальність з точки зору впровадження. Натомість розгляньте організацію як своєрідну чорну скриньку з обов'язками. Як поводитися з тими, хто вас не цікавить, як хтось із зовнішніх поглядів. Розподіл обов'язків серед ВО або навіть інших суб'єктів є проблемою впровадження.

Цитата зазначає, що лише атрибути, пов’язані з ідентичністю, повинні залишатися в сутності. Я припускаю, що автор означає, що сутність повинна містити лише ті атрибути, які часто використовуються для пошуку або відповідності цій сутності, тоді як ВСІ інші атрибути слід переміщувати?

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

якщо замість того, щоб мати клієнт.адрес (рядок типу), ми створимо властивість Customer.Adress адреса типу, ми перенесли атрибут адреси в асоційований об'єкт VO (який має тип адреси) чи ми б сказали, що клієнт все ще містить адресу атрибут?

Так, насправді немає різниці між рядковою адресою або адресою VO Address.

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

Я не на 100% в намірі автора, але думаю, що він просто описує, як вимоги пошуку суб'єкта можуть змінювати, як структура і відповідні VO є структурами.

Немає теми, але я вважав, що анемічна модель домену є результатом переміщення поведінки з об'єкта, тоді як ваш приклад заповнює організацію з великою кількістю атрибутів, що призводить до того, що Клієнт матиме занадто багато поведінки (оскільки ми, ймовірно, також включаємо в Клієнта клієнта поведінки, які змінюють ці додаткові ознаки) і, таким чином, порушують СРП?

Багато атрибутів не передбачає багато поведінки. Насправді це зазвичай припускає зворотне. Багато атрибутів з геттерами та сетерами, але ніякої інкапсуляції.


Я зробив оновлення
EdvRusj

-3

Ну, це залежить від того, як ви хочете на це подивитися.

Ще один спосіб: "Чи порушує Принцип єдиної відповідальності домен юридичної особи?"

Обидва - це керівні принципи. Ніде "принципу" в розробці програмного забезпечення немає. Однак є хороші конструкції та погані конструкції. Обидві ці концепції можна використовувати по-різному, щоб досягти гарного дизайну.


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