Рефакторинг на максималках: новая онлайн-книга

В январе этого года меня пригласили выступить с докладом о рефакторинге. Во время подготовки я собрал техники рефакторинга и полезные ресурсы, которые использую в своей работе, чтобы поделиться ими в докладе. Материала, правда, оказалось слишком много, чтобы уместить его в 40-минутный слот.

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

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

На кого это рассчитано

Эта книга о том, как эффективно и без боли рефакторить код. В ней мы поговорим о пользе рефакторинга для разработки и бизнеса, и том, как искать и решать проблемы в коде.

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

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

Более опытные разработчики, вероятно, уже знакомы с частью описанных в книге техник. Для них наиболее полезным может оказаться список литературы в конце книги.

Какие темы затрагивает книга

Мы поговорим о различных приёмах и техниках улучшения кода, а также сам процесс рефакторинга. В частности, мы обсудим:

Понятие рефакторинга и качества кода

Что такое рефакторинг вообще, зачем он нужен. К чему приводит неуправляемо растущая сложность проекта. Как определять «плохой» и «хороший» код.

Что делать до и во время рефакторинга

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

Форматирование, линтинг и возможности языка

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

Именование сущностей

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

Дублирование кода

Как разделять дублирование и недостаток знаний, зачем использовать дублирование в качестве инструмента. В чём польза регулярных аудитов кода и как выработать привычку их заводить.

Понятие абстракции и разделение ответственности

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

Функциональный пайплайн и линейное выполнение

Как и зачем выделять состояния данных в бизнес-процессах. В чём польза линейного выполнения кода. Как «запретить» передачу невалидных данных и обособить валидацию. В чём польза принципов функционального программирования.

Условия и сложность кода

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

Улучшение кода с сайд-эффектами

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

Способы обработки ошибок

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

Упрощение интеграции модулей

Что такое зацепление и связность. Как делить приложение на модули и потом компоновать эти модули друг с другом. Зачем и по какому принципу декомпозировать задачи. В чём польза контрактов и гарантий между модулями. Как максимально расцепить модули друг от друга, но при этом оставить возможность для их общения. В чём разница между объектной и функциональной композицией. Как работать с зависимостями. Как добиться целостности и согласованности данных.

Обобщения и иерархии

Как понять, когда нужен обобщённый алгоритм или тип. Почему в большей части случаев композиция предпочтительнее наследования. Как использовать принцип подстановки Лисков в качестве интеграционного линтера.

Основы рефакторинга архитектуры приложений

Чем может мешать слабая архитектура при рефакторинге. Как использовать повсеместный язык для улучшения архитектуры. Как строить взаимодействие с внешним миром и работу с зависимостями. В чём польза портов и адаптеров. Зачем разделять UI-логику от бизнес-логики. Как архитектура влияет на тестируемость.

Декларативный стиль программирования

В чём польза декларативного стиля кода по сравнению с императивным. В каких ситуациях наоборот предпочесть императивный стиль. Зачем могут пригодиться конечные автоматы во фронтенд-разработке.

Использование статической типизации

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

Рефакторинг тестового кода

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

Улучшение документации и комментариев

Как синхронизировать источники правды в проекте и предотвратить их рассинхронизацию. Как и зачем делать комментарии информационно насыщеннее. Как увеличить пользу документации, не увеличив затраты на её ведение. Чему в проекте уделять внимание «кроме кода».

Рефакторинг как процесс

Как понять, рефакторить или переписывать код. Какую информацию о проекте собрать перед началом работы. Чем руководствоваться при расчёте времени на задачу. Какими метриками измерять влияние рефакторинга на код.

Чем эта книга не является

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

Также я не стараюсь написать «мануал», который будет универсально применим во всех проектах. Моё восприятие, привычки и метод работы искажены моим опытом разработки. Решение, применять идею или нет, сильно зависит от проекта, задачи, ресурсов и цели рефакторинга. Старайтесь выбирать те идеи, которые принесут больше выгоды при меньших затратах.

Обратная связь и ошибки

Книга бесплатная и доступна на Гитхабе.

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

Сейчас книга доступна на 2 языках: русском и английском. Если у вас есть желание помочь с переводом, напишите мне, пожалуйста, на почту. Буду рад обсудить детали!

Надеюсь, книжка окажется полезной!

Ссылки и ресурсы

Книжка, содержание, список литературы и доклад, с которого всё началось: