
Зная мои извращённые вкусы, мне посоветовали книгу Кристиана Клаузена «5 строк кода». Читал я её с февраля по июнь, по дороге ругался и восхищался в Телеграме. Дочитал — пора собрать всё в одну честную рецензию.
Есть нюанс. Читал я её в уходящую эпоху — когда код ещё писали руками. Пока я мусолил главу про извлечение метода, агенты научились рефакторить сами. Так что перед вами рецензия на книгу о ремесле, которое отменили, — что-то вроде обзора учебника по каллиграфии после изобретения принтера.
Дочитайте до конца — там расскажу, зачем её читать всё равно.
Чем книга купила с порога
Предисловие — как я люблю. Без экивоков.
Вместо абстрактного запаха «функция должна выполнять одно действие» автор сразу выкатывает ультимативное правило: метод никогда не должен содержать больше пяти строк кода. Никакой эзотерики, никаких «всё не так однозначно». Круто!
Ладно, наврал. Один экивок есть:
Заметьте, что все названия правил выражены в абсолютной категоричной форме и в них используются слова вроде «никогда»: это упрощает запоминание. Однако в их подробных описаниях зачастую указываются исключения — ситуации, когда эти правила не рекомендуется применять. В начале изучения рефакторинга нужно использовать только абсолютную форму правил. После того как мы их усвоим, можно будет перейти к изучению исключений и лишь затем опираться уже на их базовое назначение — вот тогда мы станем настоящими гуру в написании кода.
Но экивок многообещающий. Я предвкушал: сейчас будут категоричные заявления, и костры ООП-инквизиции запылают на страницах.
Спойлер: запылали не везде.
Булева арифметика, которую все знали кроме меня
Простая штука из пятой главы, которая реально осела в голове: || работает как сложение, && — как умножение. Мнемоника от автора — две палки || можно сложить в +, а внутри & спрятан знак ×.
Дальше включаются обычные арифметические правила. Раскрытие скобок — как в школе: a × (b + c) = a×b + a×c.
// было
if ($client->isVip() && ($pet->isDog() || $pet->isCat()))
// раскрыли скобки
if (($client->isVip() && $pet->isDog()) || ($client->isVip() && $pet->isCat()))
Работает и в обратную сторону — вынесение общего множителя:
// было: лапша из повторов
if (($doctor->isFree() && $client->hasDebt()) || ($doctor->isFree() && !$pet->isVaccinated()))
// вынесли за скобку
if ($doctor->isFree() && ($client->hasDebt() || !$pet->isVaccinated()))
И приоритеты те же: умножение сильнее сложения, && сильнее ||. Поэтому a && b || c — это (a && b) || c, и скобки тут можно не писать. А вокруг || внутри && — обязательно.
Условное выражение можно преобразовывать, не разбираясь, что оно делает — как школьный многочлен.
Единственное требование — никаких побочных эффектов в условиях. Если $client->hasDebt() заодно пишет в лог или, не дай бог, списывает долг — арифметика ломается. «Чистые условия», как называет их автор. Ещё одно правило в копилку, тоже категоричное, тоже полезное.
Долой общие аффиксы
Мой любимый догмат из книги: всегда избегать общих аффиксов.
Все ваши UserModel, InvoiceModel, UserController — это шляпа и полная безвкусица. У вас есть директории и неймспейсы, чтобы такого не делать. Но всё равно все всё делают.
Пример из книги. До:
interface Protocol { ... }
class StringProtocol implements Protocol { ... }
class JSONProtocol implements Protocol { ... }
class ProtobufProtocol implements Protocol { ... }
let p = new StringProtocol();
Мерзость, коей полно в любом PHP-проекте. После:
namespace protocol {
export interface Protocol { ... }
export class String implements Protocol { ... }
export class JSON implements Protocol { ... }
export class Protobuf implements Protocol { ... }
}
let p = new protocol.String();
Любо!
Рефакторинг по шагам, с работающим кодом в каждой точке
А вот это самая недооценённая часть книги — и главная причина дать её новичку.
Автор не говорит «перепишите это красиво». Он показывает механику: каждый приём рефакторинга расписан по шагам, как сборка мебели. Извлекли метод — компилируется. Перенесли код в класс — компилируется. Заменили if на полиморфизм — работает как раньше.
Даже большую кучу легаси-кода так можно привести к нужному виду за несколько итераций — и в любой момент у вас работающий код, который можно закоммитить и уйти домой. Не «сломал всё, к пятнице соберу обратно», а маленькие безопасные ходы.
Опытные так и рефакторят, на мышечной памяти. Но нигде эта механика не расписана настолько подробно и без пафоса. Джуну — читать обязательно, именно ради этих глав.
Где автор плавает
В середине книги я застрял. Начались главы, в которых «всё не так однозначно». Безумно скучно такое читать. Будто читаешь код с такими комментариями:
// Вызываю функцию do
do();
Я даже с удовольствием переключился на Ицхака Адизеса. Там всё просто и однозначно: все менеджеры легко классифицируются, все компании переживают одни и те же стадии. Отдохнул душой — вернулся.
Конкретные претензии:
- Комментарии. Автор поделил их на пять или шесть видов и нашёл один, который можно оставить в коде. Будь мужиком — скажи, что удалить нужно все!
- Закон Деметры. Глава тривиальна, дотянулся проклятый Elegant Objects — но без радикализма Бугаенко. Ни рыба ни мясо.
- Пара глав подряд, где каждое правило обвешано таким количеством «но», что правилом это уже не назовёшь.
Главный тезис — и он не про пять строк
Ближе к концу автор выдаёт мысль, ради которой стоило дочитать:
Код представляет собой необходимость. Это неизбежное зло, с которым нам приходится мириться, чтобы система выполняла свои функции.
Я выражаю это короче: лучший код — код, который не написан.
А заканчивается книга вот чем:
Правила должны использоваться в качестве подспорья командной работе и сотрудничеству. При этом во время рефакторинга главным ориентиром должен выступать здравый смысл.
То есть обещали инквизицию — а на последней странице выдали здравый смысл. Костры погасили, еретиков отпустили. Я даже не знаю, обижаться или соглашаться.
Кому читать
Джунам и мидлам — обязательно: категоричные правила дают опору, а главы про пошаговый рефакторинг заменяют год насмотренности. Тем, кто прошёл через Фаулера, Мартина и Бугаенко, — можно пропустить: новых идей будет процентов десять.
Книга написана на TypeScript, но бэкендеру всё переносится один в один. Философия автора мне близка — я про то же писал в «Почему связанные тесты — это зло» и «SRP или DRY?».
Вывод
Обещал рассказать, зачем читать книгу про ручной рефакторинг, когда код пишет агент.
Затем, что агент рефакторит ровно так, как вы попросили. Попросите «сделай красиво» — получите красивую кучу. А «методы до пяти строк, чистые условия, никаких общих аффиксов, маленькими шагами с работающим кодом в каждой точке» — это уже техзадание. Правила из книги никуда не делись — просто теперь их исполняет другой работник.
Так что читайте. Не чтобы рефакторить руками — чтобы понимать, что заказывать.
А здравый смысл, которым заканчивается книга, агенту пока не завезли. Он всё ещё ваш.