Автоматичне форматування коду: де ламається процес
Автоматичне форматування коду майже завжди відкладають: репозиторій зростає швидше, ніж доходить черга до налаштування правил. Поки команда невелика, стиль тримається на домовленостях і уважності рев’юера — відступи, лапки, порядок імпортів, довжина рядка.
Але варто з’явитися другій мові й третьому репозиторію, як стиль роз’їжджається: кожен редактор налаштований по-своєму, а єдиного джерела правди немає.
Ціна проявляється не в суперечках про смаки, а у вимірюваних речах. Ручні правки в рев’ю — найчастіша причина зауважень: цикл обговорення витрачається на пробіли й перенесення рядків замість логіки зміни.
Шум у діфах зростає разом із кількістю зачеплених файлів — реальну зміну доводиться шукати серед переформатованих сусідніх рядків, час до злиття збільшується, а ймовірність пропустити дефект зростає.
Окрема категорія — зриви збірки через стиль. Prettier, Black і gofmt запускають на одному кроці конвеєра, перевірку стилю — на іншому, і правила на машині розробника розходяться з правилами на сервері збірки.
Підсумок — червона збірка на рядку, який автор не чіпав, і звичка перезапускати її замість розбору причини. Нижче розбираємо, як це закривається і чому у форматера має залишитися один режим запуску.
Що змінюється в команді та конвеєрі після впровадження автоформату
Форматер запускається до рев’ю, а не після нього: хук на коміт переписує файл, а перевірка в конвеєрі падає, якщо стиль розійшовся з конфігом. Рев’юер бачить лише смислові зміни — перестановку пробілів і перенесення рядків за нього вже зробив інструмент. Це змінює не швидкість окремих людей, а структуру самого процесу.
Ефект вимірний. До впровадження на правки відступів і лапок ішло від чверті до половини часу рев’ю, а діфи додавали сотні рядків шуму.
Після — частка рядків, змінених зі стилю, падає майже до нуля, а спірні правки перестають бути предметом обговорення: про них домовляються один раз у конфізі.
Єдиний стиль без ручних правок
Конфіг версіонується разом із проєктом, тому правило однаково працює в редакторі, на локальній машині та в конвеєрі. Prettier із зафіксованим набором опцій прибирає варіативність: файл приводиться до одного вигляду незалежно від того, хто його писав. Новому інженеру не потрібно вивчати чужу манеру оформлення — форматер застосовує її сам.
Менше шуму в рев’ю та правок у діфах
Менше шуму в діфі — швидше сходиться перевірка: зауваження зміщуються з оформлення на логіку та граничні випадки. Стабільність збірки зростає з тієї ж причини — розбіжності в стилі зникають зі списку причин відмови.
Перед масовим прогоном форматування виносять в окремий коміт, щоб в історії не змішувалися смислові та косметичні зміни.
Режими перевірки та правки: від локального хука до кроку збірки
Режими відрізняються тим, хто і коли платить за виправлення: локально правка коштує секунди, у конвеєрі — цикл збірки, рев’ю та повторний запуск. Тому формати зазвичай поєднують, а не вибирають один. Нижче — коли який режим доречний і де він перестає працювати.
Локальна правка до коміту
Форматування під час збереження в редакторі тримає робочу копію в узгодженому вигляді: автор не думає про стиль, діфи не засмічуються перестановкою пробілів.
Правка перед комітом через передкомітний хук проганяє форматер по змінених файлах і зупиняє коміт, якщо щось залишилося невиправленим. Вибірковий прогін по файлах важливий у великих репозиторіях: повний обхід усіх вихідних кодів на кожен коміт помітно гальмує роботу.
Перевірка як обов’язковий крок конвеєра
Тут форматер запускається в режимі перевірки, без запису, і падає з ненульовим кодом повернення. Це єдиний режим, який не можна обійти локальними налаштуваннями, — він і слугує спільним бар’єром для всіх гілок. Плата за це — правку доводиться вносити після пушу, а отже, запускати збірку заново.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Форматування під час збереження | Щоденна робота, потрібен миттєвий відгук | Залежить від налаштувань кожного розробника, не діє під час правок у веб-інтерфейсі |
| Правка перед комітом | Потрібно не пускати неформатований код в історію | Вимагає встановлення хуків у кожного, обходиться прапорцем пропуску перевірок |
| Крок конвеєра | Спільний бар’єр для всіх гілок і зовнішніх учасників | Помилка видна лише після пушу, потрібен повторний прогін збірки |
| Вибірковий прогін по змінених файлах | Великі репозиторії з довгим повним обходом | Потрібна коректна база порівняння гілки, інакше частина файлів випадає |
Як ми вмикаємо перевірки стилю в конвеєр: етапи робіт
Форматування, увімкнене одним комітом у всі репозиторії, обнуляє історію правок: перестає бути зрозуміло, хто і навіщо змінював рядок, а огляд змін тоне в перестановці пробілів. Тому впровадження форматування ведемо окремим проєктом з оборотними кроками, що не блокують релізи.
Інвентаризація репозиторіїв і винятків
Спочатку збираємо карту: мови та їхні частки, активність, згенерований код, вендорні каталоги, файли з навмисним вирівнюванням — таблиці, схеми міграцій, розмітка. Усе, що створюється збіркою, потрапляє у винятки, інакше форматер і генератор правлять одне одного нескінченно.
- Інвентаризація репозиторіїв: мови, активність, згенеровані та вендорні каталоги.
- Спільний профіль правил — єдиний набір налаштувань на організацію, відмінності за мовами задані перевизначеннями, а не копіями.
- Пілот на одному репозиторії в режимі перевірки без правок — оцінюємо частку файлів, які будуть зачеплені.
- Разовий прогін по репозиторію окремим комітом: лише форматування, без смислових змін.
- Підключення перевірки на гілці — спочатку попередження, потім обов’язкова умова злиття.
- Поетапне включення решти репозиторіїв партіями, від найактивніших до архівних.
- Передача команді: профіль, команди запуску, автоправка перед комітом у локальному середовищі.
Поетапне посилення перевірок
Обов’язковість вводимо не одразу: репозиторій живе в режимі попередження, поки перевірка не перестане спрацьовувати на згенерованих файлах. Потім вона стає блокувальною — не пройдене форматування не потрапляє в основну гілку, і стиль перестає бути предметом суперечок в оглядах.
Що залишається в команди: конфігурації, правила, регламенти
Форматування в конвеєрі — це не одна команда, а набір артефактів у репозиторії. Їхнє завдання — щоб новий інженер за пів року отримав ті самі правила однією командою, без листування з автором налаштування.
Файли конфігурації та спільний профіль правил
- Єдиний профіль правил у корені репозиторію: один конфіг на всі мови, без локальних варіацій у підкаталогах — розходження налаштувань між модулями зникає як клас.
- Узгодження з редактором:
.editorconfigповторює ті самі відступи та перенесення, щоб правки в IDE не конфліктували з форматером під час злиття. - Списки винятків: згенерований код, вендорні каталоги, міграції — форматується лише те, що команда править руками.
- Крок перевірки в конвеєрі: злиття блокується, якщо файл не відформатовано; автовиправлення приходить окремим комітом.
- Хук на машині розробника: передкомітна перевірка не пускає невідформатований код і економить прогони конвеєра.
Документація та порядок винятків
- Коротка інструкція в репозиторії: як прогнати форматування локально, де лежить конфіг і що робити при конфлікті з лінтером.
- Порядок відступів від правил: виняток оформлюється з причиною та власником, інакше список зростає і правила перестають діяти.
- Регламент змін профілю: правка правил іде окремою зміною з прогоном по всьому репозиторію, а не «попутно» в робочій задачі.
Підсумок — форматування перестає залежати від домовленостей: діфи в рев’ю містять сенс, а перевірка відтворювана на будь-якій машині.
Кейс: монорепозиторій без ручних правок стилю
Замовник прийшов із монорепозиторієм: десяток сервісів кількома мовами, а єдиний стиль існував лише як усна домовленість.
Форматування кожен запускав вручну, не завжди перед комітом, і перевірка коду перетворювалася на суперечку про відступи — близько третини зауважень стосувалися вигляду файлу, а не логіки.
Було
Перевірка коду на середній гілці займала близько 35 хвилин, і майже кожен третій коментар був про форматування.
Приблизно кожен п’ятий коміт не змінював поведінку системи, а лише правив відступи та перенесення: такі правки осідали в спільній історії й заважали розбирати зміни під час відкату.
Конфлікти злиття у файлах, які ведуть кілька команд, виникали саме через різний формат — розбір злиття займав більше часу, ніж сама доробка.
Стало
Форматування перенесли в конвеєр: перевірка йде до обговорення змін, при розходженні збірка падає й додає готовий виправлений варіант. Історичні файли прогнали окремим комітом через Prettier — без змін логіки, щоб правки залишалися читабельними.
Час перевірки коду скоротився з 35 до 12 хвилин. Частка комітів лише зі стилем — менше 2%. Конфлікти злиття через форматування майже зникли: кількість випадків упала приблизно в п’ять разів, а однаковий вміст у двох гілках тепер дає ідентичний файл. Обговорення знову про логіку, а не про пробіли.
Форматування та лінтинг: у чому різниця і що робити з легасі
Форматер і лінтер відповідають на різні питання, і спроба закрити обидва однією перевіркою породжує нескінченні суперечки в рев’ю. Форматер працює із зовнішнім виглядом: відступи, довжина рядка, лапки, порядок імпортів — він перезаписує файл і завжди дає однаковий результат.
Лінтер дивиться на сенс: невикористані змінні, недосяжні гілки, підозрілі порівняння — і править їх лише частково.
| Критерій | Форматер | Лінтер |
|---|---|---|
| Предмет | зовнішній вигляд коду | логіка та потенційні помилки |
| Результат | детермінований, однаковий у всіх | зауваження з рівнями важливості |
| Автовиправлення | повне, файл перезаписується | часткове, частина рішень за інженером |
| Успадкований код | вмикається одним масовим проходом | вмикається поступово, за правилами |
| Джерело налаштувань | один конфіг у репозиторії | набір правил і поріг спрацьовування |
Розділення перевірок у конвеєрі роблять за кроками: форматування — окремий крок з автовиправленням, лінт — окремий, зі своїм кодом повернення. Падіння одного не маскує інше, і розробник одразу бачить, що саме потрібно виправити.
На давно живучому коді порядок зворотний до звичного. Спочатку один масовий прохід форматера, винесений в окремий коміт, — далі будь-яка правка йде по вирівняному файлу, а історія змін не засмічується стильовими правками.
Лінтер вмикають поступово: правило за правилом, зауваження в старих модулях переводять у попередження, блокують лише нові.
Правила без конфліктів виходять, коли істина одна: стиль задає форматер, а з набору лінтера прибирають усе, що дублює оформлення. Інакше інструменти тягнуть один і той самий код у різні боки, і команда вимикає перевірки цілком — разом із корисними.
Технічні сумніви: шум в історії, чужі мови, винятки
Разове переформатування — це коміт на сотні файлів, де логіка правок не читається, а git blame після нього показує автором того, хто запустив форматер. Обидві проблеми знімаються процедурою, а не умовляннями.
Чотири сумніви, які звучать перед увімкненням обов’язкової перевірки, і те, як кожен закривається конфігурацією та процесом.
Разовий коміт «переформатувати все» зламає історію
Прохід роблять однією окремою ревізією, а її хеш вносять у файл ігнорування — історія рядків зберігається, і звичайний коментар до правки залишається осмисленим. Далі формат змінюється лише в тих рядках, які й так правили.
У нас змішаний стек
Перевірка розбивається за масками: у кожної мови свій форматер і конфіг, які запускаються лише на її файлах. Що не потрапило під жодну маску — не перевіряється, тому нова мова не вимагає переписувати правило цілком.
Є згенероване та вендорні каталоги
Ігноруються збірки, міграції, схеми та сторонні бібліотеки: згенероване не форматуємо, інакше наступна генерація поверне правки й перевірка впаде знову. Прикордонний випадок закривається точковим вимкненням на файл або блок із коментарем про причину.
У команд різні стилі
Стиль переїжджає з листування в один спільний конфіг — суперечка стає правкою одного файлу, видимою на рев’ю. Перевірка в конвеєрі робить підсумок необговорюваним: стилі команд сходяться до зафіксованого набору правил, а не до чийогось смаку.
Обговоримо задачу та повернемося з оцінкою й планом робіт
Щоб розмова була предметною, а не загальною, нам достатньо кількох вступних. Автоматичне форматування майже цілком залежить від вашого репозиторію: один він чи десяток пов’язаних, які мови в ньому сусідять, що вже зафіксовано в правилах і що заважає увімкнути перевірку сьогодні. Нижче — те, що допомагає повернутися з оцінкою та планом, а не з уточнювальними питаннями.
- Склад репозиторіїв: де монорепозиторій, де окремі сервіси, які мови і в якому співвідношенні, чи є спільні каталоги з бібліотеками.
- Поточні правила оформлення: конфігурації форматерів, налаштування редактора, винятки для згенерованого та вендорного коду, спірні файли.
- Вимоги до перевірок: що має блокувати злиття, чого достатньо попередити, які гілки захищені й чи потрібен автофікс замість відмови.
- Частка успадкованого коду: обсяг файлів, які не можна форматувати одним комітом, і готовність команди до великої разової правки.
- Порядок викату: чи плануєте вмикати одразу на всі гілки або поетапно — спочатку звіт, потім автофікс, потім блокування.
- Середовище виконання: де запускаються завдання збірки, чи є обмеження щодо доступів та ізольовані виконавці.
Опишіть задачу у вільній формі — склад репозиторіїв, мови та поточні правила. Повернемося з оцінкою та планом робіт, де порядок викату розписаний за кроками і зрозуміло, що перевірити до увімкнення блокування.







