Чистый код — это код, который работает, хорошо читается, в котором легко разобраться и который просто поддерживать. Многие программисты в поисках подходов к чистому коду часто читают книгу Роберта Мартина «Чистый код. Создание, анализ и рефакторинг» — Мартин был первым, кто собрал все правила в одном месте и рассказал о том, как такой подход работает в жизни. Давайте разберёмся, что это за правила и как их применять.
Эта статья — пересказ статьи Тиары Деванги. Если знаете английский, почитайте оригинальный материал — в нём больше теории и деталей.
Наименования в коде
Используйте наглядные наименования. Читабельность кода на 90% зависит от того, насколько понятно названы переменные, функции и другие объекты. Сравним два примера:
// Пример 1
var p float64 // финальная цена
Название переменной p не помогает понять, для чего она. Хотя в коде есть комментарий, который поясняет назначение переменной, он ухудшает читаемость кода в целом. Вместо этого лучше делать так:
// Пример 2
var basePrice float64
var totalDiscount float64
var finaPrice float64
Здесь уже без комментариев можно понять, зачем нужна каждая переменная и для каких сценариев она используется.
Избегайте двусмысленных названий. Идеально, если название чётко передаёт, что делает переменная, класс или функция. Не используйте сокращения, например r для radius или w для width, если только эти сокращения не приняты в языке программирования, на котором вы пишете. Но использовать i для организации циклов — это нормально :-)
Используйте произносимые и доступные для поиска названия. Серьёзное программирование редко делается в одиночку. Когда над кодом работает команда, важно, чтобы его обсуждение не вызывало проблем. Попробуйте произнести вслух названия переменных trsltready и test-result-ready — и почувствуйте разницу.
Функции
Соблюдайте принцип единой ответственности. У функции должно быть одно чётко определённое действие, понятное из названия. Например, с точки зрения здравого смысла функция getUserData() должна возвращать данные пользователя и не заниматься другими задачами. Не прячьте побочный функционал в имени функции, как в этом примере:
func (s *service) updateTransactionStatus(ctx context.Context,
transaction UpdateTransactionRequest) (
result UpdateTransactionResponse, err error) {
result, err := s.UpdateTransactionData(ctx, transaction)
if err != nil {
return result, err
}
result, err := s.SendEmailToUser(ctx, transaction)
if err != nil {
return result, err
}
return result, err
}
Судя по названию, функция должна только обновлять статус транзакции, но вместо этого она ещё отправляет пользователю письмо.
Создавайте код настолько небольшим, насколько возможно. Этот принцип тесно связан с принципом единой ответственности. Если функция небольшая, это упрощает модульное тестирование и позволяет обнаружить ошибки на ранних этапах разработки.
Ограничивайте количество аргументов функции. Оптимальные функции не имеют аргументов, функции с одним аргументом немного хуже, с двумя — ещё немного хуже. Но функций с тремя аргументами желательно избегать, если это возможно. Чем меньше аргументов, тем проще тестирование и меньше вероятность ошибок ввода из-за замены аргументов.
Например, вот так лучше не писать:
func createTransaction(ctx context.Context,
userID int,
transactionType string,
description string,
amount float64) (err error, status string, endingAmount float64) {
// внутренний код функции
}
Вместо этого лучше написать так:
func createTransaction(ctx context.Context,
transactionData CreateTransactionRequest)
(err error, result CreateTransactionResponse) {
// внутренний код функции
}
Комментарии
Комментарии должны быть только у рабочего кода. Не нужно забирать в комментарии ненужный код — он только усложняет чтение программы. Если код не нужен — убирайте его вместе с комментариями. Оставляйте его, только если в комментариях написано, почему этот фрагмент кода обязательно нужно оставить.
Указывайте в комментариях только то, что код не может сказать сам за себя. Не добавляйте избыточные комментарии, например как здесь:
i += 1 // увеличиваем i на единицу
Комментарий поясняет то, что и так понятно, а значит, с точки зрения чистого кода он не нужен.
Объясняйте в комментариях цели, которые лежали в основе решения. Чтобы другие могли понять ваш код, оставляйте комментарии со схемой процесса или важной информацией. Комментарии также могут служить предупреждением о последствиях запуска определённых функций. Самый интересный пример в этом плане — комментарий Джона Кармака, одного из создателей игры Quake :-)
Вот пример непонятных комментариев:
// перебираем список идентификаторов пользователей
for _, id := range userIDs {
// делаем что-то с идентификатором
}
А вот код с комментарием, который объясняет смысл:
// иногда клиенты не реагируют на письма, поэтому мы отправляем повторные
result, err := resendCallback(ctx, request)
Обновляйте устаревшие комментарии. Бывает, что при доработке кода комментарии остаются старыми и относятся к старому коду, которого уже нет. Поэтому при рефакторинге или оптимизации не забывайте о том, что комментарии тоже надо обновлять.
Общие принципы
Следуйте общим договорённостям по разработке кода. Если команда придерживается отраслевых или каких-то своих соглашений, делайте так же. Даже если команда, с вашей точки зрения, пишет не совсем чистый код, но так делают все в компании — пишите так же. Единый стиль написания кода с командой важнее принципов.
Будьте последовательны. Если вы о чём-то договорились с собой или с командой — придерживайтесь этой договорённости во всём коде. Например, если вы выбрали термин «Пользователь», используйте только его и не меняйте его на термин «Клиент», если только это не что-то новое.
Используйте объясняющие переменные. Бывает, что можно сделать код более читаемым, если разделить его на несколько строк. Но делать это нужно обдуманно. Выбор между однострочным и многострочным кодом зависит от контекста и от того, что делает код понятнее.
Что дальше
А дальше — практика. Начните новый проект или проведите ревизию своего старого кода и попробуйте применять все эти принципы в жизни. Поначалу это может показаться трудным, но со временем это станет для вас обычным и привычным подходом.