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

Розділ 9. Обід на Хрещатику

Частина II · Розділ 9

Обід на Хрещатику

1

Богдана я знайшов через статті. Він вів технічний канал у Telegram про архітектуру BAS — без політики, без флеймів, без хайпу: розбори типових кейсів, пояснення підкапотних механізмів, інколи переклади документації. Аудиторія невелика — півтори тисячі підписників, переважно архітектори, тех-ліди й люди, які хочуть ними стати. Я писав йому ще місяць тому. Він довго мовчав, потім написав: «Гаразд, але тільки за обідом. У мене вікно у середу між зустрічами. Прийдете на Хрещатик о другій?».

У середу о другій я знайшов його у вузькій кав'ярні третього поверху бізнес-центру, схованій від вулиці так, що про неї знають тільки ті, кому її показали. На вікнах — рослини, на столах — світлові плями від низького квітневого сонця, у динаміках — Бетховен на тлі. Богдан сидів біля вікна, із закритим ноутбуком і тарілкою грибного супу перед ним. Сорок п'ять років, лисуватий, у сірій кашеміровій сорочці без жодної емблеми.

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

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

— Ну, з чого? Я зрозумів, що ви хочете від мене розмови про модель даних. Я надішлю вам потім посилання на свої статті, де я це розписую систематично. Але за столом — я можу дати тільки головну тезу. Готові?

— Готовий.

2

1С не є ORM, — сказав він просто. — Не плутайте дві речі: технічний прийом і архітектурний підхід. ORM — це технічний прийом мапування об'єктів на реляційні таблиці. Hibernate, Doctrine, Eloquent — усі вони працюють у парадигмі: «у мене є код з класами, у мене є БД з таблицями, мені треба, щоб одне ↔ інше». 1С робить інше. Вона не мапить. Вона вбудовує бізнес-онтологію у виконуване середовище. Це інший рівень абстракції.

— Що це означає на практиці?
— Це означає, що Hibernate не знає, що таке «регістр накопичення». Для нього регістр — це просто ще одна таблиця, і він її мапить як будь-яку іншу. У 1С — регістр накопичення — це семантичний примітив платформи. Платформа знає, що це таблиця фактів з періодом, що з неї треба будувати агрегати залишків і оборотів, що під час її використання треба ставити блокування при проведенні, що до неї є віртуальні таблиці підсумків. Усе це — не у вашому коді. Усе це — у платформі. Ви просто користуєтесь типом.

— А що ще такого є у платформі?
— Чотирнадцять різних типів. Кожен — окрема онтологічна категорія.

Він почав перераховувати, відсуваючи тарілку убік.

3

Довідники. Нормативно-довідкова інформація. Контрагенти, номенклатура, валюти, склади. Це не просто список — це ієрархічна структура з групами, з підпорядкованими довідниками, з передвизначеними елементами, які платформа сама створює і зберігає при оновленні конфігурації. Hibernate не знає, що таке «передвизначений елемент». Для нього це просто рядок у таблиці. У 1С це — об'єкт, посилання на який можна жорстко прописати у коді, бо платформа гарантує, що він є.

Документи. Події в обліку. Кожен документ — подія у часі, з датою, номером, автором, табличною частиною, проведенням (запис рухів у регістри) і відкочуванням (видалення рухів). Hibernate об'єкти не мають вбудованого життєвого циклу «провів — відкотив». У 1С — це фундаментальний механізм. Документ або проведений, або не проведений. Це не просто прапорець у БД. Це семантика обліку.

Журнали документів. Перегляди по кількох типах документів одразу — щоб бухгалтер бачив у одному списку реалізації, надходження, повернення. Окрема онтологічна сутність, не таблиця, не подання — а семантичний агрегатор.

Перелічення. Фіксований набір значень з гарантією, що ці значення не зміняться без оновлення конфігурації. Так само як enum у Java, тільки на рівні платформи, з можливістю використовувати як параметри методів, у запитах, у формах.

Регістри накопичення. Таблиці фактів. Те, про що ви вже говорили з Юрієм минулого тижня — він вам розповідав. Я повторюся, але деталь: у платформі є дві віртуальні таблиці, які платформа агрегує заздалегідь — Остатки (стан на дату) і Обороты (зміни за період). Це не запити поверх руху. Це окремо підтримувані агрегати, які платформа оновлює сама. Hibernate такого не вміє. Якщо ви хочете швидкі залишки у Hibernate — ви будуєте їх вручну.

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

Регістри бухгалтерії. Спеціалізована форма для подвійного запису. У ній — дебет і кредит окремо, плани рахунків, субконто, валюта, кількість. Це не просто таблиця. Це онтологічна модель бухгалтерії, винесена на рівень платформи. Жоден ORM світу такого не має.

Регістри розрахунку. Для зарплати. Періодичні нарахування з базою, з витісненнями, з періодом дії. Окрема онтологія, побудована під специфіку нарахування заробітної плати з її витісненням, перерахунками і базовими алгоритмами.

Плани рахунків. Кореневі довідники, спеціалізовані під бухгалтерію. З ієрархією, з типом активності, з реквізитами субконто.

Плани видів характеристик. Динамічно розширювані набори атрибутів. Платформа дозволяє користувачу самому додавати «нові поля» до об'єкта, без перекомпіляції. У Hibernate це робиться через серіалізований JSON у колонку. У 1С — це рідний механізм, який платформа сама підтримує і відображає у формах.

Бізнес-процеси і завдання. Графи переходів станів з чергами виконавців. Окрема онтологія для workflow. Не workflow-двигун окремий — а частина платформи.

Підсистеми. Логічне групування об'єктів метаданих за функціональним призначенням. Платформа автоматично будує меню, права, обміни на основі підсистем.

Ролі і права. Декларативне керування доступом на рівні об'єктів, реквізитів і навіть записів у таблицях (Row-Level Security вшита у платформу).

Загальні модулі. Бібліотеки коду. Найближче до того, що ви розумієте під «звичайним кодом» у Hibernate.

Богдан сьорбнув холодний суп.

— Ось ваша онтологія. Чотирнадцять (плюс ще кілька) типів. Кожен — це семантично навантажений примітив. Не таблиця. Не клас. Концепція з предметної області бізнесу.

4

— А що це дає у порівнянні з ORM?

Богдан подумав.

— Швидкість на типовій задачі. Ось приклад. У Hibernate напишіть мені «отримати поточний залишок товару на складі на конкретну дату». Скільки рядків коду?

— Залежить. Я б писав щось через criteria queries, агрегації, віконні функції. Десь рядків п'ятнадцять-двадцять. Плюс міграція на створення табличних агрегатів, якщо хочу швидко.

— У 1С — один виклик. РегистрНакопления.ТоварНаСкладах.Остатки.Получить(Дата, Отбор). Усе. Платформа знає, як, платформа підтримує агрегат, платформа повертає число. Це різниця в порядок — за швидкістю розробки. І це не цукор. Це різниця в моделі думання.

— А що 1С робить ще?
— Журнал реєстрації — записує кожну зміну будь-якого об'єкта без вашого коду. Підписки на події — слухачі можуть реагувати на створення/зміну/видалення об'єктів. Обміни даними — вбудована синхронізація між базами через плани обмінів. Транзакційний контроль на рівні документів. Контроль посилань — об'єкт не можна видалити, поки на нього посилається інший. Контроль цілісності — платформа сама перевіряє типи у формах і у запитах.

— Hibernate цього не робить?
— Робить — але через окремі бібліотеки, кожна — окремий проект, з окремими залежностями, окремими версіями. У 1С — усе в коробці, узгоджене між собою. Ціна — несвобода. Вийти за рамки моделі неможливо.

5

— А що 1С не робить добре?

Богдан усміхнувся.

— Багато чого. По-перше, успадкування. У ORM ти можеш мати клас Person, від нього успадкувати Employee, Customer, Supplier. У класах метаданих 1С спадкування немає. Довідник Контрагенти не успадковується від чогось. Усі довідники — окремі рівноправні сутності. Є родитель (ієрархія груп у тому самому довіднику) і владелец (підпорядкування одного довідника іншому), але це посилання, не спадкування реквізитів. Якщо тобі треба «спільні поля для контрагента і співробітника» — копіюй або винось у регістр відомостей.

— По-друге, поліморфізм. У ORM ти можеш мати інтерфейс Auditable і будь-який клас, який його реалізує. У 1С такого немає. У платформи є обмежений механізм через «загальні реквізити», які додаються до груп об'єктів — але це не справжній поліморфізм. Це shared columns. Дрібна поступка.

— По-третє, гнучкі many-to-many. У ORM ти створюєш проміжну таблицю з reverse-mapping. У 1С ти робиш регістр відомостей — таблицю комбінацій вимірів. Якщо без періоду — це фактично проміжна таблиця, точний аналог @ManyToMany. Якщо з періодом — це M2M з історією станів, що сильніше за чистий @ManyToMany. Альтернатива — таблична частина, але вона завжди прив'язана до батьківського об'єкта, не самостійна сутність. Чого у 1С нема — це двостороннього симетричного доступу як у @ManyToMany: ти завжди працюєш через вимірі регістру, не через колекції в обох об'єктах.

— По-четверте, функціональні патерни. У Scala чи у Kotlin ти пишеш monads, comprehensions, lazy collections. У 1С ні цього, ні приблизного. Мова — імперативна, без функціональних патернів. Це обмеження, але це і свобода — менше способів вистрелити собі в ногу.

— По-п'яте, типізована полімовна композиція. У ORM у тебе є generics, type parameters, бавишся з типами. У 1С типізація — динамічна, перевірки — у runtime, generics немає. Якщо ти любиш List<UserDTO<Role>> — ти будеш страждати у 1С.

Він зробив паузу.

— Це інша мова в широкому сенсі. Не тільки синтаксично, а концептуально. Мова конкретної предметної області — бізнес-обліку. Усе, що поза ним, — або робиться через біль, або не існує взагалі.

6

— Філософське питання, — сказав я. — Що це? Чим ця штука є?

Богдан довго мовчав. Потім подивився мені прямо в очі.

— Це доменно-специфічний фреймворк, у якого предметна область — бухгалтерський і управлінський облік. У спеціалізованій літературі такі речі називають domain-specific framework або domain-driven framework. Не плутайте з DSL — це не мова, це фреймворк. У ньому є мова, але це частина фреймворку, не самостійна цінність.

— Бо 1С не виросла з універсальних інструментів. Вона виросла з обліку. У дев'яностих її проектували бухгалтери — не з нуля, але дуже близько. Ті, хто проектував, знали кореспонденцію рахунків, знали структуру балансу, знали, як закривається період. Вони закодували все це у платформу. Той факт, що з 2003-го з'явилась мова запитів, з 2009-го з'явились керовані форми, з 2013-го з'явились мобільні — це надбудови, що пристосовують ту саму онтологію до нових технологічних умов. Сама онтологія — від 1990-х. Вона має ту глибину, яку ні Hibernate, ні Salesforce, ні Odoo не мають у цьому конкретному домені.

— А в інших доменах?
— Поза цим — нуль. 1С не є хорошим фреймворком для веб-додатку. Не є хорошим для real-time системи. Не є хорошим для AI-pipelines. Це фреймворк бухгалтерії. Він гнеться до сусідніх задач — управлінський облік, логістика, виробничий облік — але всі вони — варіації на тему обліку. Як тільки виходиш за межі — платформа стає тягарем.

7

— А мова запитів? Це чистий SQL?
— Ні, — Богдан хитнув головою. — Це власний діалект, побудований над метамоделлю. Зовні схожий на SQL: ВЫБРАТЬ ... ИЗ ... ГДЕ ... СГРУППИРОВАТЬ ПО .... Але під капотом — це не SQL. Платформа транслює запит у SQL конкретної DBMS — SQL Server, PostgreSQL, Oracle, DB2. Розробник пише один раз — платформа адаптує під кожен діалект сама.

— А це працює нормально?
— Працює дивно. По-перше, немає JOIN у вашому коді. Замість JOIN ви пишете точкою: Реализация.Контрагент.Наименование. Платформа сама будує LEFT JOIN на довідник Контрагенти. Це елегантно, але приховує план виконання — і саме звідси беруться повільні запити, про які вам казав Юрій.

— По-друге, віртуальні таблиці. Я вже казав про них. У запитах 1С ти можеш писати ИЗ РегистрНакопления.ТоварНаСкладах.Остатки(&Дата) КАК Залишки — і платформа сама бере агрегат на цю дату, без сканування рухів. У чистому SQL такого механізму немає. Тут — є.

— По-третє, тимчасові таблиці у запитах. Ти можеш у запиті 1С створити іменовану тимчасову таблицю (ПОМЕСТИТЬ) і використати її далі. Платформа сама вирішить, як це реалізувати — як CTE, як #temp, як inline subquery — залежно від DBMS.

— Це SQL з покращеннями для обліку. Дуже сильний інструмент. Не такий потужний, як справжній SQL (немає віконних функцій, обмежено MERGE, немає LATERAL), але сфокусований саме під онтологію.

8

— Підсумок, — сказав я. — Як ти скажеш молодому розробнику, який питає: «що це таке»?

Богдан зробив паузу.

— Я б сказав: 1С — це не Java, це не PHP, це не Salesforce, це не Odoo. Це окрема категорія. Domain-specific framework для пострадянського бухгалтерського обліку, який виріс у платформу для пострадянського бізнес-обліку загалом, і яка зараз намагається бути платформою бізнес-додатків у широкому сенсі — з різним успіхом.

— Ваше завдання як розробника — зрозуміти онтологію. Не вивчити синтаксис — це найлегше. А зрозуміти як платформа думає про бізнес. Що таке проводка, що таке регістр, що таке період, що таке зрізи. Це не технологія — це філософія обліку, закодована у платформі. Хто це засвоїв — пише на 1С швидко й елегантно. Хто не засвоїв — бореться з платформою все життя.

— А коли ви розумієте, що ви засвоїли?
— Коли перестаєте писати запит у циклі.

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

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

— Якщо у книзі потрібен ще раз — пишіть. Я живу у Києві, мене легко знайти.

9

На Хрещатику грав перший гітарист сезону — старший чоловік біля магазину «Подоляночка», виводив вальси Бетховена нерівно, але з душею. Я йшов до метро, і у голові оберталась одна фраза:

«Зрозумій, як платформа думає про бізнес».

Це формула, яка пояснює мало не все, що я почув за всі попередні розділи. Антон, який двадцять років всередині цієї моделі — він не запам'ятав мову; він засвоїв онтологію. Юрій, який лагодить повільні запити — він знає, як платформа транслює крапку у JOIN. Олександр, який тримає чотирьох клієнтів — він розуміє, що одна онтологія працює крізь чотири рантайми. Володимир Васильович, у якого DOS-машина з шістою версією — він пам'ятає, як ця онтологія народжувалася і нашаровувалася.

Усі вони — частини однієї знаннєвої спільноти. Спільноти, у якій вхід дешевий (один курс — і ти усередині), але глибина — на десятиліття. Спільноти з власною мовою, власною онтологією, власною економікою.

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

Частина III, яка починається з наступного розділу, — про практику. Як писати на цій платформі ефективно, як уникати найпоширеніших помилок, як працювати з типовими конфігураціями, як інтегрувати Git у процес, як тестувати — у світі, у якому ніхто не тестує. Це найприкладніша частина книги. Її можна читати окремо, без попередніх — якщо ви розробник і хочете відразу до справи.

Наступний розділ — про типові конфігурації. Про екосистему продуктів, які тримають весь український бізнес. Розділ десятий.