Рефакторинг на максималках: новая онлайн-книга
В январе этого года меня пригласили выступить с докладом о рефакторинге. Во время подготовки я собрал техники рефакторинга и полезные ресурсы, которые использую в своей работе, чтобы поделиться ими в докладе. Материала, правда, оказалось слишком много, чтобы уместить его в 40-минутный слот.
Для доклада я ужал, отфильтровал и обрезал текст и примеры кода. Но отфильтрованный материал было жалко: в нём оставались детали и уточнения, когда и какие практики применимы, сравнение различных подходов и подробные пояснения к примерам.
Я решил, что будет полезнее не выбрасывать то, что не вместилось, а изменить формат и выпустить в виде небольшого сборника. Так и появилась эта книжка.
На кого это рассчитано
Эта книга о том, как эффективно и без боли рефакторить код. В ней мы поговорим о пользе рефакторинга для разработки и бизнеса, и том, как искать и решать проблемы в коде.
В первую очередь этот текст может оказаться полезным разработчикам веб-сервисов, пользовательских приложений и интерфейсов, которые пишут на высокоуровневых языках и имеют пару-тройку лет опыта.
Разработчики библиотек тоже могут найти для себя полезные подходы, но я буду фокусироваться на пользовательских приложениях и веб-сервисах — в этой области у меня больше опыта.
Более опытные разработчики, вероятно, уже знакомы с частью описанных в книге техник. Для них наиболее полезным может оказаться список литературы в конце книги.
Какие темы затрагивает книга
Мы поговорим о различных приёмах и техниках улучшения кода, а также сам процесс рефакторинга. В частности, мы обсудим:
Понятие рефакторинга и качества кода
Что такое рефакторинг вообще, зачем он нужен. К чему приводит неуправляемо растущая сложность проекта. Как определять «плохой» и «хороший» код.
Что делать до и во время рефакторинга
На что обратить внимание перед стартом. Как подготовить код к изменениям, чтобы упростить работу. Как обезопасить работу с будущими изменениями. Чего избегать во время рефакторинга, как облегчить процесс. Как изолировать изменения и убедиться, что не поломался другой код. Как не выходить за рамки бюджета и держать изменения небольшими.
Форматирование, линтинг и возможности языка
Как использовать все возможности автоматических инструментов рефакторинга и анализа кода. Зачем знать нюансы языка и окружения, в котором исполняется код. В чём польза автоматизации. Как консистентность помогает быстрее решать задачи.
Именование сущностей
Почему именование важно, как имена переменных и функций влияют на восприятие кода и скорость разработки. Почему синхронизация терминологии улучшает взаимодействие в команде. Как определить «плохие» и «хорошие» имена. Что делать с именами, которые врут.
Дублирование кода
Как разделять дублирование и недостаток знаний, зачем использовать дублирование в качестве инструмента. В чём польза регулярных аудитов кода и как выработать привычку их заводить.
Понятие абстракции и разделение ответственности
Как и зачем использовать абстракцию. Зачем делить намерение и реализацию. Чем мешает ограничение рабочей памяти человеческого мозга. Как выдавать информацию о системе дозировано и контролируемо. Что помогает декомпозировать сложные задачи на более простые. Как удостовериться, что данные в корректном состоянии.
Функциональный пайплайн и линейное выполнение
Как и зачем выделять состояния данных в бизнес-процессах. В чём польза линейного выполнения кода. Как «запретить» передачу невалидных данных и обособить валидацию. В чём польза принципов функционального программирования.
Условия и сложность кода
Как организовать условия в коде, чтобы не увеличить сверх меры когнитивную нагрузку кода. Какие метрики использовать для измерения сложности. Как использовать автоматические инструменты для управления сложностью. Зачем «выпрямлять» выполнение кода и «выворачивать» условия. Как использовать законы булевой алгебры, чтобы упрощать условия. Какие шаблоны проектирования могут помочь это сделать. Как применять функциональное программирование для этих же целей.
Улучшение кода с сайд-эффектами
Почему сайд-эффекты делают программу сложнее и непредсказуемее. Как уменьшать количество эффектов в коде и что делать с эффектами, необходимыми для работы приложения. В чём польза чистых функций и ссылочной прозрачности. Как тестировать эффекты, зачем отделять логику от эффектов. Что такое команды и запросы, в чём смысл деления кода на них.
Способы обработки ошибок
Какие бывают виды ошибок, чем они отличаются. Как и чем мешает запутанная обработка ошибок. На что обращать внимание при рефакторинге обработки ошибок в JS-коде. Какие использовать техники при наличии ограничений на технологии, парадигму или методологии.
Упрощение интеграции модулей
Что такое зацепление и связность. Как делить приложение на модули и потом компоновать эти модули друг с другом. Зачем и по какому принципу декомпозировать задачи. В чём польза контрактов и гарантий между модулями. Как максимально расцепить модули друг от друга, но при этом оставить возможность для их общения. В чём разница между объектной и функциональной композицией. Как работать с зависимостями. Как добиться целостности и согласованности данных.
Обобщения и иерархии
Как понять, когда нужен обобщённый алгоритм или тип. Почему в большей части случаев композиция предпочтительнее наследования. Как использовать принцип подстановки Лисков в качестве интеграционного линтера.
Основы рефакторинга архитектуры приложений
Чем может мешать слабая архитектура при рефакторинге. Как использовать повсеместный язык для улучшения архитектуры. Как строить взаимодействие с внешним миром и работу с зависимостями. В чём польза портов и адаптеров. Зачем разделять UI-логику от бизнес-логики. Как архитектура влияет на тестируемость.
Декларативный стиль программирования
В чём польза декларативного стиля кода по сравнению с императивным. В каких ситуациях наоборот предпочесть императивный стиль. Зачем могут пригодиться конечные автоматы во фронтенд-разработке.
Использование статической типизации
Как использовать типы для передачи дополнительных данных о предметной области. Как сделать невалидные состояния данных невыразимыми в коде. Как использовать типы для проверки кода на нарушение договорённостей и принципов разработки, принятых в команде.
Рефакторинг тестового кода
Как не сломать тесты во время рефакторинга, чем проверять тесты после него. Что делает тесты «хрупкими». Как найти баланс между высоким покрытием и низким «уроном от тестов».
Улучшение документации и комментариев
Как синхронизировать источники правды в проекте и предотвратить их рассинхронизацию. Как и зачем делать комментарии информационно насыщеннее. Как увеличить пользу документации, не увеличив затраты на её ведение. Чему в проекте уделять внимание «кроме кода».
Рефакторинг как процесс
Как понять, рефакторить или переписывать код. Какую информацию о проекте собрать перед началом работы. Чем руководствоваться при расчёте времени на задачу. Какими метриками измерять влияние рефакторинга на код.
Чем эта книга не является
Я не претендую на единственно правильный способ рефакторить или писать код. Если у вас много опыта, вероятно, о большей части описанных техник вы уже знаете и у вас есть своё мнение на их счёт.
Также я не стараюсь написать «мануал», который будет универсально применим во всех проектах. Моё восприятие, привычки и метод работы искажены моим опытом разработки. Решение, применять идею или нет, сильно зависит от проекта, задачи, ресурсов и цели рефакторинга. Старайтесь выбирать те идеи, которые принесут больше выгоды при меньших затратах.
Обратная связь и ошибки
Книга бесплатная и доступна на Гитхабе.
Если вы заметили опечатку или у вас есть идеи, как улучшить текст и примеры кода, пожалуйста, отправьте их в ишьи в репозитории на Гитхабе. История изменений и обновлений будет доступна в истории комитов этого репозитория.
Сейчас книга доступна на 2 языках: русском и английском. Если у вас есть желание помочь с переводом, напишите мне, пожалуйста, на почту. Буду рад обсудить детали!
Надеюсь, книжка окажется полезной!
Ссылки и ресурсы
Книжка, содержание, список литературы и доклад, с которого всё началось: