Советы разработчикам по написанию чистого кода

0
978
views

Перевод статьи «How to write clean code».

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

Чистый код предполагает масштабируемую организацию. Это означает, что внесение в него даже существенных изменений не приводит к хаосу. Умение писать такой код — одно из ключевых отличий разработчика-сеньора.

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

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

1. Код должен быть не только рабочим, но и читаемым. Эти два качества одинаково важны

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

Как быть и что делать

Хороший нейминг + классы и функции с единой ответственностью + написание тестов.

2. Позже значит никогда

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

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

Как быть и что делать

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

3. Функции должны быть маленькими

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

Что касается аргументов функции, их идеальное количество — 0. Дальше идет 1, 2, но нужно стараться, чтобы аргументов было не больше 3.

Как быть и что делать

Функции нужно писать в соответствии с принципами единой ответственности и открытости/закрытости.

Photo by AltumCode on Unsplash

4. Дублирование кода — зло

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

Как быть и что делать

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

5. Единственный хороший комментарий — о найденном способе избежать комментариев

«Нет ничего полезнее хорошего комментария в нужном месте. Но комментарии даже в наилучшем случае — неизбежное зло».

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

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

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

Как быть и что делать

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

6. Объект раскрывает поведение, но не данные

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

Как быть и что делать

Область видимости переменных должна быть как можно более локальной, чтобы не раскрывать больше необходимого.

7. Тестирование

Код тестов так же важен, как и тот, что идет в производство. Поэтому он должен меняться и расти по мере развития проекта.

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

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

Как быть и что делать

Нужно следовать принципам чистых тестов FIRST. Тесты должны быть:

  • Быстрыми (Fast). Тесты должны выполняться быстро. Если вам приходится слишком долго ждать выполнения теста, вы вряд ли станете запускать его почаще.
  • Независимыми / изолированными (Independent). Тесты должны быть как можно более изолированными и не зависящими друг от друга.
  • Повторяемыми (Repeatable). Тесты должны быть повторяемыми в любой среде — в разработке, стейджинге и продакшене.
  • Очевидными (Self-Validating). Результатом выполнения теста должно быть булево значение. Тест должен быть или пройден, или провален.
  • Исчерпывающими (Thorough). Нужно стремиться охватить тестами все крайние случаи, все проблемы безопасности, каждый use case (вариант использования) и happy path (самый благоприятный сценарий работы кода).
Photo by AltumCode on Unsplash

8. Обработка ошибок и исключений

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

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

Как быть и что делать

Создавайте информативные сообщения об ошибках и передавайте их вместе с вашими исключениями. Указывайте операцию, в которой произошел сбой, и тип ошибки.

9. Классы

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

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

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

Как быть и что делать

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

10. Форматирование

Каждая пустая строка — это визуальная подсказка, помогающая определить, что началась новая, отдельная концепция.

Локальные переменные должны появляться вверху функции.

Переменные экземпляра должны декларироваться вверху класса.

Короткие строки предпочтительнее длинных. Обычно верхняя граница — 100-120 символов, длиннее уже не стоит делать.

Как быть и что делать

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

Photo by AltumCode on Unsplash

Принципы разработки программ

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

Именование переменных

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

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

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

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

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

Зависимости должны быть сведены к минимуму

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

Аккуратность

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

Уборка

Не оставляйте в кодовой базе бесполезный код (старый и уже не использующийся или созданный «на всякий случай»). Уменьшайте количество дубликатов и создавайте простые абстракции на ранних этапах.

Стандартизация

При написании кода следует придерживаться стиля и практик, установленных для репозитория.

Самодисциплина

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


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