CTO Vetmanager, PHP Developer, Ironman 70.3

«5 строк кода»: обещали инквизицию, а выдали здравый смысл

Обложка: 5 строк кода

Зная мои извращённые вкусы, мне посоветовали книгу Кристиана Клаузена «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?».

Вывод

Обещал рассказать, зачем читать книгу про ручной рефакторинг, когда код пишет агент.

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

Так что читайте. Не чтобы рефакторить руками — чтобы понимать, что заказывать.

А здравый смысл, которым заканчивается книга, агенту пока не завезли. Он всё ещё ваш.