Інженерна майстерність і карʼєра / крок 04
Голосове №3 — страшні абстракції
Про що це відео
Третій випуск серії «голосових» — про дивний феномен, який він постійно спостерігає (навіть зробив про це слайд для доповіді на DOU Day, але не встиг розповісти): розробники бояться створювати нові абстракції. Менш досвідчені розробники працюють за шаблоном — або допихають новий вміст в існуючі файли/класи, або копіюють файли з готовою структурою; по-справжньому нові абстракції зʼявляються дуже рідко. Він доводить, що річ насправді не у створенні нового файлу (файли розробники створюють постійно і в React, і на бекенді) — а в тому, що вигадування нової абстракції вимагає подумати, як зробити її правильно: додаткове зусилля, у яке багато хто не готовий інвестувати, плюс джуни ще не бачать наслідків того, що абстракцію не створили (Проєктування програмного забезпечення).
Головне
- Історія 1 —
assertDateу TestFactory (webilab): у їхніх бекендних тестах є абстракціяTestFactory(створює тестових користувачів/дані/склади для підготовки середовища) і chai для assert-ів. Комусь знадобився кастомний assert для календарних дат — і він опинився вTestFactory.assertDateлише тому, щоTestFactory— це обʼєкт, уже доступний у кожному тесті, хоча його відповідальність зовсім інша. Правильний хід був сміховинно малий: новий модуль з однією функцією. - Цей патерн узагальнюється до класичного антипатерну God Object: він бачив, як базові класи сервісів накопичують утиліти для дат, файлів, сесій — усе звалюють у батьківський клас, «щоб усі нащадки могли дотягнутися», замість створити
DateUtils,FileUtilsтощо, аж поки базовий клас не стає незвʼязною купою відповідальностей. - Історія 2 — proof of concept на 100 рядків, що став файлом на 5000: для вебсистеми презентацій у стилі PowerPoint (webilab) він написав маленький PoC (~100 рядків): серіалізовну структуру даних слайда, примітив віджета з позицією/поворотом/конфігом і пару стандартних віджетів (коло, прямокутник, текст). Через пів року: один файл, 5000 рядків, усі віджети плюс підсистеми синхронізації впереміш, підтримувати неможливо. Коли він спитав чому, відповідь була: «ну, ви ж так показали». Його думка: коли було 100 рядків, та структура була правильною; коли відповідальності ростуть, треба виділяти нові абстракції — а розробники йдуть за наявним патерном і просто докладають. Показово, що команда сама відчувала біль (усе «не летіло») і сама ініціювала той review.
- Історія 3 — білдери (перегук із голосовим №2): маючи низькорівневий ґрід із декларативним конфігом, усі копіюють цей сирий конфіг на кожен екран замість написати вищерівневий, проєктно-специфічний білдер/фасад, який ховає низькорівневу конфігурацію, — той самий страх додати структуру, якої ще не існує.
- Історія 4 — контролер, якого бракувало: обговорюючи React-проєкт знайомих із dumb- і smart-компонентами, він побачив, що бракує координаційної абстракції для високорівневих дій. Його пропозиція — просто додати контролер — була команді некомфортна, бо ніхто на тому проєкті так ніколи не робив. Тим часом у Google, коли UI-підсистемі бракувало абстракцій, він додав контролери над низькорівневими частинами, які ховали деталі конфігурації, перевикористовувалися і «чудово» спростили код та його підтримку.
- Мета-урок: досвідчені розробники створюють нові абстракції, коли зʼявляються нові відповідальності; небажання це робити — перевикористання будь-якої вже наявної структури — і є те, що повільно гноїть кодову базу, навіть коли кожна окрема зміна виглядає консистентною з навколишнім кодом.