JavaRush /Java блог /Архив info.javarush /Геттеры/Сеттеры. Зло. И точка
angelina
5 уровень

Геттеры/Сеттеры. Зло. И точка

Статья из группы Архив info.javarush
Статья Егора Бугаенко 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), и удаляем, если нужно. Мы руководим, а данные - просто пассивный компонент. Собака для нас ничто - она просто "содержит данные". У нее нет своей жизни. Мы можем свободно получить (get ) все, что нужно от нее и поместить (set) любые данные в нее. Так работают (работали) C, COBOL, Pascal и другие процедурные языки. И совершенно противоположная ситуация в объектно-ориентированном мире. Тут мы относимся к объектам как к живым организмам, с их собственной датой рождения и моментом смерти, со своей собственной индивидуальности и привычками, если хотите. Мы можем попросить собаку дать нам кусочек данных (к примеру ее вес) и она может вернуть нам информацию. Но всегда помните, что собака -это активный компонент. Она решает что случиться после запроса. И именно поэтому - это абсолютно неверно, когда методы объекта начинаются с set или get. И это даже не о нарушении инкапсуляции, как многие думают. Это о том, что либо вы думаете как объект или вы все еще пишете на COBOL с синтаксисом Java. PS. И да, вы можете спросить: "А что по поводу JavaBeans, JPA, JAXB и многих других Java APIs, которые зависят от get/set?" А что по поводу встроенной функции в Ruby, которая упрощает создание акксессоров? Ну что вам сказать... вам не повезло. Намного легче оставаться в примитивном мире процедурного COBOL, чем понять и принять прекрасный мир настоящих объектов. PPS. Забыл сказать, да, вставка зависимостей через сеттер - это тоже ужасный анти-паттерн. Но об этом в следующем посте! Oригинальная статья
Комментарии (13)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Егор А. Марков Уровень 14
7 декабря 2021
хотел просто узнать, зачем применять get/set методы для приватных переменных, когда можно просто сделать их публичными, а по итогу третий день провожу в рефлексии. вернусь сюда после 6 лет джава-разработки
Егор Уровень 27
10 января 2020
По моему мнению, это лишь игра слов. Какая разница set или take? get и set это лишь общепринятые названия, которые говорят нам о функционале метода. Статья ни о чем.
sokolov Уровень 40
16 ноября 2016
Есть у кого-то Object Thinking в русском переводе, понимаю, что подобную литературу нужно читать в оригинале, но как-то очень тяжело идет оригинал и тема не простая. Заранее спасибо поделившемуся!
fatfaggy Уровень 26
8 августа 2015
Она решает что случиться после запроса.

извините, но режет глаз)
maks1m Уровень 25
2 января 2015
Зачем было мешать мух и котлеты?!
Все что здесь предлагается это просто игра с именами методов не всегда применимая на практике.
Новичкам вообще не читать!!!
В большинстве своем мы оперируем объектами как невоодушевленными сущностями и эта излишняя вежливость к объектам, как по мне, ни к чему. Я получил из базы документ (объект), поработал с ним и записал его назад в базу, зачем мне цирк устраивать?
zharenkov Уровень 30
25 декабря 2014
а как же, например, фреймворки типа seam, где используются java бины, у которых по спецификации должны быть гетеры-сетеры? а hibernate и прочие прелести маппинга в бд? с таким подходом код станет нечитаем и несопровождаем на мой взгляд. А в некоторых случаях и вовсе не взлетит.
alexnjc Уровень 31
24 декабря 2014
То уже для опытных прогеров. Остальным только усложнит жизнь.
CynepHy6 Уровень 34
18 декабря 2014
дальше. Собака — это сущность базы данных (база данных собак). есть поля: рост, вес, возраст, кличка, дети, родители, хозяин, адрес проживания, любимые игры, характер. тут тоже устраивать игры с кормежкой собаки и даванием мячика?
вывод для себя сделал — статья бесполезная и вредная, написана чтобы запутать и сбить молодого разработчика с пути)
CynepHy6 Уровень 34
17 декабря 2014
плохая статья. только добавляет непонимания и безобразия в мой хаос java-знаний.
насчет собаки. что если собака это герой в игре и по мере прокачки он увеличивает свои параметры. каждый раз создавать новую собаку? или по воздействием каких-то сил его параметры изменяются. что опять new Собака и куча параметров в конструкторе?