Object Calisthenics by Jeff Bay - 9 простых правил для clean code

По наводке Сергея Бобровского прочитал презентацию Jeff Bay о практике Object Calisthenics. Практика представляет собой 9 простых правил по оформлению кода, что, как ни странно, позволяет (заставляет на самом деле :) ) писать более совершенный код (более лёгкий для понимания и поддержки).

1. Один уровень отступа для каждого метода

Условно если в методе есть цикл, то внутри него с натяжкой может быть if, но внутри этого if уже точно нет вложений второго уровня. Никаких циклов в цикле, никаких деревьев из if-ов. Решается активным использованием методов функционального программирования

2. Не используйте конструкцию ELSE (ELIF)

Внутри функции конструкцию типа

if a % 3 == 0:
  return a
else:
  return a + 1

легко заменить на

if a % 3 == 0:
  return a
return a + 1

3. Оборачивайте все примитивы и строки в пользовательские классы

Если у вас есть переменная типа int, где хранится значение возраста - вы можете по ошибке передать туда отрицательное значение или сделать ещё что-то, что позволительно делать с целыми числами, но нельзя делать с возрастом. А вот если у вас есть собственный класс для хранения возраста с конкретным списком методов, которые позволительны для этого класса - вероятность ошибки резко снижается.

4. Оборачивайте стандартные структуры данных в пользовательские классы

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

5. В одной строке кода не более одной “точки” (префикса вызова метода)

Не должно быть конструкций вида:

obj1.get_obj2().obj2method().get_obj3().obj3method()

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

full_name = full_name_in.strip()
  .lower()
  .split()

где новый объект не создаётся, а последовательно применяются методы одного и того же объекта. Тем не менее правило “одна точка на строку” должно соблюдаться и в этом случае.

6. Не используйте аббревиатуры для названий классов и методов

Названия должны состоять из 1-2 слов и не должны дублировать контекст. Это заставляет лучше продумывать, что делает объект, не делать его мульти-комбайном.

7. Сохраняйте все сущности маленькими

Класс не должен превышать 50 строк, пакет не должен быть больше 10 файлов. Позволяет удерживать структуру объекта в голове во время отладки.

8. Не больше двух переменных в классе

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

9. В классе не должно быть геттеров/сеттеров, все поля должны быть инкапсулированы

Если надо изменить поле класса - не должно быть возможности сделать это простым заданием значения. Условно, если для объекта Самолёт надо задать скорость ноль, это нельзя сделать просто написав

plane.speed = 0 

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

plane.land()

Может позже распишу некоторые из этих пунктов отдельными заметками. А пока, хочу найти статистический анализатор кода для vs code, где можно задать эти правила. Правда, я не пишу большие проекты, где применение этих правил даст заметный выигрыш (понятно, что если надо написать двадцать-тридцать строчек кода применение этих правил и даже использование ООП скорее всего будет избыточно), но для тренировки мозгов - это будет интересно

Written on February 26, 2024