Builders and Manipulators

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

Вот простой принцип для именования методов в ООП, которому я пытаюсь следовать в своем коде: это глагол, если он выполняет действия, это существительное, если он создает. Вот и все. Никаких промежуточных вариантов. Методы, такие как saveFile() или getTitle(), не подходят и должны быть переименованы и отрефакторены. Более того, методы, которые “выполняют действия”, всегда должны возвращать void, например print() или save(). Позвольте мне объяснить.

Прежде всего, я должен сказать, что эта идея очень похожа на идею, предложенную Бертраном Мейером в его книге Object Oriented Software Construction, где он предлагает разделить методы объекта на две четко отделенные категории: запросы и команды.

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

Очевидно, это “конструктор” (или “запрос” по терминологии Мейера). Я прошу книгу, и она мне предоставляется. Проблема, однако, заключается в названии метода. Он называется “найти”, что подразумевает, что я знаю, как будет обработана книга. Она будет найдена.

Однако, так мы не должны обращаться с нашими объектами. Мы не должны указывать им, как выполнять работу, которую мы хотим, чтобы они делали. Вместо этого мы должны позволить им решить, будет ли книга найдена, сконструирована или возможно взята из кэша памяти. Когда мы делаем запрос, мы должны сказать, какой результат мы ищем, и позволить объекту принять решение о способе построения этого результата. Гораздо более подходящим названием для этого метода было бы book():

Правило заключается в следующем: строитель - всегда существительное. Если метод возвращает что-то, это должно быть существительное. Предпочтительно, имя метода должно объяснять, что он возвращает. Если это книга, назовите его book(). Если это файл, назовите метод file(), и так далее. Вот несколько хороших примеров строителей.

Здесь, напротив, приведены несколько примеров плохо названных строителей:

В названии строителя нет места для глагола!

Это не только о названии, кстати. Строитель, поскольку его название не содержит глагола, не должен вносить изменения в инкапсулированные сущности. Он может только создавать или находить что-то и возвращать это. Точно так же, как чистая функция, он не должен иметь побочных эффектов.

Далее, есть “манипуляторы” (или “команды” в терминах Мейера). Они выполняют работу для нас, модифицируя сущности, которые инкапсулирует объект. Они противоположны строителям, потому что они фактически вносят изменения в абстрагированный объектом мир. Например, мы просим Bookshelf добавить новую книгу в себя:

Метод добавляет книгу в хранилище. Как именно будет изменено хранилище, мы не знаем. Но мы знаем, что поскольку имя метода является глаголом, будут произведены изменения.

Также, манипуляторы не должны возвращать ничего. Мы всегда видим, что их ответ имеет тип void. Это нужно в основном для того, чтобы отделить императивную часть кода от декларативной части. Мы либо получаем объекты, либо указываем им, что делать. Необходимо избегать смешивания этих действий в одном методе.

Цель этих правил - упростить код. Если вы следуете им, и все ваши строители только возвращают объекты, а ваши манипуляторы только изменяют мир, весь дизайн станет более понятным. Методы будут меньше, а их названия - короче.

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

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

Более подробное обсуждение этой проблемы вы можете найти в книге Elegant Objects, том 1, раздел 2.4.

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-05 at 22:14

sixnines availability badge   GitHub stars