Чому класи класів вважаються запахом коду?


18

У цій статті стверджується, що клас даних - це "запах коду". Причина:

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

Чому неправильно, щоб об’єкт містив лише дані? Якщо основна відповідальність класу полягає у представленні даних, то чи не додаватимуть методи, що працюють над даними, порушують Єдиний принцип відповідальності ?


1
Це буде сильно залежати від мовних особливостей. Наприклад, у Python немає різниці між "полем" та його аксесуарами, якщо тільки ви не підете зі свого написання Java на Python .
jscs

1
Я думаю, що лише деякі класи класів не є запахом коду, але якщо більшість класів подібні, то ми говоримо про
антипатерн "anemic

1
Я не бачу, як це питання є дублікатом. Інші питання стосуються використання класів даних в ОО, тоді як це стосується недоліків класів даних - абсолютно різних предметів.
Мілош Мрдович

Ви можете прочитати цю відповідь на stackoverflow, який є набагато більш диференційованим, ніж відповідь, що голосує вгорі, що постулює неповноцінність багатої доменної моделі та подає її як перевірений факт. stackoverflow.com/questions/23314330 / ...
McLovin

Відповіді:


31

З чистими об'єктами даних абсолютно нічого поганого немає. Автор твору відверто не знає, про що йде мова.

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

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


1
Просто хотілося додати, що чисті об'єкти даних можуть бути безцінними для моделювання відносин, перевірки, контролю доступу / змін.
Адріан

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

7
Якщо функція бере аргумент цього типу даних, вона вже пов'язана з даними.
RemcoGerlich

4
Відхилення, тому що це неправильно, або в кращому випадку питання думки. У мові ОО зазвичай є сенс, щоб об'єкт містив як дані (які все ще можуть бути незмінні!), Так і методи, що діють на нього. Чисті функції та окремі дані чудово підходять для інших мовних парадигм, але якщо ви виконуєте OO, виконайте OO повністю.
Marnen Laibow-Koser

3
Реальність показала нам багато речей. -1 для догматичної ноу-хау, всі "інші провалили" думку. Також автор не каже, що чисті об'єкти даних "помиляються", просто що вони є "запахом коду" і варті запитання. Я шкодую лише про те, що я маю один голос для своєї країни. :-)
user949300

7

З чистими об'єктами даних абсолютно нічого поганого немає. Автор має думку, яку не поділяють розробники програмного забезпечення, яких я знаю.

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

Ідея лунки Java-бобів, що використовується багатьма інструментами / рамками, заснована на класах даних, які називаються бобами, які містять лише поля та пов'язані з цим геттери та сетери. Wikipdia JavaBeans

Фазіт:
Якщо хтось стверджує, що щось є «поганим» або «кодовим запахом», завжди слід шукати наведені причини. Якщо причини не переконують, запитайте когось іншого про кращі причини чи іншу думку. (Як ви робили на цьому форумі)


Автор не каже, що чисті об'єкти даних "неправильні". Вони кажуть, що чисті об'єкти даних - це «запах коду», а це означає, що вам варто подумати над їх використанням.
user949300

1
@ user949300, ти виглядаєш розгубленим. Якщо автор відноситься до них як до кодового запаху, то він вказує, що з ними може бути щось не так. Оскільки вони широко визнані в наші дні як дуже хороша практика, вони, очевидно, не є кодовим запахом. Таким чином, MrSmith42 є правильним: з ними абсолютно нічого поганого.
Девід Арно

4

Хороший аргумент, чому Мартін Фаулер:

"Tell-Don't-Ask" - це принцип, який допомагає людям пам’ятати, що орієнтація на об'єкт полягає в поєднанні даних з функціями, які працюють на цих даних. Це нагадує нам, що замість того, щоб запитувати об'єкт для даних і діяти на цих даних, ми замість цього слід сказати об’єкту, що робити. Це спонукає перенести поведінку в об’єкт, щоб перейти з даними ".

https://martinfowler.com/bliki/TellDontAsk.html


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

2
@DavidArno Ви забуваєте про інкапсуляцію та приховування. Ви говорите об’єкту виконати метод-член, а метод-член переходить у чорний ящик об'єкта і робить все, що потрібно, щоб отримати відповідь. Якщо ви запитаєте об'єкт ззовні, у вас немає доступу до його приватного стану, і тому або об’єкт відкриває більше стану, ніж розумно, або запитуючий повинен перестрибувати більше обручів, ніж потрібно. Я не бачу, чому ви коли-небудь "запитували" об'єкт в середовищі ОО. (Звичайно, інші парадигми програмування можуть вимагати різних підходів.)
Marnen Laibow-Koser

2
@DavidArno Звичайно, ви можете передати bazяк параметр статичний метод, але для цього спочатку потрібно попросити об’єкт. Можливо, у парадигмі програмування, де методи були первинними (як, скажімо, функціональне програмування), це має сенс, але в середовищі ОО це абсолютно не відбувається, оскільки об'єкти є первинними і повинні містити як дані, так і функції, що діють на неї. Наскільки Ви можу сказати, що видалення методу з об'єкта збільшило інкапсуляцію, саме на зворотному рівні , оскільки це означає, що Ви bazз'явилися поза об'єктом.
Marnen Laibow-Koser

1
@ MarnenLaibow-Koser, я не претендую на те, що "займаюся ОО". Я пишу код і використовую хороші методи для цього. Незалежно від того, чи ці методи походять від функціональної парадигми, чи парадигми ОО, або парадигма, яка дає прокляття, мене не цікавить. Вибір парадигми та дотримання її максимально повно - це чиста догма. Це погано. Це смішно. Це задушує вас і призводить до неповноцінного коду. Не робіть цього.
Девід Арно

1
@DavidArno Навпаки, якщо ви повністю дотримуєтесь парадигми (будь-якої гідної парадигми, а не лише OO), ви отримуєте потужні абстракції високого рівня та логічно послідовний, бездоганний код. Я не кажу, що це догматично, а скоріше прагматично. Я бачив і підтримував занадто багато коду, який, мабуть, був вироблений з таким ставленням, як ваше, коли автор насправді не покладався на логічну послідовність використовуваної системи. Це важко зрозуміти, важко підтримувати і важко модифікувати. Жодна парадигма не є ідеальною, але загалом зрозуміти суміш (якщо не уважно розглядати) важче.
Marnen Laibow-Koser

2

Що вам потрібно зрозуміти, це те, що існує два види об’єктів:

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

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

    Більшість класів, які я пишу, належать до цієї категорії.

  • Об'єкти, які насправді є лише даними . Вони повинні просто оголосити всіх своїх членів громадськістю (або надати повний набір аксесуарів для них).

    Прикладом може бути заняття Point2D. Не існує інваріанта, який потрібно забезпечити для членів цього класу, і користувачі повинні мати можливість просто отримувати доступ до даних через myPoint.xта myPoint.y.

    Особисто я мало використовую такі класи, але, мабуть, немає більшого фрагмента коду, який я написав, який не використовує такого класу десь.

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


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


1
Пояснення попутного голосування було б крутим ...
cmaster - відновити

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