Как писать меньше кода и получать больше толку

Автор оригинала: Ravi Shankar Rajan
  • Перевод


Как справедливо заметил легендарный писатель Жюль Верн: «Хорошо использованный минимум вполне достаточен». В нашу эпоху понятие хорошо использованного минимума применимо и к коду. Печально, но факт: в современном мире кода слишком много. Если быть точнее, то слишком много ненужного кода, среди которого код полезный просто задыхается.

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

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

Для всех этих проблем существует одно решение: писать меньше кода. У такого подхода масса преимуществ:

  • Меньше кода в разработке = меньше затрат на разработку
  • Меньше кода в разработке = меньше затрат на его сопровождение
  • Меньше кода в разработке = меньше багов
  • Меньше кода в разработке = более эффективное тестирование

И самое-то главное: чем меньше кода вы вынуждаете людей читать, тем больше вероятность, что кто-то вообще его прочтет.

Вот несколько способов, которые помогут вам урезать объем кода.

Принцип YAGNI («Вам это не понадобится»)


Под принципом «Вам это не понадобится» (его часто упоминают в виде аббревиатуры YAGNI – You Aint’ Gonna Need It) понимается следующее правило экстремального программирования: «Реализуйте ту или иную возможность только тогда, когда она действительно нужна, а не когда вы предполагаете, что она вскоре понадобится». Даже если вы на сто процентов уверены, что без этой функции в будущем не обойтись, не начинайте внедрять ее уже сейчас.

Есть два довода в пользу этой практики:

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

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

Основное правило здесь: сосредоточьтесь на том, что явно нужно, и не думайте о том, что, наверное, произойдет.

Не пишите неуязвимый код


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

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

Именно поэтому, если вы преследуете цель писать меньше кода, нужно стремиться к максимально простой реализации, из разряда «лишь бы работало».

В руководстве по экстремальному программированию упоминается два золотых правила написания простого кода:

  • Сначала внедрите новую функциональность самым примитивным способом, который только может сработать. Не возводите умопомрачительных суперструктур, не изощряйтесь – просто сделайте так, чтоб все запустилось. Убедитесь, что код проходит модульные тесты для новой функциональности (и для старой тоже, как всегда).
  • Затем – и это критически важная часть правила – проведите рефакторинг системы и максимально упростите код для всех функций, которые на данный момент содержатся в продукте. Следуйте принципу DRY и другим принципам, которые помогают сделать систему опрятнее.

Не забывайте: мы стремимся не к кратчайшему пути, а к простейшему результату.

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

Помните, что в основе элегантности лежит простота. Способность контролировать и устранять лишнюю сложность – это и есть виртуозное программирование.

Не делайте код хуже


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

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

Временами в процессе устранения проблемы мы приносим больше вреда, чем пользы. В своей книге «Совершенный код», которая входит в золотой фонд литературы для программистов, Стив Макконнелл пишет, что если вы работаете не над корнем проблемы, а над ее симптомом, то только ухудшаете положение – обманываете сами себя, создавая иллюзию, что проблема решена.

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

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

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

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

Избегайте излишнего параллелизма


Параллелизм – палка о двух концах. К нему следует прибегать только если без этого не обойтись.

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

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

Одна из самых громких катастроф, связанных с разработкой ПО, была вызвана именно неверно прописанными взаимозависимыми условиями. Ошибка при программировании Therac-25, аппарата для лучевой терапии, привела к смерти четверых человек.

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

Не ударяйтесь в накопительство


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

Когда симптомы накопительства проявляются у разработчиков, они начинают цепляться за любой фрагмент кода, даже если он уже устарел или кишит багами. Такие разработчики никогда не удаляют код сами и вообще выступают против этой практики. Если сказать им об этом напрямую, получите ответы в духе: «Он же может когда-нибудь понадобиться» или «Без этого я не смогу выполнять операцию Х» и так далее.

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

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

Хороший программист работает над совершенствованием кода день изо дня, и со временем качество кода стабильно растет. Устаревший код, который писал хороший программист, всегда выделяется своей аккуратностью – профессионалы не оставляют после себя беспорядка; ведь код – это наша репутация и именно по нему о нас и будут судить. Как справедливо сказал Роберт Мартин: «Истину можно найти только в коде».
  • +19
  • 9,9k
  • 6
Цифровые Экосистемы
235,61
Переводим бизнес в цифру
Поделиться публикацией

Комментарии 6

    0
    Страшные вещи пишет автор: «если вы преследуете цель писать меньше кода, нужно стремиться к максимально простой реализации, из разряда «лишь бы работало»». По моему скромному мнению, метод написания «тяп-ляп» не выход, я бы скорее выделил идею переносить большую часть проверок из кода в тесты.
      +1

      Скорее, автор высказывал следующую идею:


      1. Написать код для наилучшего случая (все данные валидны, все сервисы отвечают правильно)
      2. Для каждого такого допущения оценить вероятность, что что-то пойдет не так.
      3. Сравнить стоимость исправления сейчас и ожидаемую величину ущерба из-за ошибки.
      4. Исправить только то, что нужно.
      5. Ариан-5
        +1
        Это цитата из «экстремального программирования» К. Бека. из раздела юнит-тестирования. Основная идея — как раз в том, как определить минимально необходимый уровень кода, чтобы выполнить текущую задачу, не воздвигая замков.
        0

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


        P.S. Как всегда не стоит забывать что все советы это конечно хорошо, но личный удачный/не_удачный опыт ничем не заменишь

          0
          Советы для кого? Для сферического программиста в вакууме?
          Есть задачи, которые так решать нельзя. Пример с аппаратом для лучевой терапии тому подтверждение.
          Если хотите писать меньше кода, нужно заложить в разработку больше математики.
          Большинство интерактивных программ хорошо описывается конечным автоматом. Честно построив модель и получаем хорошее т.з. на минимально-необходимое программирование.
          Да, не все «побочные» ветви необходимо сразу реализовать в виде подробного анализа нештатной ситуации. Достаточно стандартного сообщения.
            0

            Соглашусь только с последним пунктом. По мне всякая необходимость оставлять неиспользуемые функции полностью исчезла с появлением Git.


            А вот на счёт остального скажу — такие рекомендации и без того часто понимают превратно. Вообще, много раз убеждался, что любую разумную идея можно довести до абсурда. И особенно могу сказать про первые два пункта, во что это скорее всего превратится в реальности. Умельцев внедрят функциональность самым примитивным способом хоть отбавляй. После этого соответствующие задачи переходят в статус выполнено и включать в очередной sprint время на refactoring редко кто топорится. Вместо этого реализуется дальнейшая функциональность со всё новыми костылями. В итоге очередную новую функцию становится нереально в сколь-нибудь сопоставимые сроки реализовать без новых костылей, как ни хотелось б. Ну и далее характерный реальзтат, когда исправление одной ошибки создат другую ошибку.

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

            Самое читаемое