Платформа, яка пережила все
12 / 21

Розділ 11. Чиста типова

Частина III · Розділ 11

Чиста типова

1

Михайла я знайшов через Антона. Той у одному з наших попередніх обідів кинув мені: «Якщо хочеш зрозуміти Розширення зсередини — є один хлопець, він на цьому собаку з'їв. Михайло, фрілансить, живе на Лівобережній, у нього кімната як домашня студія. Я тобі скину контакт».

Михайло відповів за годину: «Приходь у понеділок з ранку, у мене якраз пусто між клієнтами. Кав'ярні я не люблю — у мене вдома краще. Лівобережна, від метро десять хвилин пішки, я скину локацію».

У понеділок о десятій я вийшов з метро Лівобережна, перейшов через міст пішки, знайшов новий ЖК — з тих, що почали будуватися ще до повномасштабної, потім зупинялись, потім добудовувались. Дванадцятий поверх, квартира з номером сім. Михайло відчинив двері — чоловік років тридцяти семи, у спортивних штанах і простій сірій футболці, з кружкою в руці.

— Заходь. Тільки взуття залиш отам. У мене там кімната, ходімо.

Кімната була у дальньому кутку квартири. Десь метрів дванадцять. Один довгий стіл уздовж стіни, три монітори (два горизонтальних, один вертикальний з кодом), обертове крісло Herman Miller, на стіні — звукоізоляційні панелі сірого кольору. Поряд — два піаніно, одне акустичне, одне сценічне електро. На підвіконні — кактус і годинник з ретро-дизайном.

— Ти на роялі граєш?
— Іноді. Коли тупляк. Сідай, ось друге крісло. Зараз каву зварю.

2

Михайло повернувся з двома горнятками, поставив одне переді мною, сів у своє крісло і повернувся до мене.

— Антон тобі що сказав?
— Що ти на Розширеннях собаку з'їв.
— Не зовсім собаку. Скажімо, добре розумію, чим живу. У дев'ятнадцятому я перейшов повністю на Розширення. До того був звичайний «модифікую типову руками» розробник, як усі. Перейшов і не хочу назад.

— Чому перейшов?
— Бо мене допекло. Я тоді сидів у клієнта, у якого було вісім років доопрацьованої типової. Кожне велике оновлення BAS Бухгалтерії — кілька днів зі мною: день клацання «з нової», «з поточної», «об'єднати» на двох з половиною тисячах об'єктів, потім ще день-два на тестування і виправлення регресій після злиття. Тиждень з усім. Мені стало сумно. Я подумав — невже немає іншого способу.

— Був інший спосіб?
— Був. Розширення. Я тоді вперше прочитав документацію уважно. Зрозумів, що це той механізм, який платформа додала з версії 8.3, щоб саме від цього страждання позбавити. Тільки люди ним не користувалися. Звичка.

— Що ти зробив?
— Запропонував клієнту: давайте перенесемо всі ваші модифікації з типової у розширення. Це буде окремий проект, місяці на два. Натомість наступне оновлення типової вам коштуватиме годину, а не тиждень. Він трохи поскрипів, але погодився. За два місяці я переніс усе. З того дня — ні разу не клацав об'єднання конфігурацій у нього. Кожне оновлення — типова накотилася чисто, розширення увімкнулися окремо.

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

3

— Розкажи технічно. Що це таке.

Михайло повернувся до монітора, відкрив Конфігуратор. У дереві об'єктів — типова конфігурація BAS Бухгалтерії, а у нижній частині — окрема гілка «Розширення конфігурації», у якій було три пункти: «КонтрольПДВ_укр», «БанкІнтеграціяЗПриватом», «ЗвітиДляКерівника».

— Це три розширення цього клієнта. Кожне — окремий пакет коду, який живе поверх типової. Типова — у себе, чиста, від постачальника. Розширення — у себе, мої, окремо. Платформа знає, як їх з'єднати.

— Як саме?
— Кожне розширення може робити три речі.

Перше — додавати свої об'єкти. Я можу створити у розширенні новий довідник, новий документ, новий звіт. Він буде існувати лише при увімкненому розширенні. Якщо розширення вимкнено — об'єкта не існує. Платформа сама його ховає.

Друге — запозичувати об'єкти з типової і додавати у них поля. Я можу взяти типовий документ «РеализацияТоваров», додати у нього свій реквізит «НомерРейсу». Реквізит з'явиться в усіх формах цього документа, у всіх запитах, у звітах. Типова конфігурація при цьому не зміниться. У моєму розширенні буде запис: «у документі РеализацияТоваров я додаю поле НомерРейсу типу Рядок 50». Це декларація, платформа її виконує сама.

Третє — підмінювати модулі. Це найцікавіша частина. Я можу взяти процедуру з модуля типової, наприклад ОбработкаПроведения, і додати свій код перед нею або після неї. Або повністю замінити. У розширенні я пишу:

Він повернув монітор до мене. На екрані був ось такий код:

&Перед("ОбработкаПроведения")
Процедура НомерРейсу_ПередПроведением(Отказ, РежимПроведения)

    // Мій код, який виконається ПЕРЕД штатною ОбработкаПроведения.
    Если ЭтотОбъект.НомерРейсу = "" Тогда
        Сообщить("Не вказано номер рейсу. Документ не проводиться.");
        Отказ = Истина;
        Возврат;
    КонецЕсли;

КонецПроцедуры

— Це аналог "before-hook", — сказав Михайло. — Платформа сама знає: при проведенні документа спочатку викликати мій код, потім штатний. Якщо я виставив Отказ = Истина — штатний не запускається.

— Є й «після»?
— Є. &После(...) — виконується після штатного. І &Вместо(...) — повністю замінює штатний на мій. Це три фундаментальні директиви розширень. І, до речі, усі три — російською, як і вся мова платформи. Українських аналогів не існує: &Після не скомпілюється, &Замість не скомпілюється. Тільки &Перед, &После, &Вместо. Так само як Если ... Тогда, не Якщо ... Тоді. Ти про це говорив з Іриною — те саме мовне питання, тільки тепер у директивах розширень.

4

— Я тебе перебиваю, — сказав я. — Це дуже схоже на одну річ, яку я знаю.

— Що знаєш?
Hooks у WordPress. add_action('before_save'). Або Apex Triggers у Salesforce. Або AOP-анотації у Spring Framework. Це класичний патерн Aspect-Oriented Programming, перенесений у бізнес-світ.

Михайло посміхнувся.

— Так і є. Це AOP, тільки без слова «AOP» у документації 1С. Платформа не любить технологічні терміни з західного інженерного словника. Вона називає це просто — Розширення, директиви, запозичення. Але концептуально — це AOP, плюс структурні модифікації об'єктів, плюс зовнішні підписки на події. Це досить просунутий механізм, який тільки виглядає простим, бо документація написана у пострадянському стилі — інструкція, не маніфест.

— А що з культурою?
— Тут є біда. Розробники, які прийшли у 1С з універу, часто не чули про AOP. Вони не мислять у термінах «before / after / around». Вони мислять у термінах «знайти модуль і змінити рядок номер сорок сьомий». Для таких людей Розширення — щось дивне і незручне. Вони звикли бачити весь код у одному файлі, з усіма вкрапленнями своєї логіки. А Розширення — це розкидання логіки по двох-трьох файлах, по типовій і по своєму. Для звиклого ока — це фрагментація. Для культурно-нового ока — це здорова сепарація відповідальностей.

— Можна сказати, що Розширення — це SOLID для типових?
— Десь так. Single Responsibility — типова відповідає за основну логіку, розширення — за специфічне. Open-Closed — типова закрита для модифікації, відкрита для розширення. Без Розширень ти весь час порушуєш цей принцип. З Розширеннями — нарешті дотримуєшся.

5

— Як це виглядає на практиці? Що змінюється у житті твоїх клієнтів?

Михайло відсунув монітор, повернувся до мене.

— Я скажу прямо. Розширення розв'язують три великі проблеми, які мучили 1С-розробку двадцять років.

Перше — оновлення. Це головне. До розширень: кожне оновлення типової — це злиття конфігурацій з усіма твоїми правками. На клієнті з двома роками модифікацій — це день роботи. На клієнті з вісьмома роками — тиждень. Підприємство не оновлюється, бо це дорого. У результаті — застарілі версії, баги, які давно виправлені у типовій, недоступні нові функції.

З розширеннями: оновлення типової — просто завантажив новий cf-файл і накотив. Розширення живе окремо, нічого не зачіпає. Платформа автоматично перевіряє сумісність розширень з новою типовою. Якщо щось ламається — виводить попередження.

Друге — рідкісний код. До розширень: твої правки змішані з типовою. Хтось через п'ять років дивиться у модуль документа — двісті рядків коду, з них тридцять — твої. Ніхто не розрізнить, які чиї. Археологія.

З розширеннями: твій код — у твоїх файлах. Виключно. Через п'ять років хтось відкриває розширення — і там тільки твоє. Чистенько. Можна знайти, де закопано тіло.

Третє — увімкнути / вимкнути. До розширень: твої правки завжди діють. Хочеш протестувати без них — повертайся до оригінальної типової вручну.

З розширеннями: я можу вимкнути розширення одним кліком. Запустити базу без нього. Перевірити, чи проблема — в типовій, чи в моєму коді. Дебагінг змінився. До розширень у клієнта з повільним проведенням — я не міг швидко зрозуміти, де проблема. З розширеннями — вимкнув своє, проблема залишилась — значить, типова. Зникла — значить, моє. Бінарний пошук.

6

— Що Розширення не вирішують?

Михайло задумався, наче перебираючи у голові своїх клієнтів.

— Багато чого. Це не магічна паличка.

Перше — не всі типи об'єктів запозичуються повноцінно. З документами — нормально. З довідниками — нормально. З регістрами — частково: ти не можеш додати вимір у регістр накопичення типової через розширення (бо це фундаментальна структурна зміна, яка вимагає міграції даних). Не можеш додати рахунок у план рахунків. Не можеш додати реквізит у тимчасову таблицю запиту.

Друге — взаємодія кількох розширень. Якщо у тебе три розширення, які всі хочуть &Перед на одній процедурі — у якому порядку платформа їх запустить? Документація каже: за порядком завантаження. Але цей порядок не завжди прозорий. Бувають збої, коли два розширення конфліктують одне з одним.

Третє — продуктивність. Розширення на ходу транслюються у виконуваний код. Платформа об'єднує модулі типової і модулі розширення. У великих базах з багатьма розширеннями це може дати помітне сповільнення компіляції. У продакшені — невелике, але вимірне.

Четверте — деякі сценарії неможливі. Якщо тобі треба змінити семантику проведення документа на корені — наприклад, ввести новий концепт «попереднє проведення», який не існує у типовій — це не зробити через розширення. Бо це не «додати щось», це «переробити фундамент». Тоді доводиться все одно іти у типову.

— Як часто це?
— У моїй практиці — приблизно п'ять-десять відсотків випадків. Решта — закривається розширеннями. Це не сто відсотків, але це достатньо, щоб переписати робочий процес.

7

— А чому тоді не всі перейшли на розширення? — спитав я. — Якщо це так очевидно?

Михайло посміхнувся, як людина, яка часто думала про це питання.

— Кілька причин.

Перша — звичка. Я тобі вже казав. Розробник, який двадцять років правив типову руками, не хоче змінювати робочий процес. Йому некомфортно дивитися на двох екранах — типова і розширення. Йому простіше «зайти у модуль і дописати рядок».

Друга — короткі гроші. Перенесення зі звичних правок у розширення — це інвестиція, яка окупається не сьогодні. Клієнт каже: «у мене все працює, нащо я тобі заплачу за міграцію коду?». Розробник каже: «ну, добре, не платиш — буду далі лагодити по-старому». Замкнене коло.

Третя — освіта. В курсах про Розширення згадують, але мало хто пояснює культурно, як їх використовувати правильно. Студенти не отримують ментальної моделі AOP, не розуміють, чому «before / after / around» — це сильна абстракція. Виходять з курсу зі знанням синтаксису, а не філософії.

Четверта — недосконалість самого механізму. Я тобі вже сказав — не все можна. Деякі проекти впираються у це і виходять з думкою «розширення — це обмежено, давайте по-старому». На жаль, це запам'ятовується сильніше, ніж сотні випадків, де все вдалося.

— Куди це йде?
— Я думаю, що повільно, але неухильно — у бік чистих типових з розширеннями. Молодші розробники охочіше переходять. Великі франчайзі мігрують клієнтів на розширення. BAS постачає типові з кожним релізом більш «розширенням-дружними». Це природна еволюція, тільки повільна — як усі еволюції у пострадянському ринку.

8

— А тобі особисто, як це змінило роботу?

Михайло допив каву.

— Я став спати краще. Без жартів. До дев'ятнадцятого року в мене на кожне велике оновлення BAS була проста відповідь — два тижні випадання з родинного життя, бо клієнти-«пожежі», бо щось упало після злиття. З двадцятого року — я роблю той самий апдейт за вечір, з пивом у руці. Більшість роботи виконується деклараціями: завантажив нову типову, перевірив сумісність розширень, увімкнув. Робота, яка раніше була ремонтом, стала адмініструванням.

— Тобі стало нудніше?
— Як подивитися. Менш драматично — так. Менше платять за пожежі — теж так. Але я заробляю на іншому. На архітектурі. Клієнти платять за те, що я спочатку правильно спроектую, а не за те, що я потім лагоджу. Це інша економіка. Я перейшов з «вибуху до вибуху» на «постійну системну роботу». Це здоровіше.

— А для індустрії?
— Для індустрії — це підвищення планки. Через десять років ми, сподіваюся, зможемо казати: «Розширення — це не круто, це базове». Тоді не буде самого розрізнення «класична розробка vs Розширення». Буде просто «розробка». А класична залишиться у тих рідкісних випадках, де без неї не вдається.

Він зачинив ноутбук.

— Слухай, я тобі ще скажу одну річ, яку я ніде не публікував. Якщо хочеш — для книги.

— Кажи.

— Розширення — це єдиний механізм у BAS, який реально намагається наблизити платформу до сучасної інженерії. Усе інше — мова, метадані, форми, регістри — це шари дев'яностих, на яких є нова обкладинка. А Розширення — це нова, на сучасних патернах побудована штука, яка живе всередині старого корпусу. Як сучасний двигун у радянському «Москвичі». Не повністю врятує машину, але якщо вмієш користуватися — ти вже не зовсім у дев'яностих.

Я записав цю фразу.

9

Я вийшов з ЖК на Лівобережній, пройшов повз будматеріали ще на одному об'єкті, що добудовувався, і пішов до метро. Над Дніпром був квітневий вітер, листя на тополях ще не повністю розгорнулось.

Я думав про одне.

Усі попередні розділи Частини II і початок Частини III — це історія платформи, яка накопичувала, не очищаючи. Версії, мови, форми, типові — все нашаровувалось. Михайло — перший герой, який показав мені рівень, на якому ця платформа намагалася почати спочатку. Не повна перебудова. Не «нова мова», не «нова метамодель». Маленький, локальний, але стратегічний хід — зробити шар, на якому можна писати по-новому, не торкаючись старого.

Це і є інженерна цінність Розширень. Не у конкретних можливостях. У філософській позиції, яку платформа обрала: «ми не можемо змінити минуле, але ми можемо запропонувати чисту піщану доріжку для майбутнього». Хто на цю доріжку зайшов — отримує переваги.

Михайло — один з тих, хто зайшов. Багато інших — ще ні. Це повільний рух, але він є.

У наступному розділі я повернусь до продуктивності. Не як Юрій — з конкретними анти-патернами і повільними запитами. А як архітектор, який проектує продуктивність на рівні архітектури всього рішення. Десять правил, які можна врахувати до того, як база виросте. Розділ дванадцятий.