image Привет, Хаброжители!

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

Книга не заставляет читателя проводить очистку сразу и целиком, а позволяет протестировать несколько примеров, которые подходят для поставленной задачи. Вы узнаете, как логически разделить на части большую функцию, содержащую множество строк кода. Познакомитесь с теоретическими понятиями программного дизайна: сцеплением, связностью, дисконтированными денежными потоками и вариативностью.
Для кого эта книга
Эта книга предназначена для разработчиков, лидов, практикующих архитекторов ПО и технических руководителей. Она не привязана к конкретному языку программирования, и все разработчики смогут прочитать ее и применить представленные концепции в своих проектах. Предполагается, что читатель уже имеет опыт программирования.
Структура книги
Книга состоит из введения и трех частей.

Введение

Я начну с краткого описания того, почему я написал эту книгу, как я решил написать ее, для кого она предназначена и чего от нее ожидать. Затем перейдем к сути.

Часть I. Очистка

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

Часть II. Управление

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

Часть III. Теория

Здесь я наконец расправлю крылья и погружусь в тему, которая вызывает у меня неподдельный интерес. Что я имею в виду, говоря, что дизайн ПО — это проверка человеческих отношений? Кто эти люди? Почему улучшение дизайна поможет лучше удовлетворять их потребности? Почему программные продукты такие дорогие? Что с этим можно сделать (спойлер: дизайн ПО)? Сцепление? Связность? Степенной закон?

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

Управление


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

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

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

Этот раздел посвящен управлению очисткой. В нем вы узнаете, как интегрировать очистку в ваш личный рабочий процесс:

  • Когда начинать очистку?
  • Когда заканчивать очистку?
  • Как объединить очистку, изменяющую структуру кода, с изменением поведения системы?
Начнем с обсуждения того, как очистка взаимодействует с запросами на вытягивание (пул-реквестами) и код-ревью.

Очистка отдельно


Представьте, что вы используете модель пул-реквест/код-ревью (позже мы обсудим возможную альтернативу). Какое место в этой схеме занимает очистка?

Рассмотрим неэффективную схему «порочного круга»:

  1. Я провожу очистку во время изменения поведения.
  2. Ревьюеры жалуются, что пул-реквесты занимают слишком много времени.
  3. Я выделяю операции очистки в отдельные пул-реквесты — до (более вероятно) или после изменения поведения.
  4. Ревьюеры жалуются, что пул-реквесты с очисткой не имеют смысла.
  5. Возвращаемся к шагу 1.

Для очистки необходимо выделить место или вообще ею не заниматься. Где ее выполнять? В двух словах: в собственных пул-реквестах с минимально возможным количеством действий по очистке на один пул-реквест.

Рассмотрим плюсы и минусы более подробно. Похоже, люди, которые только учатся чистить код, совершают ряд предсказуемых шагов. Первый шаг — просто внести изменения; в таком случае все начинается с недифференцированной массы изменений (рис. 16.1).

image

Где-то в середине исправления инструкции if вы вдруг понимаете, что в ней используется неверное имя, исправляете его и снова возвращаетесь к инструкции if. Изменение есть изменение.

После знакомства с азами очистки все начинает выглядеть так, словно картинка под микроскопом вдруг обрела резкость. Одни изменения меняют поведение программы и ее атрибуты, видимые при ее запуске. Другие меняют структуру программы. Такие изменения можно заметить только при просмотре кода: B — поведение (behavior), S — структура (structure) (рис. 16.2).

К этому моменту еще не существует никакого плана, нет зависимостей между изменением поведения и структуры — только понимание того, что это разные виды изменений, которые влияют друг на друга.

image

Спустя какое-то время вы начинаете замечать общие закономерности. Группировка инструкций помогает увидеть необходимость хелперов, а те в свою очередь упрощают изменения поведения. Теперь программирование начинает напоминать шахматную партию, и вы можете предположить, как будет развиваться игра на несколько ходов (или последовательностей) вперед (рис. 16.3).

image

Обратите внимание: в этой точке все еще существует один большой пул-реквест. Мы находимся на шаге 1 цикла. Каждый ход имел определенную цель: либо вносить простые изменения, либо упрощать их внесение. Но когда все собралось воедино, получилась путаница. Ревьюеры не оценят.

Поэтому мы разбиваем изменения на отдельные пул-реквесты. Серии операций очистки (и даже одиночные действия) включаются в один пул-реквест. Изменения поведения изолируются в отдельном пул-реквесте. Каждый раз, когда мы переключаемся между очисткой и изменением поведения, мы открываем новый пул-реквест (рис. 16.4).

image

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

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

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

Цепочки


Процесс очистки напоминает картофельные чипсы: вы съедаете один, и вам немедленно хочется взять другой. Управление желанием продолжать очистку — один из ключевых навыков. Вы только что улучшили что-то в своем коде; нужно ли продолжать? Это зависит от обстоятельств (а от каких именно, вы узнаете в части III).

Насколько большими должны быть шаги по очистке? Решать вам, но я рекомендую начать с малого. Оптимизируйте каждый шаг. Со стороны будет казаться, что вы бежите со всех ног, но на самом деле вы, словно сороконожка, делаете множество мелких шажков.

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

Охранные выражения

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

Мертвый код

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

Нормализация симметрий

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

Новый интерфейс, старая реализация

Когда вы создали блестящий новый интерфейс, вам хочется его использовать. Если у вас нет автоматизированных средств для преобразования всех точек вызова, вам придется преобразовывать их одну за одной. Здесь мы впервые сталкиваемся с разветвлением на выходе (fanout) — ситуацией, в которой одна операция очистки влечет за собой сразу несколько других, каждая из которых ведет еще к нескольким (я подробнее расскажу об этом, когда речь пойдет о сцеплении и степенных зависимостях).

Порядок чтения

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

Принцип связности

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

Пояснительные переменные

Правую часть присваивания пояснительной переменной целесообразно преобразовать в хелпер (после чего переменную, возможно, удастся встроить). Информация, содержащаяся в имени переменной, может пригодиться для удаления избыточных комментариев.

Пояснительные константы

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

Существуют целые теории, определяющие, где следует размещать константы и как их лучше упорядочить. Я не стану углубляться в эту тему — выберите вариант, который покажется вам самым простым (или хотя бы проще по сравнению с другими).

Явная передача параметров

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

Визуальная группировка инструкций

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

Извлечение хелперов

После извлечения хелперов можно добавить охранное выражение, извлечь пояснительные константы и переменные или удалить избыточные комментарии.

Большая свалка

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

Содержательные комментарии

По возможности переместите информацию из комментария в код, введя пояснительные переменные, пояснительные константы или хелперы.

Удаление избыточных комментариев

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

Раз уж меня обвиняют в нетерпимости к комментариям, еще раз подчеркну: удалять следует только абсолютно, полностью избыточные комментарии. А в процессе очистки стоит стремиться к тому, чтобы комментарии стали абсолютно, полностью избыточными. Ваша задача как проектировщика программного продукта — создать условия для успеха (своего и своей команды) сейчас и в будущем.

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

Выводы


Со временем вы начнете объединять действия по очистке в цепочки и таким образом вносить более крупные изменения в структуру кода. Постарайтесь не изменять слишком много и слишком быстро. Неудачная очистка будет стоить дороже нескольких успешных. Тренируйтесь проводить очистку подобно тому, как вы разучиваете ноты. Когда их звучание станет чистым и естественным, из них можно будет складывать мелодии.
Об авторе
Кент Бек — разработчик, создатель методологии экстремального программирования, первопроходец в области паттернов проектирования, соавтор JUnit, человек, открывший заново разработку через тестирование, и наблюдатель 3X (Explore/Expand/Extract). Его фамилия также значится первой в алфавитном списке подписавших манифест agile-разработки.

Более подробно с книгой можно ознакомиться на сайте издательства:

» Оглавление
» Отрывок

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
Для Хаброжителей скидка 25% по купону — Чистый дизайн

Комментарии (0)