Уникайте геттерів та сетерів, відображаючи інформацію про користувачів


10

Фон

Я читаю "Книгу чистого коду", і паралельно я працюю над гігієнічними об'єктами Ката, як банківський рахунок, і я дотримуюся цього правила:

Дев'яте правило калієстичних об'єктів - це те, що ми не використовуємо геттер або сеттер.

Це здається досить веселим, і я згоден з цим принципом. Більше того, на сторінці 98-99 Чистого кодексу автор пояснює, що геттери / сетери порушують абстракцію, і що нам не потрібно запитувати наш об’єкт, але ми мусимо сказати наш об’єкт.

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

Контекст

Наприклад, у мене є додаток, у якому я повинен перераховувати деяких користувачів та відображати дані про користувачів.

Мій користувач складається з:

-> Name
   --> Firstname --> String
   --> Lastname --> String
-> PostalAddress
   --> Street --> String
   --> PostalCode --> String

Проблема

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

Що приходить мені в голову

Одне рішення - зробити:

user.getName().getFirstName().getStringValue()

Що загалом страшно, порушуючи багато правил гігієнічних об'єктів та порушуючи закон Деметра.

Ще одне було б щось на зразок:

String firstName = user.provideFirstnameForOutput();
// That would have called in the user object =>
String firstName = name.provideFirstnameForOutput();
// That would have called in the name object =>
String firstName = firstname.provideFirstnameForOutput();

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

Будь-яка ідея?

Відповіді:


17

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

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

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

Чи варто вам розглянути можливість використання геттерів / сетерів, повністю залежить від тієї частини програми, в якій ви зараз працюєте. Якщо ви турбуєтеся про користувальницький інтерфейс, що використовує getters, це зовсім чудово, для бізнес-логіки, де ви б запустили частину коду на основі значення, отриманого через getter, не так вже й багато (це кричить, що логіка повинна була бути фактично інкапсульована в клас, на який ви називаєте геттера).

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

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


Гаразд, я думаю, що ця пропозиція подібно до картографування між моєю суттю домену, до спеціального DTO для мого шару презентації, який би мав деякі права доступу?
mfrachet

@Margin Досить, так.
Енді,

Весь цей каскадний матеріал звучить дуже добре і плавно, дякую за відповідь;)
mfrachet

2

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

String lastName = user.formatDescription("$(Lastname)");
String fullName = user.formatDescription("$(Lastname), $(Firstname)");
String abbreviated = user.formatDescription("$(FnAbb). $(LnAbb).");

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

String accountName = user.formatDescription("$(firstname).$(lastname)");

Ви також можете одночасно визначити деякі часто використовувані, можливо, складні формати, так що можна сказати, наприклад

String fullAddress = user.formatDescription(User.kAddressFormat);

Краса такого підходу полягає в тому, що він зберігає окремі рядки внутрішніми для Userкласу, водночас надаючи значно більше функціональних можливостей викличному коду. Однак недоліком є ​​те, що вам потрібно реалізувати механізм шаблону, в межах formatDescription()якого буде кілька рядків коду.

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


5
Однак це для мене схоже на порушення SRP. Чи справді відповідальність Userоб'єкта розбирати та компілювати / інтерпретувати мову шаблону?
Йорг W Міттаг

@ JörgWMittag Не обов'язково. Як я вже сказав, принцип KISS має перевагу. І я ніде не сказав, що Userклас не повинен сам реалізувати цю функціональність. Якби у мене було лише два класи, які потребували такої функціональності, ти можеш зробити ставку на мене, розподіляючи механізм заміни шаблону на свій клас. Це мається на увазі як приклад того, як можна підняти абстракцію, що Userнадається, до рівня, коли це насправді більше, ніж просто контейнер даних. І я вважаю, що ось у чому полягає уникнення доступу до користувачів: робити OOP, а не обробляти купу structs.
cmaster - відновити моніку

Ви знаєте, що KISS є абсолютно суб'єктивним та СРП-об'єктивним? KISS нічого не розповідає про те, що робити. І те, що для вас "Просте", може не "просто" для мене. Я бачу справжню різницю в якості, якщо сперечатися з KISS або SRP.
oopexpert
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.