ключевых вывода
1. Пишите чистый код, который легко читать и поддерживать
Единственная допустимая мера качества кода: WTFs/минута
Читаемость превыше всего. Чистый код должен быть легко понятен другим разработчикам. Он должен быть простым, элегантным и свободным от лишнего. Стремитесь писать код, который ясно выражает свои намерения без необходимости в обширных комментариях. Используйте значимые имена переменных и функций, держите функции маленькими и сфокусированными, и логически организуйте код.
Поддерживаемость позволяет эволюционировать. Код, который трудно изменить, становится обузой. Проектируйте свой код так, чтобы он был гибким и модульным, чтобы он мог адаптироваться к изменяющимся требованиям. Следуйте принципам, таким как DRY (Don't Repeat Yourself) и SOLID, чтобы создавать слабо связанные, высоко когерентные системы. Безжалостно рефакторите, чтобы улучшить структуру кода без изменения его поведения.
Чистый код окупается. Хотя написание чистого кода требует больше усилий на начальном этапе, это экономит значительное время и избавляет от головной боли в долгосрочной перспективе. Чистый код легче отлаживать, расширять и поддерживать. Он позволяет разработчикам работать более эффективно и снижает риск внесения ошибок при изменениях. Сделайте чистый код основой своей практики разработки.
2. Следуйте значимым соглашениям о наименованиях
Имя переменной, функции или класса должно отвечать на все важные вопросы. Оно должно объяснять, почему оно существует, что оно делает и как используется.
Используйте имена, раскрывающие намерения. Выбирайте имена, которые ясно передают цель и поведение переменных, функций и классов. Избегайте однобуквенных имен или криптографических сокращений. Используйте произносимые имена, которые легко искать. Например:
- Плохо: d (время в днях)
- Хорошо: elapsedTimeInDays
Будьте последовательны и точны. Используйте последовательные соглашения о наименованиях по всему коду. Будьте точны, чтобы избежать двусмысленности - например, используйте значимые различия, такие как getActiveAccounts() и getActiveAccountInfo(). Избегайте кодировок или префиксов, которые добавляют шум без ценности. Имена классов должны быть существительными, имена методов - глаголами.
Длина имени должна соответствовать области видимости. Используйте более длинные, описательные имена для переменных и функций с большой областью видимости. Короткие имена допустимы для небольших, локальных областей. Длина имени должна быть пропорциональна его области использования. Оптимизируйте для читаемости и понимания в контексте, где используется имя.
3. Держите функции маленькими и сфокусированными
Функции должны делать одно дело. Они должны делать это хорошо. Они должны делать только это.
Маленькое - это красиво. Функции должны быть маленькими - обычно 5-10 строк. Они должны помещаться на один экран и быть мгновенно понятными. Выносите код в хорошо названные вспомогательные функции, а не пишите длинные, сложные функции. Маленькие функции легче понять, тестировать и поддерживать.
Делайте одно дело хорошо. Каждая функция должна иметь одну, четкую цель. Если функция делает несколько вещей, вынесите их в отдельные функции. Признаки того, что функция делает слишком много, включают:
- Несколько уровней абстракции
- Несколько секций или блоков кода
- Многочисленные параметры
Поддерживайте один уровень абстракции. Операторы внутри функции должны быть на одном уровне абстракции. Не смешивайте высокоуровневую логику с низкоуровневыми деталями. Выносите низкоуровневые операции в отдельные функции. Это улучшает читаемость, удерживая функции сфокусированными и концептуально простыми.
4. Практикуйте правильное форматирование и организацию
Форматирование кода - это о коммуникации, а коммуникация - это первоочередная задача профессионального разработчика.
Последовательное форматирование имеет значение. Используйте последовательные отступы, разрывы строк и пробелы по всему коду. Это улучшает читаемость и снижает когнитивную нагрузку. Согласуйте стандарты форматирования с вашей командой и используйте автоматические инструменты для их соблюдения. Основные рекомендации по форматированию включают:
- Правильные отступы
- Последовательное размещение скобок
- Логические разрывы строк
- Соответствующие пробелы
Организуйте код логически. Группируйте связанный код вместе и разделяйте несвязанный код. Используйте пустые строки для создания "абзацев" между логическими секциями. Размещайте связанные функции рядом друг с другом. Держите файлы сфокусированными на одной концепции или компоненте. Разбивайте большие файлы на меньшие, более сфокусированные, когда это уместно.
Следуйте стандартным соглашениям. Соблюдайте стандартные соглашения для вашего языка и сообщества. Это делает ваш код более знакомым и доступным для других разработчиков. Например, в Java:
- Имена классов используют PascalCase
- Имена методов используют camelCase
- Константы используют ALL_CAPS
5. Управляйте зависимостями и избегайте дублирования
Дублирование может быть корнем всех зол в программном обеспечении.
Устраняйте дублирование. Дублированный код - это упущенная возможность для абстракции. Когда вы видите дублирование, выносите общий код в переиспользуемую функцию или класс. Это улучшает поддерживаемость, централизуя логику и снижая риск несогласованных изменений. Типы дублирования, на которые следует обращать внимание:
- Идентичные блоки кода
- Похожие алгоритмы с небольшими вариациями
- Повторяющиеся цепочки switch/case или if/else
Управляйте зависимостями осторожно. Минимизируйте зависимости между модулями, чтобы уменьшить связность. Используйте внедрение зависимостей и инверсию управления, чтобы сделать код более модульным и тестируемым. Следуйте принципу инверсии зависимостей - зависеть от абстракций, а не от конкретных реализаций. Это делает ваш код более гибким и легким для изменения.
Используйте принцип наименьшего знания. Модуль не должен знать о внутренностях объектов, с которыми он работает. Это уменьшает связность между модулями. Например, используйте Закон Деметры - метод должен вызывать методы только на:
- Своем собственном объекте
- Объектах, переданных в качестве параметров
- Объектах, которые он создает
- Своих прямых компонентах
6. Обрабатывайте ошибки аккуратно
Обработка ошибок важна, но если она затеняет логику, это неправильно.
Используйте исключения вместо кодов ошибок. Исключения чище и не загромождают основную логику вашего кода. Они позволяют отделить обработку ошибок от основной логики. При использовании исключений:
- Создавайте информативные сообщения об ошибках
- Предоставляйте контекст с исключениями
- Определяйте классы исключений на основе потребностей вызывающего кода
Не возвращайте null. Возврат null приводит к исключениям null pointer и загромождает код проверками на null. Вместо этого:
- Возвращайте пустые коллекции вместо null для списков
- Используйте паттерн Null Object
- Используйте Optional в Java или Maybe в функциональных языках
Пишите try-catch-finally сначала. Начинайте с try-catch-finally при написании кода, который может выбросить исключения. Это помогает определить область и ожидания для вызывающего кода. Это гарантирует, что ресурсы правильно управляются и освобождаются, даже в сценариях ошибок.
7. Пишите тщательные модульные тесты
Тестовый код так же важен, как и производственный код.
Следуйте трем законам TDD. Разработка через тестирование (TDD) улучшает качество и дизайн кода:
- Напишите неудачный тест перед написанием любого производственного кода
- Напишите только столько теста, чтобы продемонстрировать неудачу
- Напишите только столько производственного кода, чтобы пройти тест
Держите тесты чистыми и поддерживаемыми. Применяйте те же стандарты качества кода к вашим тестам, что и к производственному коду. Регулярно рефакторите и улучшайте тестовый код. Хорошо структурированные тесты служат документацией и позволяют без страха рефакторить производственный код.
Стремитесь к всестороннему покрытию тестами. Пишите тесты, которые охватывают крайние случаи, граничные условия и сценарии ошибок - не только счастливый путь. Используйте инструменты покрытия кода, чтобы выявить пробелы в покрытии тестами. Помните, что 100% покрытие не гарантирует отсутствие ошибок, но оно дает уверенность в рефакторинге и изменениях.
8. Постоянно рефакторите код
Оставляйте лагерь чище, чем вы его нашли.
Рефакторите оппортунистически. Улучшайте структуру кода всякий раз, когда работаете с ним. Следуйте правилу бойскаутов: оставляйте код лучше, чем вы его нашли. Маленькие, постепенные улучшения накапливаются со временем и предотвращают гниение кода. Общие техники рефакторинга включают:
- Выделение методов или классов
- Переименование для ясности
- Упрощение сложных условий
- Удаление дублирования
Рефакторите безопасно с тестами. Всегда имейте надежный набор тестов перед рефакторингом. Делайте маленькие, постепенные изменения и часто запускайте тесты. Это дает уверенность, что ваши изменения не ломают существующую функциональность. Используйте автоматические инструменты рефакторинга, когда это возможно, чтобы снизить риск внесения ошибок.
Балансируйте рефакторинг с доставкой ценности. Хотя постоянный рефакторинг важен, не позволяйте ему парализовать прогресс. Стремитесь к "достаточно хорошему", а не к совершенству. Сосредоточьтесь на рефакторинге самых проблемных или часто изменяемых областей кода. Объясняйте ценность рефакторинга заинтересованным сторонам, чтобы обеспечить поддержку для постоянного улучшения кода.
9. Применяйте принципы объектно-ориентированного и функционального программирования
Объекты скрывают свои данные за абстракциями и предоставляют функции, которые работают с этими данными. Структуры данных раскрывают свои данные и не имеют значимых функций.
Используйте принципы объектно-ориентированного программирования с умом. Применяйте принципы, такие как инкапсуляция, наследование и полиморфизм, чтобы создавать гибкие, модульные дизайны. Следуйте принципам SOLID:
- Принцип единственной ответственности
- Принцип открытости/закрытости
- Принцип подстановки Лисков
- Принцип разделения интерфейсов
- Принцип инверсии зависимостей
Используйте концепции функционального программирования. Даже в объектно-ориентированных языках техники функционального программирования могут привести к более чистому коду:
- Чистые функции без побочных эффектов
- Неизменяемые данные
- Функции высшего порядка
- Композиция функций
Выбирайте правильный подход для задачи. Объектно-ориентированные и функциональные парадигмы имеют свои сильные и слабые стороны. Используйте объектно-ориентированный дизайн, когда нужно моделировать сложные домены с поведением. Используйте функциональные подходы для преобразования данных и обработки потоков. Многие современные языки поддерживают гибридный подход, позволяя использовать лучший инструмент для каждой части системы.
10. Внимательно рассматривайте вопросы параллелизма
Параллелизм - это стратегия разъединения. Он помогает нам разъединить то, что делается, от того, когда это делается.
Понимайте проблемы параллелизма. Параллельное программирование вводит сложность и потенциальные тонкие ошибки. Общие проблемы включают:
- Гонки условий
- Взаимные блокировки
- Пропущенные сигналы
- Проблемы видимости памяти
Разделяйте проблемы параллелизма. Держите ваш код, связанный с параллелизмом, отдельно от остального кода. Это делает его легче для понимания и тестирования. Используйте абстракции, такие как Executors, Futures и Actors, для управления параллелизмом, а не работайте с сырыми потоками.
Предпочитайте неизменяемость и чистые функции. Неизменяемые объекты и чистые функции по своей природе потокобезопасны. Они устраняют многие проблемы параллелизма, избегая общего изменяемого состояния. Когда изменяемое состояние необходимо, используйте правильные техники синхронизации и рассмотрите использование атомарных переменных или конкурентных коллекций.
Последнее обновление:
Отзывы
Чистый код получает в основном положительные отзывы за свои принципы написания читаемого и поддерживаемого кода. Читатели ценят практические советы по именованию, функциям и тестированию. Основные критические замечания касаются акцента на Java и некоторых чрезмерно строгих рекомендаций. Многие считают эту книгу обязательной для чтения разработчиками, хотя некоторые находят её менее полезной для опытных программистов. Примеры из практики и примеры рефакторинга хвалят одни, но критикуют другие за излишнюю детализацию. В целом, рецензенты сходятся во мнении, что книга предлагает ценные идеи по качеству кода, даже если не все предложения универсально применимы.