JavaRush /Java блог /Random UA /Геттери/Сеттери. Зло. І крапка
angelina
5 рівень

Геттери/Сеттери. Зло. І крапка

Стаття з групи Random UA
Стаття Єгора Бугаєнка 19 вересня, 2014 | Опубліковано в: Core Java Геттери/Сеттери.  Зло.  І точка - 1 Цей старий спір почав Аллен Холаб у своїй знаменитій статті, ще в 2003 році, Чому методи гетер і сеттер - зло - чи є гетери/сеттери анти-патерном і чи варто їх уникати, або це те, що нам неминуче знадобиться в об'єктно-орієнтованому програмуванні. Додам я і свої півкопійки до цієї дискусії. Суть тексту нижче ось у чому: гетери та сеттери - це погана практика, у тих, хто їх використовує немає жодних виправдань. Але знову ж таки, щоб уникнути нерозуміння, я зовсім не стверджую, що використання get/set потрібно уникати де можливо. Ні. Я говорю про те, що ви їх навіть близько до вашого коду не підпускали . Геттери/Сеттери.  Зло.  І точка - 2Як вам така заява? Достойно вашої уваги? Ви вже користуєтеся get/set патерном 15 років і ви шановний Java архітектор? І не хочете навіть слухати цю нісенітницю від незнайомця? Ну... я розумію ваші почуття. Я відчував те саме, поки не натрапив на книгу Девіда Веста "Object Thinking" - це найкраща книга з об'єктно-орієнтованого програмування, яку я коли-небудь читав. Тому, будь ласка. Заспокойтеся та спробуйте зрозуміти, що я намагаюся пояснити. Предмет Спора Є кілька аргументів проти "аксесорів" (інша назва гетерів та сеттерів) в об'єктно-орієнтованому світі. І всі вони – дуже правильні аргументи. Давайте коротко їх розглянемо. Запитуй, Не говори: Аллен Холаб каже: "Не проси інформацію, яка вам потрібна для роботи; "проси" об'єкт, який має цю інформацію зробити роботу за вас." Порушений Принцип Інкапсуляції : Предмет може бути розібраний частинами іншими об'єктами, тому що вони в змозі вбудувати будь-які дані в об'єкт, через сеттери. Об'єкт просто не може інкапсулювати свій власний стан досить безпечно, тому що будь-хто може змінити цей стан. Розкриті Деталі Реалізації: Якщо ви можете дістати (get) один об'єкт з іншого об'єкта, тоді виходить, що ми надто сподіваємося на деталі реалізації першого об'єкта. Якщо завтра він зміниться (наприклад, тип результату), то нам доведеться змінювати код. Всі вищевикладені обгрунтування звичайно мають сенс, але тут упускається найважливіший момент. Основна помилка Більшість програмістів вірять, що об'єкт - це структура даних з методами. Я цитую статтю Божидара Божанова: Геттери та Сеттери – не зло. Але більшість об'єктів, для яких створюються гетери та сеттери просто містять дані. Ця помилка є результатом величезного нерозуміння! Об'єкти - не просто зберігають дані. Об'єкти - не структури даних із прикріпленими методами. Ця концепція "зберігання даних" прийшла в об'єктно-орієнтоване програмування їх процедурних мов, особливо таких як C і COBOL. Я знову повторю: об'єкт – не просто набір елементів даних та функції, які ними маніпулюють. Об'єкт - це об'єкт даних. Тоді що? М'ячик та Собака У цьому об'єктно-орієнтованому програмуванні об'єкти - живі істоти, як і я. Вони живі організми, зі своєю власною поведінкою, властивостями та циклом життя. Чи може живий організм мати сетер? Ви можете причепити (“set”) м'ячик до собаки? Не думаю. Але так і робить шматок коду нижче:
Dog dog = new Dog();
dog.setBall(new Ball());
Ну як це вам? Ви можете дістати (“get”) м'ячик із собаки? Ну, припустимо, що ви зможете. Якщо вона його з'їла і ви зробабо їй операцію. У цьому випадку, так, ви зможете дістати (“get”) м'ячик із собаки. Це саме те, про що я говорю:
Dog dog = new Dog();
Ball ball = dog.getBall();
Або ще більш безглуздий приклад:
Dog dog = new Dog();
dog.setWeight("23kg");
Ви таке у реальному житті можете собі уявити? Схоже на те, що ви пишете щодня? Якщо так, то ви – процедурний програміст. Просто зізнайтеся у цьому. А ось, що говорить Девід Уест на сторінці 30 своєї книги: Першим кроком у трансформації успішного процедурного розробника в успішного об'єктивного розробника це лоботомія. Вам потрібна лоботомія? Мені точно була потрібна, і я її отримав, доки читав книгу Веста "Object Thinking". Об'єктивне мислення Почніть думати як об'єкт і ви відразу ж перейменуєте ці методи. Ось що можливо у вас вийде:
Dog dog = new Dog();
dog.take(new Ball());
Ball ball = dog.give();
Ось тепер ми ставимося до собаки як справжньої тварини, яка може взяти у нас м'ячик і може віддати назад, якщо ми попросимо. Про всяк випадок зауважу, що собака не зможе повернути NULL. Просто собаки не знають, що таке NULL! Об'єктивне мислення (думання) відразу ж забирає NULL references з вашого коду. Геттери/Сеттери.  Зло.  І точка - 3
Рибка на ім'я Ванда (1988) Чарльза Кричтона
Крім того, об'єктивне мислення призведе до незмінності (immutability) об'єкта, такого як "вага собаки" в нашому прикладі. Ви б переписали код приблизно так:
Dog dog = new Dog("23kg");
int weight = dog.weight();
Собака- це незмінний живий організм, який дозволить нікому зовні змінювати її вагу, чи розмір, чи ім'я, тощо. Вона може "повідомити", на запит, її вагу або ім'я. Немає нічого поганого у публічних методах, які відображають запити певних "внутрішніх" властивостей об'єкта. Але ці методи не "гетери" і вони ніколи не повинні отримувати префікс "get". Ми не "дістаємо" (“getting”) із собаки. Ми не отримуємо її ім'я. Ми просимо її сказати нам її ім'я. Бачите різницю? Ми навіть не про семантику тут говоримо. Ми диференціюємо процедурний підхід до програмування від об'єктно-орієнтованого. У процедурному програмуванні ми працюємо з даними, маніпулюємо ними, отримуємо (get) і встановлюємо (set), і видаляємо, якщо потрібно. Ми керуємо, а дані – просто пасивний компонент. Собака для нас ніщо - він просто PS . І так, ви можете запитати: "А що з приводу JavaBeans, JPA, JAXB та багатьох інших Java APIs, які залежать від get/set?" А що з приводу вбудованої функції Ruby, яка спрощує створення аксессорів? Ну, що вам сказати... вам не пощастило. Набагато легше залишатися в примітивному світі процедурного COBOL, ніж зрозуміти та прийняти чудовий світ справжніх об'єктів. PPS . Забув сказати, так, вставка залежностей через сеттер - це також страшний анти-патерн. Але про це у наступному пості! Оригінальна стаття
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ