Статьи

Геттеры / сеттеры.

Существует старая дискуссия, начатая в 2003 году Алленом Холубом в этой статье « Почему методы получения и установки являются злой известной статьей о том, является ли получение и установка методов анти-паттерном и его следует избегать или если это то, что нам неизбежно необходимо в объектно-ориентированном виде» программирование. Я попытаюсь добавить свои два цента к этой дискуссии.

Суть следующего текста такова: добытчики и установщики — ужасная практика, и те, кто ее использует, не могут быть оправданы. Опять же, чтобы избежать недоразумений, я не говорю, что следует избегать get / set, когда это возможно. Нет. Я говорю, что вы никогда не должны иметь их рядом с вашим кодом.

Объектно-мышление-на-DAVID-запад Достаточно высокомерен, чтобы привлечь ваше внимание? Вы использовали этот шаблон get / set в течение 15 лет, и вы уважаемый архитектор Java? И ты не хочешь услышать эту чушь от незнакомца? Ну, я понимаю твои чувства. Я чувствовал почти то же самое, когда наткнулся на объектное мышление Дэвида Уэста, лучшую книгу об объектно-ориентированном программировании, которую я когда-либо читал. Поэтому, пожалуйста. Успокойся и попытайся понять, пока я пытаюсь объяснить.

Существующие аргументы

В объектно-ориентированном мире есть несколько аргументов против «аксессоров» (другое название для методов получения и установки). Все они, я думаю, недостаточно сильны. Давайте кратко пройдемся по ним.

Спросите, не говорите: Аллен Голуб говорит: «Не спрашивайте, какая информация вам нужна для работы; попросите объект, у которого есть информация, сделать работу за вас ».

Принцип нарушенной инкапсуляции: объект может быть отделен от других объектов, так как они могут вводить в него любые новые данные через сеттеры. Объект просто не может достаточно безопасно инкапсулировать свое собственное состояние, поскольку любой может его изменить.

Открытые детали реализации: если мы можем извлечь объект из другого объекта, мы слишком полагаемся на детали реализации первого объекта. Если завтра это изменит, скажем, тип этого результата, мы должны также изменить наш код.

Все эти обоснования разумны, но они упускают главное.

Фундаментальное заблуждение

Большинство программистов считают, что объект — это структура данных с методами. Я цитирую « добытчиков и сеттеров не зло» , статья Божидара Божанова:

Но большинство объектов, для которых люди генерируют геттеры и сеттеры, являются простыми держателями данных.

Это заблуждение является следствием огромного недопонимания! Объекты не являются «простыми держателями данных». Объекты не являются структурами данных с прикрепленными методами. Эта концепция «держателя данных» пришла к объектно-ориентированному программированию из процедурных языков, особенно C и COBOL. Я повторю еще раз: объект — это не набор элементов данных и функций, которые ими манипулируют. Объект не является объектом данных.

Что тогда?

Мяч и собака

В настоящем объектно-ориентированном программировании объекты — это живые существа, такие как вы и я. Это живые организмы со своим поведением, свойствами и жизненным циклом.

Может ли живой организм иметь сеттер? Вы можете «поставить» мяч на собаку? На самом деле, нет. Но это именно то, что делает следующее программное обеспечение:

1
2
Dog dog = new Dog();
dog.setBall(new Ball());

Как это звучит?

Можете ли вы получить мяч от собаки? Ну, вы, вероятно, можете, если она съела это, и вы делаете операцию. В таком случае, да, мы можем «достать» мяч у собаки. Вот о чем я говорю:

1
2
Dog dog = new Dog();
Ball ball = dog.getBall();

Или еще более нелепый пример:

1
2
Dog dog = new Dog();
dog.setWeight("23kg");

Можете ли вы представить эту сделку в реальном мире?

Похоже ли это на то, что вы пишете каждый день? Если да, то вы процедурный программист. Признай это. И вот что Дэвид Уэст говорит об этом на странице 30 своей книги:

Первый шаг в превращении успешного процедурного разработчика в успешного разработчика объектов — это лоботомия.

Вам нужна лоботомия? Ну, я определенно нуждалась в одном и получила его, читая Уэст- объектное мышление .

Мышление объекта

Начните думать как объект, и вы сразу же переименуете эти методы. Вот что вы, вероятно, получите:

1
2
3
Dog dog = new Dog();
dog.take(new Ball());
Ball ball = dog.give();

Теперь мы относимся к собаке как к настоящему животному, которое может отобрать у нас мяч и вернуть его, когда мы попросим. Стоит отметить, что собака не может вернуть NULL . Собаки просто не знают, что такое NULL ! Объектное мышление немедленно удаляет пустые ссылки из вашего кода.

Рыба по имени Ванда (1988) Чарльз Крайтон

Рыба по имени Ванда (1988) Чарльз Крайтон

Кроме того, объектное мышление приведет к неизменности объекта, как в примере с «весом собаки». Вы бы переписали это так:

1
2
Dog dog = new Dog("23kg");
int weight = dog.weight();

Собака является неизменным живым организмом, который не позволяет никому снаружи изменить свой вес, размер, имя и т. Д. Она может сообщить, по запросу, свой вес или имя. Нет ничего плохого в открытых методах, которые демонстрируют запросы на определенные «внутренности» объекта. Но эти методы не являются «получателями» и никогда не должны иметь префикса «get». Мы ничего не «получаем» от собаки. Мы не получим ее имя. Мы просим ее назвать нам ее имя. Увидеть разницу?

Мы не говорим здесь и о семантике. Мы отличаем мышление процедурного программирования от объектно-ориентированного. В процедурном программировании мы работаем с данными, манипулируем ими, получаем, устанавливаем и удаляем при необходимости. Мы отвечаем, а данные — просто пассивный компонент. Собака для нас ничего не значит — это просто «держатель данных». У него нет своей жизни. Мы можем получить от него все, что необходимо, и внести в него любые данные. Так работают C, COBOL, Pascal и многие другие процедурные языки (ред.).

Напротив, в истинно объектно-ориентированном мире мы относимся к объектам, как к живым организмам, с их собственной датой рождения и моментом смерти — с их собственной индивидуальностью и привычками, если хотите. Мы можем попросить собаку предоставить нам некоторые данные (например, ее вес), и она может вернуть нам эту информацию. Но мы всегда помним, что собака является активным компонентом. Она решает, что будет после нашей просьбы.

Поэтому концептуально некорректно иметь какие-либо методы, начинающиеся с set или get в объекте . И дело не в нарушении инкапсуляции, как утверждают многие. Вы думаете, как объект или все еще пишете COBOL в синтаксисе Java.

PS. Да, вы можете спросить, — как насчет JavaBeans, JPA, JAXB и многих других API Java, которые используют нотацию get / set? Как насчет встроенной функции Ruby, которая упрощает создание методов доступа? Ну, все это наша беда. Гораздо проще остаться в примитивном процедурном мире COBOL, чем по-настоящему понять и оценить прекрасный мир истинных объектов.

PPS. Забыл сказать, да, внедрение зависимостей через сеттеры также является ужасным анти-паттерном. Об этом в одном из следующих постов!

Похожие сообщения

Вы также можете найти эти сообщения интересными:

Ссылка: Геттеры / сеттеры. Злой. Период. от нашего партнера JCG Егора Бугаенко в блоге « О программировании» .