← Усі статті

Чистий код (Clean Code): читабельність без догм

Розбір Мартіна: імена, функції, тести й межі — з критикою догм, контекстом ШІ, кейсами та діями на сьогодні. Не замінює книгу.

Чистий код (Clean Code): читабельність без догм
Зміст

Два запити на злиття виправляють одну й ту саму помилку. У першому рецензент за п’ять хвилин розуміє намір і дивиться на ризики. У другому — пів години суперечки про довжину функцій і фігурні дужки, а питання «де тепер живе правило бізнесу?» так і не з’являється. Код «чистий» на вигляд — і все одно небезпечно змінювати.

Чистий код (Clean Code) Роберта Мартіна часто читають як збірник правил стилю. Корисний шар книги інший: читабельність під зміни — імена, межі функцій, тести, робота з чужим кодом. Нижче — розбір своїми словами з критикою спірних місць (і вони є: спільнота сперечається з книгою вже багато років, особливо після альтернатив на кшталт Ousterhout). Вижимка не замінює оригінал.

Теза книги

Хороший код читається майже як проза: ви витрачаєте час на розуміння наміру, а не на розшифровку шуму. Мартін пов’язує це з професійною відповідальністю: залишати код легшим для наступної людини — часто для вас через півроку.

Книга не про «красу заради краси». Вона про зниження вартості правки: менше прихованих припущень, менше сюрпризів на перегляді коду, менше страху перед рефакторингом. Але багато порад треба перекласти на ваш контекст — мову, домен, стиль команди, епоху після появи ШІ-помічників.

Ключові ідеї

Імена як документація

Що каже автор. Ім’я має відповідати на питання «навіщо існує», а не «якого типу». Уникайте шуму (data, info, manager, process), хибної точності та невдалих скорочень. Клас — іменник або іменникова фраза; метод — дієслово або дієслівна фраза. Константи й переліки мають передавати сенс домену.

Як це виглядає в Enterprise. Файл із трьохсот рядків, де result, temp і handle() зустрічаються двадцять разів — і пошук по репозиторію марний. Нова людина перейменовує одну змінну — і ламає звіт, бо ім’я було єдиною «документацією» зв’язку із зовнішньою системою.

Як це змінюється з ШІ. Модель генерує правдоподібні імена: validateUser, processOrder, handleRequest. Звучить охайно — але метод робить три речі й надсилає листа. ШІ рідко питає: «це ім’я бреше про побічний ефект?» Ваше завдання — перевірити відповідність імені й поведінки, не приймати «гарний» набір змін.

Де порада може не спрацювати. Догма «ім’я має бути ідеальним» перетворює запити на злиття в косметику. У гарячому успадкованому коді іноді краще вузьке перейменування в зоні правки плюс коментар до інваріанту, ніж героїчне перейменування всього модуля без тестів.

Що зробити вже сьогодні. Відкрийте файл, який ви правили останнім. Знайдіть одне ім’я, яке бреше про те, що робить код. Перейменуйте або додайте уточнюючий контекст у сусідньому рядку.

Мій досвід. Імена — найдешевший рефакторинг із найвищою віддачею для junior і middle. Для senior частіше проблема не в foo, а в тому, що поняття не назване в домені — тоді потрібна розмова з продуктом, а не лише перейменування.

Якщо запам’ятати одну думку — назвіть ідею, а не тип даних.

Функції: одне завдання й один рівень абстракції

Що каже автор. Функція робить одне; аргументів мало; рівень абстракції всередині тіла один — не змішуйте «копійки в рублі» й HTTP-відповідь в одній площині. Розмір функції другорядний щодо ясності, але довгі «процедури на все» — ознака змішання відповідальностей.

Як це виглядає в Enterprise. Обробник на чотириста рядків: валідація, SQL, відображення, відправка в чергу, журналювання «на всякий випадок». Кожна правка — лотерея: торкнулися рядка 120 — упало сповіщення в іншому кінці файлу.

Як це змінюється з ШІ. Помічник охоче дробить код на десятки однорядкових шматків «за Clean Code». Читабельність формально зростає, зв’язність падає: стрибаєте по файлу, втрачаючи сюжет. Корисніше просити: «винеси рівень домену окремо, межу вводу-виводу залиш явною».

Де порада може не спрацювати. Культ «функція не довша за п’ять рядків» — зворотний бік книги. John Ousterhout у A Philosophy of Software Design справедливо б’є по дрібних модулях із шумним інтерфейсом: іноді глибокий шматок із простим контрактом читабельніший за ланцюжок обгорток. Не дробіть заради метрики.

Що зробити вже сьогодні. В одному «товстому» методі проведіть горизонтальну лінію: усе нижче — деталі реалізації. Винесіть їх або хоча б згрупуйте під говоручим іменем.

Мій досвід. Я ріжу функції там, де змінюються причини правки (валідація проти збереження проти інтеграції). Не там, де лінтер незадоволений довжиною, а сенс один.

Якщо запам’ятати одну думку — читач не має мисленно «розпаковувати» три шари абстракції на одному екрані.

Коментарі: пояснювати «чому», а не вибачатися за код

Що каже автор. Коментарі не мають дублювати очевидне; закоментований мертвий код — сміття; хибні коментарі гірші за відсутність. Добрий коментар фіксує намір, інваріант, попередження, юридичний або історичний контекст.

Як це виглядає в Enterprise. Кладовище // TODO 2019 і блоки if (false). Або коментар «синхронізуємо з ERP» — а інтеграція переїхала три роки тому. Довіра до коментарів нижче нуля — і нові не пишуть.

Як це змінюється з ШІ. Модель генерує безглузді описи («отримує user і повертає result») і стирає старі коментарі з «чому». Після автоправки перевіряйте: чи не зник єдиний текст про обмеження вендора або стан гонки.

Де порада може не спрацювати. Фраза «коментарі — ознака провалу» стала релігією. На межах систем, у фінтеху й регулюванні коментар до неочевидного компромісу — частина дизайну. Не плутайте шум і інженерну записку.

Що зробити вже сьогодні. Видаліть один закоментований блок коду (історія в git). Або додайте один рядок «чому» там, де без нього страшно торкатися.

Мій досвід. Я пишу коментарі до того, що не можна висловити іменем: зовнішній баг вендора, навмисне порушення «чистоти» заради продуктивності, узгодженість із контрактом API.

Якщо запам’ятати одну думку — коментар для майбутнього себе під стресом, не для звіту про синтаксис.

Форматування й командний закон

Що каже автор. Вертикальна щільність, близькість пов’язаних рядків, одноманітність важливіші за особистий смак. Команда домовляється про правила й автоматизує їх — суперечки про дужки не мають з’їдати перегляд коду.

Як це виглядає в Enterprise. В одному репозиторії три стилі відступів «за авторами». Зміни на три рядки логіки й двісті рядків переформатування — класичний біль.

Як це змінюється з ШІ. «Відформатуй файл» у запиті на злиття ховає суть зміни. Правило: форматування — окремий коміт або автоформатер у CI, не змішувати з логікою. ШІ-перегляд часто схвалює «гарний» набір змін, не бачачи семантичного дрейфу.

Де порада може не спрацювати. Єдиний стиль на весь монорепозиторій іноді шкодить (згенерований код, DSL). Домовтеся про зони, а не про один «священний» автоформатер для всього.

Що зробити вже сьогодні. Якщо в команді немає автоформатера — запропонуйте один для нового коду. Суперечки про стиль переведіть у конфіг.

Мій досвід. Форматування — дешева турбота про колег. Я не трачу перегляд на табуляцію, якщо CI вже вирішив питання.

Якщо запам’ятати одну думку — стиль це протокол спілкування, не хобі.

Обробка помилок і межі відмови

Що каже автор. Не повертайте null без потреби; не ковтайте винятки; повідомлення про помилки інформативні; межа між доменом і інфраструктурою має перекладати збої в зрозумілі сигнали.

Як це виглядає в Enterprise. Порожній catch (Exception e) { log.warn(...) } у нічному пакеті — вранці «дані не зійшлися», а траси немає. Або API віддає 500 без тіла, і клієнтська частина тиждень показує «щось пішло не так».

Як це змінюється з ШІ. Генерація любить «компілюваний» основний сценарій: catch {}, return null, загальне Error occurred. Явно просіть: контекст, тип помилки, що може зробити викликаючий.

Де порада може не спрацювати. Книга Java-2008: у сучасних екосистемах Result, Either, типізовані помилки іноді ясніші за винятки. Принцип «не ховати збій» важливіший за механізм.

Що зробити вже сьогодні. Знайдіть один проковтнутий catch або null, який уже вкусив. Поверніть сигнал нагору або зафіксуйте контракт.

Мій досвід. Чистота тут — не в кількості try/catch, а в тому, що відмова — частина інтерфейсу, а не сюрприз у журналах.

Якщо запам’ятати одну думку — помилка має допомагати наступній дії, а не зникати.

Тести: страховка змін, а не галочка

Що каже автор. Тести — частина професіоналізму: читабельні, швидкі, незалежні, повторювані, самоперевірні (FIRST). Вони дають сміливість рефакторити. Суперечки навколо «один assert на тест» — скоріше евристика, ніж закон.

Як це виглядає в Enterprise. Тести, що підміняють половину всесвіту заглушками й перевіряють, що «викликалось» — але не поведінку. Або набір на двадцять хвилин, який ніхто не ганяє локально.

Як це змінюється з ШІ. Модель пише тести до згенерованого коду: зелені, крихкі, прив’язані до реалізації. Просіть сценарії, що зламаються при зміні наміру, а не лише імені приватного методу.

Де порада може не спрацювати. TDD як обов’язковий ритуал для кожного рядка — не для всіх доменів. В інтерфейсі й інтеграціях іноді потрібен інший контур. Беріть страховку, не догму.

Що зробити вже сьогодні. Один тест на поведінку, яку ви боїтеся торкнутися в наступному тікеті — без заглушок «заради заглушок».

Мій досвід. Clean Code найкраще поєднується з Fowler (Refactoring): тести дають право на маленькі кроки. Без них «чистота» — косметика.

Якщо запам’ятати одну думку — тест захищає поведінку, яку дорого втратити.

Класи, межі й чужий код

Що каже автор. Клас малий, з однією причиною для зміни (SRP); зв’язність висока. Чужі API обгортаються — не протікають по всій системі. «Навчальні тести» на зовнішні бібліотеки фіксують очікування.

Як це виглядає в Enterprise. SDK платіжки розмазаний по сотні файлів; зміна версії — квест. Або десять класів по «одному методу» без доменного сенсу.

Як це змінюється з ШІ. ШІ імпортує бібліотеку напряму скрізь. Просіть адаптер і одну точку заміни — як у книзі про межі.

Де порада може не спрацювати. SRP до абсурду — клас на кожен геттер. Дивіться на причини зміни, не на лічильник методів.

Що зробити вже сьогодні. Знайдіть прямий виклик зовнішнього SDK у доменному шарі. Намалюйте тонку обгортку — хоча б у голові для наступного запиту на злиття.

Мій досвід. Межі окуповуються на другій зміні вендора. Імена й функції — щодня.

Якщо запам’ятати одну думку — ізолюйте те, що змінюється не за вашим графіком.

На практиці

На перегляді коду

Питайте не «гарно чи ні», а:

  • Зрозумілий намір без археології?
  • Чи не розмазано одне правило бізнесу?
  • Чи є страховка (тест) на ризиковому місці?
  • Чи не сховано відмову?

У команді без домовленостей

Clean Code часто беруть, коли «усі пишуть по-різному». Почніть з автоформатера + імен + тестів на критичне — не з війни за довжину функції.

З успадкованим кодом

Не «приведемо все до ідеалу за спринт». Один модуль, один шов, один тест — див. Ефективна робота з успадкованим кодом у списку серії (Feathers).

З ШІ-помічниками

Перевіряйте три речі після кожного великого набору змін: імена не брешуть; помилки не проковтнуті; тести перевіряють поведінку. «Чистий» стиль від моделі ≠ чиста архітектура.

Кому яка ідея корисніша

Ідея Junior Middle Senior
Імена ★★★★★ ★★★★ ★★★★
Короткі функції ★★★★★ ★★★ ★★
«Без коментарів» ★★★ ★★
Тести ★★★★★ ★★★★★ ★★★★
Обгортки зовнішніх API ★★★ ★★★★ ★★★★★

Оцінки — орієнтир для розмови, не таблиця істини.

Обмеження та критика

Книга 2008 року на Java: приклади, інструменти й частина прийомів старіють. Спільнота справедливо критикує догматизацію: функції «по три рядки», війну з коментарями, деякі приклади SRP.

Коротке порівняння. Clean Code — про локальну читабельність і дисципліну на рівні файлу. The Pragmatic Programmer — про звички інженера й систему загалом (ортогональність, оборотність, інструменти) — див. вижимку. A Philosophy of Software Design — протиотрут від дрібних «чистих» шматків: глибина модулів і простота інтерфейсу. Refactoring (Fowler) — як змінювати код безпечно; Мартін — як він має виглядати, коли ви вже змінюєте.

Читайте Clean Code як словник намірів, не як священний лінтер. Спірні місця — привід думати, не привід для фанатизму.

Кому читати

Варто, якщо в команді немає спільної мови про читабельність; якщо перегляд коду перетворюється на смаковщину; якщо junior пише «працює, але страшно торкатися».

Обережно як єдиний канон, якщо ви senior/platform: ризикуєте нав’язати дрібну чистоту замість модульної глибини.

Паралельно має сенс Fowler на рефакторинг і Ousterhout на дизайн — вони знімають сліпі зони цієї книги.

Що зробити сьогодні

  1. Перейменуйте одну брехливу змінну або метод у зоні поточної задачі.
  2. Видаліть один блок закоментованого коду або мертвий TODO без власника.
  3. Додайте один тест на поведінку, яку боїтеся зламати.
  4. На перегляді коду задайте питання: «де живе правило бізнесу після цих змін?»