Чистый код — избавляемся от грязного кода

Чистый код — меньше багов
  • Среда разработки помогает быстрее писать код. А еще, она подсказывает как сделать код чище. Стоит обращать внимание на все предупреждения среды разработки и учитывать их. Так же выявляется и дублирование кода
  • Дублирование — большая помеха чистоте кода. Простейшая форма дублирование — целые куски дублирующего кода. Их стоит выделять в отдельные функции, иногда — классы и пере-использовать. Более сложные примеры дублирования проявляются в одинаковых условиях if-else. Вместо них следует использовать принцип полиморфизма. Существуют еще более сложные случаи дублирования. Схожие алгоритмы могут соседствовать со специфичной логикой. Используем паттерны проектирования, например Шаблонный метод или Стратегия.
  • Дублирующий код может быть инкапсулирован в более высокие уровни абстракций, если необходимо пере-использовать его в других классах.
  • Не используемый код следует удалять, а не сохранять на будущее. Тоже происходит с “мертвым кодом”, до которого алгоритм никогда не дойдет. Это нередкая “болезнь” циклов if-else и switch-case
  • Вертикальное разделение помогает чтению кода. Переносы строк, без пропуска строк, покажут что код относится к одной логике. Пропуски строк разделят алгоритм на 2е логически-обособленные части
  • Такой балласт, как пустой конструктор или пустое тело цикла будет мешать читать код. Следует удалить их.
  • Пояснительные переменные помогают чтению и пониманию кода
$today = date('Y-m-d', now());
$targetDateString = '2020-07-08';
$targetDate = date('Y-m-d', strtotime($targetDateString));
If ($today >= $targetDate) {
	doTheJob();
}
  • Чистоте кода, так же, поможет соблюдение стандартных конвенций. Не обязательно это должен быть согласованный документ. Сам код служит примером оформления.
  • Так называемые “волшебные числа” заменяют именованными константами — пример кода со стр 339
$dailyPay = $hourlyPay * 8;
$PI = 3.14;
$circleLength = $radius * $PI * 2;

Конфигурационные данные выносим на высокие уровни абстракций — конфигурационные файлы или файл

Чистый код — комментарии

Чистый код — искусство комментирования

Комментарии

Комментарии к коду — не однозначная концепция. С одной стороны, комментарии используют для пояснения работы следующего кода. С другой стороны, одна из концепций “Чистого кода”: код должен быть понятным и без комментариев.

От сюда, обозначим основные концепции:

  • Комментарии быстро устаревают. Важно не забывать обновлять комментарии при обновлении следующего кода. Это известная проблема комментариев. Устаревшие комментарии могут быть вредны. Они описывают одно поведение, а алгоритм кода — другое, что путает программиста.
  • Комментарии увеличивают размер кодовой базы и время на изучение кода. Нужно прочитать не только код, но и комментарии, чтобы вникнуть в алгоритм. 
  • Есть такое заблуждение, что комментарии компенсируют плохой код. Например, пишем не очень понятный или запутанный код, а далее, в комментариях поясняем его работу. Лучше написать ясный и выразительный код, чтобы комментарии не потребовались
  • Замена комментариям — подходящие, говорящие имена переменных, методов и классов
  • Лучше удалять старый код, чем комментировать его. Закомментированный код со временем разрастается и создает большой объем бесполезного или вредного груза. 
  • В некоторых случаях комментарии уместны. Они будут мощным инструментом. 

Уместные типы комментариев:

  • Юридические комментарии в начале модулей или классов, копирайты
  • Пояснения к сложным регулярным выражениям или маскам
  • Если используются какие то стандартные имена из сторонних библиотек. При этом, мы не можем на них повлиять, но можем описать комментариями
  • Когда передают опыт использования или предупреждения (например, // код ниже может работать очень долго если количество записей в базе данных больше миллиона)
  • Комментарии TODO
  • Усиление значения какого то факта, если его значение может показаться неочевидным (например, //не удаляйте код ниже, так как это защита от…)
  • Комментарии вида APIdoc, необходимые для генерации авто-документации по методам АПИ

Чистый код — функции и классы

Чистые функции и классы

Классы и функции — важнейшие блоки построение кода проекта. Это делает их основными целями при работе с чистотой кода.

Рекомендации к написанию функций:

  • Функции должны быть как можно компактнее. Можно ориентироваться на размер максимум 20 строк, чтобы понимать масштабы
  • Функции могут содержать вложенности (циклы foreach, if else, while). Следует уменьшить число вложенностей до 1-2. В идеале одна вложенность. Больший уровень вложенности можно помещать в отдельные функции
  • Функция должна выполнять одну операцию. Это упрощает разделения алгоритма на функции
  • Если в функции есть “секции” (например объявление, инициализация, сбор данных и т.д.) значит она выполняет несколько операций. Следует разделить на разные функции
  • При этом имя функции следует выбирать таким образом, чтобы доходчиво объяснить операцию
  • Связанные функции следует размещать ближе к “родительским”. Создаем, таким образом, понятный уровень иерархии, который читается сверху вниз
  • Следует минимизировать количество аргументов функций. Большое количество аргументов усложняет понимание функции. Лучше всего читаются функции без аргументов. Они могут манипулировать полями классов ($this->variable). 
  • Если в функцию нужно передавать много аргументов, следует рассмотреть объединение их в класс, тогда из аргументов будет только один объект класса

Классы:

  • Оптимальный вариант строения класса: сначала идут открытые переменные, затем приватные. За списком переменных идут публичные функции. За каждой публичной функцией следуют приватные вспомогательные функции. При таком размещении, класс читается как газетная статья
  • Классы должны быть компактными. Размер класса может определить принцип единой ответственности. Этот принцип говорит, что класс должен иметь только одну причину для изменения. Пример класса с 2мя причинами для изменения ниже
Class UserDashboard {
    public function getLastFocusedElement() {…};
    public function setLastFocusedElement() {…};
    public function getMajorVersion() {…};
    public function getMinorVersion() {…};
}

Его стоит разделить на 2 класса: первый  — для работы с выделенным элементом дашборда, второй — для версионирования дашборда

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

Чистый код — простые концепции

Чистый код хорошо пахнет

Что такое “Чистый код”

Нету простого определения понятию “Чистый код”. Но можно тезисно описать некоторые подходы к пониманию:

  • Не содержит дубликатов
  • Четкий, простой и прямолинейный
  • Минимально-необходимое количество сущностей: классов, зависимостей, методов, функций, строк кода и т.д.
  • Понятный и выразительный
  • Продуманный. Создает впечатление, что автор кода над ним усердно потрудился
  • Реализованы все требования к продукту

Почти все это абстрактно, поэтому ниже будет конкретика

Почему важно писать чистый код

  • “Грязный код” накапливается. Это приводит к ошибкам. Количество ошибок растет лавинообразно. В конечном счете проект становится очень дорого поддерживать
  • Вы сами будете не раз возвращаться к своему предыдущему коду. Нужно будет вносить правки или улучшения. Чистый код проще поддерживать. Скорость разработки с чистым кодом выше
  • Не только вы будете изучать предыдущий код, но и ваши коллеги. Они почувствуют уважение и благодарность, если столкнуться с чистым кодом
  • Написание чистого кода так же будет развивать в вас такие положительные черты, как аккуратность, внимательность и предусмотрительность

Начало — простые концепции

Несмотря на кажущуюся простоту, они очень важные:

  1. Правило бойскаута

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

Этот принцип формируем в нас характер и стремление к чистоте

  1. Содержательные имена

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

Что следует избегать:

  • Короткие названия, которые слабо описывают смысл
grnp109, a1, pf
  • Однобуквенных переменных, где можно заложить смысл
$items = $this->userOrdersFromLastVisit($date);
foreach($items as $i) {
   $i->date = Date.now();
}

Может быть

$userOrders = $this->userOrdersFromLastVisit($dateOfLastVisit);
foreach($userOrders as $userOrder) {
    $userOrder->updatedDate = Date.now();
}
  • Сокращения и неудобно-читаемые имена

Было

mngmnt, len, datefromlastupdate

стало

management, length, dateFromLastUpdate

Другие рекомендации

  • Имена классов — обычно имена существительные: Product, UserPage, OrderParser
  • Имена методов — глаголы или глагольные словосочетания: deleteProduct, save, getName
  • Писать имена на английском языке без ошибок. Перевод любого слова можно получить в онлайн-переводчике
  • Быть последовательным. Если для получения данных в классе несколько раз использовался термин get, в похожем контексте слово fetch будет выбиваться