В статье "Пережить великую нехватку переменных" (Outliving the Great Variable Shortage) Тим Оттингер формулирует закон Кёрли:

«Переменная должна означать только что-то одно. Она не должна означать "что-то при таких-то условиях" и иметь разный смысл в разных обстоятельствах. Также она не должна иметь два смысла одновременно. "За двумя зайцами погонишься – ни одного не поймаешь". Переменная должна означать что-то одно все время своего существования»

Седого ковбоя Кёрли Уошбурна в комедии 1991 года "Городские пижоны" сыграл великий Джек Пэланс, ныне покойный. Закон Кёрли обозначен в небольшом диалоге из этого фильма (привожу перевод диалога от ТВ5 в сокращении):

Джек Пэланс в роли Кёрли Уошбурна, "Городские пижоны" (1991)
Джек Пэланс в роли Кёрли Уошбурна, "Городские пижоны" (1991)


Кёрли: Знаешь, в чем секрет жизни? В одной вещи. Всего в одной. Есть только она, а все остальное – вранье.
Митч: Что же это за "вещь"?
Кёрли: [улыбаясь] Это тебе самому решать.

Прим. пер.: на мой взгляд, перевод на русский немного лишает смысла исходную фразу и "игру слов". В оригинале "one thing" можно перевести не только как "одна вещь", но и как "что-то", особенно в контексте фразы "do one thing" – что можно перевести как "делай одно дело", "делай одну вещь", или, наконец – "делай что-то одно".


Закон Кёрли: Делай что-то одно отражён в нескольких современных принципах разработки ПО:

Если есть больше одного способа сделать одно и то же, в какой-то момент два или три способа, скорее всего, перестанут идти в ногу друг с другом. Даже если этого не произойдет, Вам будет гарантирована головная боль с их параллельной поддержкой в случае возникновения изменений. А изменения будут. Не повторяйтесь – это важно, если Вам нужно гибкое и поддерживаемое ПО.

Каждое поведение должно быть объявлено только один раз. Это одна из основных целей, если не главная цель во время рефакторинга. Цель проектирования состоит в устранении повторяющихся поведений, как правило, путем их слияния или замены нескольких похожих под объединяющей их абстракцией.

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


Несмотря на то что закон Кёрли больше про нормализацию и устранение избыточности, "делать что-то одно" куда сложнее, чем, например "делать что-то только один раз", как было описано выше. Он куда глубже. Боб Мартин назвал это принципом единой ответственности (SRP):

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

Рассмотрим для примера следующий класс:

class Employee
{
    public Money calculatePay()
    public void save()
    public String reportHours()
}

Этот класс нарушает SRP, потому что у него есть три причины для изменения. Этими причинами являются изменения:

  1. Бизнес-логики, связанной с расчётом зарплаты.

  2. Схемы базы данных.

  3. Формата строки, в которой сообщается о часах.

Нам не нужно, чтобы эти три совершенно разных причины могли воздействовать на один класс. Мы не хотим изменять класс Employee каждый раз, когда бухгалтеры меняют формат почасового отчета, или когда администраторы БД внесли изменения в схему БД, а также каждый раз, когда менеджеры меняют расчет заработной платы. Как раз наоборот: мы должны разделить эти задачи на разные классы, чтобы они могли меняться независимо друг от друга.


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

Закон Кёрли также заключается в выборе того, что Ваш код не должен делать. Это гораздо сложнее, чем выбирать что он должен делать, ведь процесс этого выбора противоречит всем популярным тенденциям в разработке ПО. Это может включать в себя разбиение кода на части, нарушение традиционных правил ООП или использование повторяющегося кода. Мы делаем шаг назад чтобы сделать два шага вперед.

Каждая переменная, каждая строчка кода, каждая функция, каждый класс, каждый проект – должны делать что-то одно. К сожалению, о том, что именно они должны делать, мы узнаём только в самом конце.

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


  1. amakhrov
    04.04.2022 01:36
    +1

    SRP и DRY вообще несвязанные друг с другом принципы. Легко можно представить себ код, удовлетворяющий SRP, в котором при этом много повторения. Равно как и наоборот.


    1. Daisoto Автор
      04.04.2022 12:52

      Я думаю дело в том что факт повторения кода говорит о том что он находится не там где нужно, т.е. не вынесен в свою зону ответственности. Буду рад увидеть Ваш пример.


  1. amkartashov
    04.04.2022 12:29
    +4

    нужно ещё

    • не путать одинаковый и повторяющийся код. Одинаковый код в разных местах в дальнейшем может развиваться по разному.

    • учитывать целесообразность следованию принципов в конкретном проекте и условиях. Иногда всё таки проще и надёжнее скопипастить, чем обособлять повторяемый код с возможностью включить его в нескольких местах