Данная статья является конспектом книги "Чистый Код" Роберта Мартина и моим пониманием того, каким Чистый Код должен быть. Тут нет разделов о тестировании, TDD, о том какая должна быть архитектура и т.д. Здесь все только о том, каким должен быть Чистый Код.





Да, возможно, тема Чистого Кода уже заезженна, но тем не менее еще не все с ним знакомы и, тем более, я не встретил аналогов контента, который содержится в моей статье.


Общее


Нет истинного пути и решения. Есть тот, который лучше всего подходит для решения конкретной задачи.


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


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


Перед тем, как отправить задачу в релиз — проверь правильно ли она работает. Нет ли в ней ошибок. Это касается даже тех коммитов, которые отправляются в твою ветку. Самый идеальный сценарий — тот, в котором никто не смог найти ошибки в функционале, который ты разрабатывал.


Всегда задумывайся о том как можно сделать твой код проще, чище и читабельнее.


  • Какие кейсы могут быть у задачи?
  • Все ли я учел?
  • Что может пойти не так?
  • Что можно объединить?
  • Есть ли похожий функционал?
  • Что тут лишнее?
  • Как сделать проще?
  • Как сделать читабельнее?
  • Как сделать понятнее?

Чистый Код


Как писать чистый и хороший код? Это похоже на написание книги. Сначала ты делаешь черновик и потом причесываешь его до того состояния, в котором тебе было бы приятно его читать. Всегда помни, что твой код должен рассказывать историю происходящего, чтобы читатель мог ее понять.


Под сущностью понимается — интерфейс, класс, метод, переменная, объект и т.д.


  • Чистый код простой, выразительный и направлен на конкретную задачу.
  • Чистый код читается легко, как проза. Если это не так, то его стоит рефакторить.
  • Чистый код легко изменять. Он не должен быть жестко завязан на куче сущностей. Любую сущность можно легко изменить.
  • Чистый код намного лучше проходит ревью. Если ревью проходит с огромным количеством комментариев, то он не чистый и его надо рефакторить.
  • Чистый код всегда выглядит так, словно над ним очень долго трудились. Какие бы пути для его улучшения ты не искал, ты все равно придешь к тому, что этот код лучший. Соответственно, чистый код — продуманный до всех мелочей.
  • Правило бойскаута: Оставь место стоянки чище, чем оно было до тебя. Это легко перекладывается и на программирование. Видишь грязный код? Сделай его чище, пока решаешь свою задачу. Не стоит увлекаться этим и если грязный код очень грязный, то стоит выделить отдельную задачу и время для его очистки.
  • Не бойся делать изменений. Если ты хочешь их сделать, то значит у тебя есть на то причины, а значит ты сделаешь код лучше и чище. Тем более тесты покажут нет ли ошибок в твоем коде (при условии, что они вообще есть).
  • Любая сущность должна отвечать за один функционал и только за него. И она должна выполнять его хорошо. Single Responsibility.
  • Если сущность отвечает сразу за два и более действий, то её функционал нужно разделять.
  • Код должен читаться сверху вниз.
  • В хорошей и грамотной архитектуре внесение изменений обходится без значительных затрат и усилий.
  • Удаляй мертвый код. Мертвый код это код, который не будет вызван ни при каких условиях или код, который нигде не используется.

Наименования и разделения


  • Используй понятные и удобнопроизносимые имена для любых сущностей. Они должны описывать почему эта сущность существует, что она делает и как используется.
  • Не бойся тратить время на выбор лучшего и понятного имени. Ты выиграешь в будущем при работе или чтении этого кода.
  • Если название сущности не соответствует еe функционалу или по названию не понятно, что сущность делает, то еe надо переименовать в самое понятное название. Если этого сделать невозможно, то значит с еe функционалом что-то не так и еe надо рефакторить.
  • Сущность, которая имеет в названии "And", "With" — нарушает Single Responsibility. Функционал такой сущности стоит разделять. Но этим правилом стоит иногда пренебрегать.
  • Непонятные тексты, строки стоит выносить в переменные и давать им понятные названия.
  • Названия методов должны содержать глагол, который описывает, что этот метод делает и ключевое слово с которым работает данный метод. Если в названии метода нет глагола, то эта сущность не должна быть методом или ему нужно дать правильное название.
  • Нужно избегать одинаковых наименований для двух разных целей.
  • Если сущность имеет схожее с другой сущностью название, то скорее всего их функционал очень сильно похож и их нужно объединить? Если нет, то их названия нужно менять так, чтобы они не были похожими.
  • Если ты мысленно переименовываешь сущность, когда читаешь код, чтобы тебе было понятнее понимать её функционал, то переименуй её в это мысленное название.
  • Выбери одно слово для одной концепции. Сложно будет понимать функционал, когда у тебя есть fetch, retrieve и get в названиях. Пусть лучше везде будет get.
  • Длинное и понятное имя лучше, чем короткое, но непонятное.

Функции


  • Функции должны быть короткими и компактными.
  • Функции должны быть очень короткими и очень компактными.
  • Приблизительный максимум 20 строк и 150 символов в одной строке, если не влезает, то нужно разделять.
  • Функция должна выполнять только одну операцию.
    • Она должна выполнять её хорошо и ничего другого она делать не должна.
    • Если функция выполняет только те действия, которые находятся на одном уровне абстракции, то функция выполняет одну операцию.
    • Чтобы определить выполняет ли функция более одной операции, попробуй извлечь из нее другую функцию, которая не будет являться простой переформулировкой реализации.
  • Любые условные операторы с длинными выборами через switch-case, if-else должны разделяться или объединяться без дублирования, возможно на классы с реализациями, а выбор реализации передать базовому классу, фабрике или еще кому-то.
  • If, else, while и т.д. должны содержать вызов одной функции. Так будет читабельнее, понятнее и проще.
  • Идеальное количество входных аргументов для функции = 0. Если входных аргументов больше трех, то стоит задуматься каким образом лучше от них избавиться, например, создать класс для этих аргументов.
  • Чем больше входных аргументов, тем тяжелее понимается функция.
  • Функция в которую передается аргумент-флаг, от которого зависит работа функции говорит о том, что функция выполняет более одной операции. Такие функции следует разбить на две и вызывать их уровнем выше.
  • Функция, которая изменяет входной аргумент, должна отдавать ссылку на измененный объект, а не просто изменять без возврата. String transform(String text)
  • Если функция, должна изменять входной аргумент, то пусть она изменяет состояние своего объекта-владельца.
  • Если входной аргумент функции не должен меняться (и используется дальше в коде), то следует скопировать значение аргумента и внутри функции работать с копией.
  • Вместо return null лучше использовать пустой объект — Collection.empty() или null-объект -EmptyObject().
  • Всегда старайся использовать нестатические функции. Если это невозможно, то используй статические.
  • Если есть код, который должен следовать один за другим, то передавай результаты первой функции во вторую, чтобы кто-нибудь не изменил последовательность вызовов.
  • Используй полиморфизм вместо if/else или switch/case или when.
  • Избегай отрицательных условий.

Комментарии


  • Не используй комментарии, если ты можешь использовать функцию или переменную вместо этого.
  • Не комментируй плохой код — перепиши его. Не стоит объяснять, что происходит в плохом коде, лучше сделать его явным и понятным.
  • Комментарии можно использовать для передачи какой-то информации, предупреждения о последствиях, но не для объяснения того, как работает код.
  • Используй TODO и FIXME в тех случаях, когда нужно пометить, что код нуждается в доработке, но сейчас нет ресурсов на это.
  • Используй //region REGIONNAME //endregion REGIONNAME, а если используешь, то подумай можно ли разделить region на сущности.
  • Документируй код, который является сложным, но чистым.
  • Не оставляй старый закомментированный код. Ты можешь найти его в истории коммитов, если необходимо.
  • Комментарии должны быть краткими и понятными. В комментариях с информацией не должно быть много информации. Все должно быть кратко и по делу.

Форматирование и правила


  • Соблюдай codestyle, принятый на проекте.
  • Соблюдай правила, принятые в команде.
  • При соблюдении форматирования и codestyle код будет читаться проще и лучше. Ведь не зря книгу отдают на редакцию, перед тем, как её издавать.
  • Нужно иметь автоматические средства, которые будут форматировать код за тебя.
  • Файл с исходным кодом должен быть как газетная статья. Есть заголовок, краткое описание в виде параметров и содержание в виде функций. Если это не так, то стоит изменить форматирование.
  • Сущности, связанные друг с другом, должны находиться рядом, например, в одном package, чтобы было проще навигировать по коду.
  • Переменные(поля) класса должны находиться вверху класса.
  • Переменные методов должны находиться ближе к своему месту использования.
  • Функции должны находиться в порядке вызова. Если одна вызывает другую, то вызывающая функция должна находиться над вызываемой. C другой стороны, приватные функции более низкого уровня могут находиться внизу файла и не мешать пониманию кода высокого уровня. Но я предпочитаю первый способ.

Объекты и структуры данных


  • Ты должен работать с абстракциями, чтобы реализацию можно было легко изменить.
  • Ты должен работать с абстракциями, потому что клиент, использующий функционал, не должен знать о деталях реализации, он должен знать какую реализацию в каком случае использовать.
  • Ты должен предоставлять API, с которым стоит работать и скрывать детали реализации, структуру. Так будет проще работать с такими сущностями и добавлять новые виды поведений, функционала и реализаций.
  • DTO — Data Transfer Object. Класс, который содержит только данные и никакого функционала. Нужен для того, чтобы передавать какие-то данные. Объект такого класса должен быть неизменяемым.

Классы


  • Классы должны быть компактными.
  • Классы должны быть еще компактнее.
  • Имя класса должно описывать его ответственности. Отсюда можно и вычислить размер класса.
  • Функционал класса должен четко соответствовать и вписываться в название класса.
  • Разделяй связанность на маленькие классы. Жесткой и обильной связанности не должно быть — это усложняет поддержку и развитие проекта.
  • Помни о Single Responsibility. Сущность должна иметь одну и только одну причину для изменения.
  • Соблюдай инкапсуляцию. Ослабление инкапсуляции всегда должно быть последней мерой.
  • Обычно мы объявляем переменные и вспомогательные функции приватными, но иногда их нужно объявлять protected и иметь возможность обратиться к ней из теста.
  • Если группа функций относится к определенному функционалу, то эту группу функций можно и нужно выделить в отдельный класс и использовать его экземпляр.

Обработка ошибок


  • Используй Exceptions вместо возвращения кодов ошибок.
  • Обработка ошибок — это одна операция. Если в функции есть ключевое слово try, то после блоков catch/finally ничего другого в функции быть не должно.
  • Если у тебя есть enum, который перечисляет ошибки, то от него лучше избавиться и вместо него использовать исключения.
  • Используй unchecked exceptions, чтобы явно указать на место в котором есть проблемы. Такие ошибки не нужно отлавливать, вместо этого нужно написать код так, чтобы этой ошибки никогда не было.
  • Передавай достаточное количество информации вместе с выбросом исключения, чтобы потом пользователи твоего кода могли понять, что же действительно произошло.
  • Вместо условных операторов с обработкой ошибок лучше выбрасывать исключения и обрабатывать их.
  • Не передавай null куда-либо. Старайся этого максимально избежать.
  • Обработка ошибок — это отдельная задача и не относится к основной логике программы.

Границы


  • Мы всегда используем какие-либо библиотеки, которые чаще всего дают нам слишком широкий, слишком маленький функционал или конфликтуют с ожидаемым функционалом, что делает код грязнее в его конечном использовании. Избежать этого можно просто применив паттерны типа Decorator, Adapter, Facade или другие.
  • Бывают ситуации, когда тебе нужно работать с функционалом, который находится в разработке или пока что не адаптирован для использования в продакшен коде. В этом случае стоит представить чего ты ждешь от библиотеки/этого функционала и написать свой интерфейс или создать сущность с которыми ты будешь работать в своем проекте так, как тебе нужно. Когда библиотека доделается и станет стабильной, ты адаптируешь её под свои готовые структуры и использовать уже готовый функционал.

Послесловие


В данной статье представлены лишь рекомендации к написанию Чистого Кода. Разумеется, ими можно пренебрегать. Вам лишь стоит понять, что у любого вашего решения должны быть аргументы в пользу него.

Комментарии (44)


  1. ianzag
    24.09.2018 20:49
    -1

    Откуда стойкое обращение на Ты :-? Это вроде не men's health & K


    1. tanchuev Автор
      24.09.2018 21:14
      +1

      Это лишь способ повествования) Каждый, кто читает что-либо, никогда не обращается к себе на вы)


  1. Oskal174
    24.09.2018 21:09

    Достойная выжимка, ничего нового, но конспект отличный. Можно распечатывать и класть на рабочий стол


    1. tanchuev Автор
      24.09.2018 21:20

      Спасибо) Собственно, с этой целью и создавался данный материал) Чтобы под рукой всегда была краткая памятка того, как стоит писать код)


      1. gangstarcj
        24.09.2018 21:50

        Спасибо вам за такой труд.
        Часто не хватает таких конспектов по книгам. Самому составлять очень лень(


  1. Hokum
    24.09.2018 21:57

    Отличный труд! Но, мне кажется, лучше стараться делать функции чистыми и отказываться от модификации передаваемых аргументов. Если хочется изменить входной аргумент — пусть функция вернет модифицированную копию. Это не всегда возможно, но к этому стоит стремиться. Такой код проще читать и проще тестировать.


    1. vanxant
      26.09.2018 01:31

      … а еще он отлично жрет процессорное время и память (реклама производителей железок)


    1. worldmind
      26.09.2018 14:10

      Так там так и написано


  1. sentyaev
    24.09.2018 23:14
    +1

    Не забудьте после каждого пункта поставить запятую и дописать: «but it depends...»


  1. berezuev
    24.09.2018 23:51

    Используй TODO и FIXME.

    Крайне сомнительная рекомендация. Либо делай сразу, либо заводи задачу там, где она не потеряется. А вот уже ссылку на задачу можно добавить в TODO.


    1. Slonopotamych
      25.09.2018 10:29

      Я вот тоже не очень понимаю, зачем приниципиально оставлять TODO в коде, а не создавать задачу в трекере задач. Недавно только чистили код от TODO, которые лежали просто годами.


      1. khim
        25.09.2018 13:16

        А TODO и должно ссылаться на задачу. Например сегодня мы работаем с x86, но в будущем нам, возможно, потребуется поддержать ARM. Заводится задача по поддержке ARM'а и всё TODO ссылаются на неё.

        Можно ли сразу поддержать ARM? Можно, но не нужно: полноценная поддержка усложнит разработку в 1.5-2 раза, а если вы оставите «мёртвый код» без тестов и/или пользователей, то обнаружите, что к моменту, когда он понадобится — код «протухнет». TODO «протухают» тоже, конечно, но худшее, что с ними может произойти — они станут непонятными и вы их выкините, а странный код, появившийся ради задачи, от которой, в итоге, отказались будет вам мешать долгие годы — так как без комментариев все будут его видеть, но никто не будет понимать — зачем он там.


        1. Slonopotamych
          25.09.2018 13:26

          Без этого вашего пояснения фраза

          Используй TODO и FIXME.

          вредна. Сегодня с утра один наш разработчик скинул в общий чат скриншот этой статьи с этой фразой. Тогда как у нас в компании всего месяц назад с моей подачи запретили оставлять в коде TODO без указания номера задачи.


      1. Jopezzia
        26.09.2018 14:05

        Ну, можно создать связку, которая переводит TODO сразу в трекер, для этого вроде уже существуют инструменты


    1. tanchuev Автор
      25.09.2018 10:33

      Это призыв к использованию TODO и FIXME в тех случаях, когда нужно пометить, что код нуждается в доработке.


    1. deniss-s
      25.09.2018 12:16
      +1

      Я часто использую TODO и FIXME, чтобы потом вернуться к месту на которое сейчас не является приоритетным. Проект настроен так, что не собирается если в коде где-то есть эти метки, что помогает не забыть о том, что хотел сделать и не сделал.


    1. unclejocker
      25.09.2018 13:48

      В MS VS комбинация кнопок ctrl + w,t открывает окно со списком всех TODO в проекте. В других IDE наверное тоже есть что то подобное.


  1. moonster
    25.09.2018 01:16

    Чтоб научиться писать хороший код — нужно много писать и читать код, периодически возвращаясь к доработке уже написанного. Без такой практики этот список не поможет, а вот качестве дополнения будет очень полезен.


  1. ttmt
    25.09.2018 10:37

    >>Обработка ошибок — это одна операция. Если в функции есть ключевое слово try, то после >>блоков catch/finally ничего другого в функции быть не должно.
    Предполагает вынос блока try в отдельную функцию. Имеет ли смысл выносить в отдельную функцию если внутри блока одна строчка


    1. Danik-ik
      26.09.2018 18:50

      Автор утверждает, что имеет, насколько помню. Я с этим согласен. Есть метод, который работу работает. Есть тот, который ошибки ловит. И второй не разобран на части первым. И вообще это разные задачи, зачем их перемешивать?


      Привыкнуть только никак не могу. Среда разработки и язык не располагают к хоть сколько нибудь быстрому и / или удобному рефакторингу. В Джаву хочу, на Идею… И выделять методы, выделять методы...


  1. Xuxicheta
    25.09.2018 12:57

    Идеальное количество входных аргументов для функции = 0. Если входных аргументов больше трех, то стоит задуматься каким образом лучше от них избавиться, например, создать класс для этих аргументов.

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


    1. nlinker
      25.09.2018 17:23

      +1
      Идеальное — это 1. Что-то вошло — что-то вышло. Прямолинейный поток выполнения, композиция, лёгкость переиспользования. Когда у функции нет аргументов, это значит, что она берёт входную информацию из окружения, а значит имеет побочный эффект. Такую архитектуру нельзя называть «чистой».


      1. mayorovp
        25.09.2018 17:46

        this для методов — это не окружение, а один из аргументов.


    1. mayorovp
      25.09.2018 17:44

      А почему методы не могут быть чистыми?


  1. Avitale
    25.09.2018 13:48

    Вместо return null лучше использовать пустой объект — Collection.empty() или null-объект — EmptyObject().

    Объясните, почему так? До настоящего момента приходилось встречать только вариант с null, чем он хуже?


    1. siziyman
      25.09.2018 13:57

      Ну про EmptyObject неоднозначно, а вот пустая коллекция точно реже ведёт к ошибкам (притом не факт, что очевидным), чем null.


    1. Neikist
      25.09.2018 14:12

      Как по мне проще для понимания и использования. В какой то статье (или книге) приводился пример как НЕ надо возвращать значение в стиле:
      1) Нет друзей — возвращаем null;
      2) Есть один друг — возвращаем собственно объект;
      3) Друзей больше одного — возвращаем коллекцию объектов.
      Мало того что на null например можно попросту забыть проверить, или ожидать только null или коллекцию не учтя случай с одним объектом, так еще и разное поведение лепить в зависимости от типа возвращаемого значения.
      Тогда как при пустой коллекции или коллекции с одним элементом нам бы не пришлось в клиентском коде городить отдельную логику.


      1. ookami_kb
        25.09.2018 14:47
        +1

        Все так. Говоря более формальным языком, пустой список – это константа для монады "список".


  1. khim
    25.09.2018 15:45

    По хорошему к этому манифесту книга должна прилагаться. Ибо каждый пункт имеет области применимости — тупое следование этим правилам ни к чему хорошему не приведёт…

    То есть каждое правило применимо, ну, скажем, в 99% случаев, но поскольку у нас тут чуть больше, чем полсотни правил, то в половине мест хотя бы одно из правил стоит нарушить…

    Про это недавно отдельная статья была


  1. ta6aku
    25.09.2018 15:49

    Я понимаю что ООП, и во всех учебниках написано, но чем автору насолили статические методы? Про состояния понятно, но с методами то в чем проблема?


    1. poxvuibr
      25.09.2018 16:05

      В том, что статические методы могут ссылаться на статические поля
      В том, что в статический метод нельзя подставить свою реализацию для тестирования


  1. cyberzx23
    25.09.2018 16:19
    +1

    «Идеальное количество входных аргументов для функции = 0»
    Очень спорное утверждение.


    1. tanchuev Автор
      25.09.2018 18:22

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


    1. sentyaev
      25.09.2018 18:27

      Идеальный код — это код который не написан, в нем нет багов и его не нужно тестировать и поддерживать.


  1. unabl4
    25.09.2018 17:11

    Приблизительный максимум 20 строк и 150 символов в одной строке

    150 символов — это явный перебор. Большенство редакторов ставят отсечку почти на половине от этой величины. И даже это многовато.

    Идеальное количество входных аргументов для функции = 0

    Если это foo/bar/baz для hello world — да, а так нет.

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

    Не обязательно. Это зависит от ЯП.

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

    Это не всегда зависит от пожеланий одного разработчика. Время на рефакторинг далеко не всегда удаётся выбить.

    If, else, while и т.д. должны содержать вызов одной функции. Так будет читабельнее, понятнее и проще.

    Вообще не обязательно. Очень сомнительное правило.


  1. XopHeT
    25.09.2018 17:13

    Не обязательно. Это зависит от ЯП.

    Пример можно?
    Я всего на нескольких ЯП пишу. Ни в одном из них нет ограничений на имя метода.

    Если это foo/bar/baz для hello world — да, а так нет.

    • start() — идеальный метод;
    • start(speed) — отличный метод;
    • start(speed, direction, path) — похуже. Сходу и не вспомнишь, в какой последовательности параметры передавать;
    • start(speed, direction, path, maxBias, onError) — комментарии, думаю, излишни.


    1. unabl4
      25.09.2018 17:37

      Пример можно?
      Я всего на нескольких ЯП пишу. Ни в одном из них нет ограничений на имя метода.

      Ruby. Вполне характерно писать вообще без глаголов или глагольных префиксов.
      И если чистые глаголы это ещё куда не шло (#call, #perform или что-то в этом роде), то глагол + ключевое слово — это скорее code smell, чем норма.
      И это не ограничение, а соглашение.

      start() — идеальный метод;
      start(speed) — отличный метод;
      start(speed, direction, path) — похуже. Сходу и не вспомнишь, в какой последовательности параметры передавать;
      start(speed, direction, path, maxBias, onError) — комментарии, думаю, излишни.

      Если аргументов больше ~3 (это эмпирически) — это уже code smell.
      Разумно применять keyword-аргументы, если возникает путаница.


    1. cyberzx23
      25.09.2018 18:10
      +2

      Например возьмите любую функцию из C math.h. Там нет глаголов, только существительные: sqrt, sin. log, exp, round и
      Если следовать правилам чистого кода, то надо было их назвать calc_sqrt, calc_sin, find_exp и т.д. Делает ли это код чище? Ничуть.


      1. XopHeT
        26.09.2018 15:49

        Вы говорите о «общепринятых» названиях, которые

        • применяются в т.ч. в математике
        • приживались годами

        и поэтому не вызывают дополнительных вопросов.
        А вот на заре моей программистской деятельности SQR и SQRT было сложно запомнить.
        Полная запись GetSqareRoot (вполне вероятно) вызывала бы меньше вопросов поскольку не является «набором несвязанных букв» (как я тогда воспринимал) а вполне осмысленным словосочетанием.


        1. Neikist
          26.09.2018 15:58

          Да, помню свои первые попытки программировать. Особенно если учесть что английский я знал никак — почти все для меня было магическим сочетанием символов. Тогда это здорово притормозило.


  1. XopHeT
    25.09.2018 17:47

    Ruby. Вполне характерно писать вообще без глаголов или глагольных префиксов.

    Я не сталкивался с Ruby.
    Например, как геттеры от сеттеров отличаются?

    И если чистые глаголы это ещё куда не шло (#call, #perform или что-то в этом роде), то глагол + ключевое слово — это скорее code smell, чем норма.

    Из текущего:
    Есть запрос (Request), который содержит список параметров (Parameter).
    У Request есть метод для добавления параметра в список.
    Назови я его add никто не поймет что именно добавляется.
    Назови я его addParameter — даже не знакомому с архитектурой человеку будет понятно что именно добавляется в Request.

    Будет ли имя addParameter «запахом»?


    1. mayorovp
      25.09.2018 18:17

      parameters.add выглядит немного лучше нежели addParameter


    1. FreeNickname
      25.09.2018 21:46

      Я не сталкивался с Ruby.
      Например, как геттеры от сеттеров отличаются?

      Немного вклинюсь к вам просто разнообразия ради)
      Objective-C
      getter: `param`;
      setter: `setParam:(value)` (синтаксис неточный)
      Т.е. функция-геттер не имеет глагола.


    1. unabl4
      26.09.2018 01:45

      Например, как геттеры от сеттеров отличаются?

      # это геттер
      def first_name
        @first_name
      end
      
      # это сеттер
      def first_name=(val)
        @first_name = val
      end
      

      Вот и всё различие.
      На самом деле таким макаром геттеры/сеттеры не пишут, только если надо переопределить их стандартное поведение.
      Дефолтную пару можно сгенерировать с помощью одной строчки
      attr_accessor :first_name
      


      Будет ли имя addParameter «запахом»?

      Скорее да, чем нет.
      Из Вашего примера, скорее всего данный функционал будет имплементирован немного по-другому.
      request.params[key]=value

      params — это просто словарь, к которому можно обратиться напрямую.
      "[]=(key,value)" — это тоже метод.

      P.S. Проверил — так примерно в рельсах и сделано. Только там params — это экземпляр класса Parameters, который в свою очередь ведёт себя как словарь.