Перенесення застосунку 1С
1. Що це
Перенесення legacy — не задача «переклади синтаксис». Це задача відновити й зафіксувати, що система насправді має робити, відокремивши це від того, як вона випадково робила це двадцять років. Тому посередині стоїть специфікація, а не транслятор.
Чотири артефакти, і межі між ними жорсткі:
| що це | хто править | |
|---|---|---|
| вивантаження | знімок конфігурації 1С (XML + модулі) | ніхто, закріплене |
| дамп | as-built: що в застосунку є, у читабельному вигляді | ніхто, перезбирається однією командою |
| спека | опис застосунку: що він робить, з чого складається і чому саме так | людина і модель |
| застосунок | цільова платформа | після генерації живе своїм життям |
Три межі, які тримають конструкцію:
- інструмент розбору не знає про спеку — він проєктує 1С у читабельний вигляд, і все;
- спека не знає цільової платформи;
- дамп — риштування витягування, а не вхід генерації. Він показує аналітикові й моделі, куди дивитися, поки спека пишеться. Коли спеку написано, дамп не читає ніхто: ні генерація, ні той, хто вестиме застосунок через рік.
Спека самодостатня, і це перевіряється фізично: скопіювати теку в порожній каталог, віддати моделі, яка вихідної системи не бачила, і попросити застосунок. Про що вона спитає — того в спеці немає. Ні дампу, ні вивантаження, ні інструментів, ні авторів поруч при цьому немає.
Звідси головне для роботи: склад сутностей і подій має бути у спеці цілком. Не «склад полів
лежить у дампі» — генерація дампу не бачить. Що при цьому заборонено — references/writing.md.
Питання — не задача
«Що це таке», «що воно вміє», «з чого почати» — відповісти й нічого не створювати, наприкінці спитати: «Починаємо роботу?». Названа дія (перенеси, розбери, додай, згенеруй) — задача, далі за §3 і §4.
Розмова з людиною
Спілкуватися українською, якщо людина явно не попросить іншу мову. Мова спеки й словника термінів — окреме рішення (§3.3), розмову воно не змінює.
Людині йде зміст її застосунку, словами її справи. Устрій роботи — скрипти, файли, дамп, лік об'єктів — лише якщо вона спитала.
- по ходу — рядок, коли зрозумів щось про застосунок або перейшов до нового кроку:
«надходження посилається на рахунок постачальника — схоже, один ланцюжок закупівлі», а не
«запускаю
section.py». Розуміння, що виявилося хибним, так і виправити; - наприкінці — доповідь у чотири частини (
references/fanout.md); - показувати, а не відсилати — що потребує відповіді, іде в чат; довідкове — посиланням на файл і суттю у двох-трьох реченнях. Питання, залишене у файлі, відповіді не отримує;
- питання — про рішення чи намір, а не про те, як часто щось буває в даних
(
references/writing.md); - підтверджене записується одразу, у той самий хід: зміст — у
spec/, робота — у нотатки. Згода людини на пропозицію і є моментом запису; рішення, що живе лише в листуванні, губиться під час стискання контексту й перепитується наступною сесією.
Стан проєкту
Живе в проєкті перенесення, а не в скілі. Нотатки про роботу — дошку, чергу до інструменту, відкладене — модель веде де зручно, окремою текою. Правил два:
CLAUDE.mdпроєкту називає адреси — вивантаження, дамп, нотатки, спека: сам завантажується лише він, і без адрес наступна сесія почне спочатку;- у спеці немає нічого про роботу. Її читають як опис застосунку; дошка чи черга поруч із нею не відрізняються від змісту. Виняток один і названий — тека міграції: вона обслуговує перехід, позначена такою в своєму README і викидається разом із вимкненою старою системою.
Розвилка на початку роботи, за ознаками, які можна перевірити:
- вивантаження немає → §2.2, далі нічого;
- вивантаження є, дампу немає → §3.1;
- дамп є, спільних рішень немає → §3.3, і це обов'язковий крок, а не рекомендація;
- усе є → задача, диспетчер наприкінці файла.
2. Передумови
Перевірити до першої команди й сказати людині, чого бракує. Перевірка займає секунди; робота, розпочата без неї, упреться в стіну посеред розбору.
2.1 Інструмент розбору
Вивантаження читає confdump — консольний інструмент .NET, ставиться маніфестом у корені
перенесення:
dotnet new tool-manifest
dotnet tool install A2v10.Confdump
dotnet confdump --version
Не --global: версія інструмента визначає склад дампа, а глобальна установка її ніде не
записує — і голе confdump узялося б із PATH, тобто з іншої, можливо старішої, копії. Маніфест
лежить поруч із перенесенням, версія в ньому закріплена.
Немає .NET потрібної версії — сказати про це прямо й зупинитися: ставити рантайм за людину не треба.
Напрям в інструмента один: вивантаження → дамп, завжди повна перезбірка. Режиму «дописати в
готовий дамп» немає, і дамп руками не правиться ніколи. Команди й форма виходу →
references/confdump.md.
2.2 Вивантаження конфігурації
Це робить людина у своїй 1С, і замінити її тут нічим.
Створити теки проєкту заздалегідь, потім сказати буквально:
Відкрий свою базу в конфігураторі: Конфігурація → Вивантажити конфігурацію у файли… (у російському інтерфейсі — Конфигурация → Выгрузить конфигурацию в файлы…), обери порожню теку
source/у цьому проєкті. Це кілька хвилин і сотні мегабайтів — так і має бути. Скажи, коли закінчиш.
Нічого не вигадувати понад цей шлях: інша версія платформи, інша назва пункту — спитати, а не вгадувати. Вивантаження після цього закріплене: воно знімок, і перезнімати його посеред роботи означає міняти ґрунт під уже написаним.
2.3 Місце на диску
Вивантаження типової конфігурації — сотні мегабайтів, дамп — десятки. Обидві теки похідні для версіонування: вивантаження чуже й пропрієтарне, дамп перезбирається однією командою. У репозиторій не кладуться, але лежать у робочому корені — щоб шляхи були відносними.
2.4 Цільовий скіл — якщо конвертувати одразу
Саме перенесення змісту йде без нього: спека — самостійний артефакт, і витягування від цільової
платформи не залежить зовсім. Але якщо людина хоче одразу отримати робочий застосунок,
потрібен скіл цільової платформи — для A2v10 це a2v10meta (режим metaendpoint).
Перевіряти його — перед генерацією, а не на початку: платформу людина називає сама, коли до неї дійде; спека пишеться без знання цілі. Немає скіла — не привід зупиняти роботу: доводимо до спеки й кажемо, чого бракує для останнього кроку.
3. Витягування змісту
3.1 Перший прогін і доповідь
Прогнати інструмент і розповісти людськими словами, що це за система: чим займається, що в ній є великого, що помітно важке. Не список видів із числами — це перше враження, і воно має читатися.
Тут же назвати вголос, чого інструмент поки не читає: мовчання не відрізнити від «цього там немає».
3.2 Що беремо в роботу
Людина називає розділи обліку словами своєї справи: «перенеси закупівлі», «усе, крім зарплати». Розділ обліку існує сам — закупівлі, продажі, банк і каса. Ділянка обліку без розділів не існує — розрахунки з контрагентами, ПДВ, закриття періоду — і приходить із розділом у тій частині, якою той користується. Підсистема 1С — доказ складу розділу, а не розділ.
Розділ — цикл: список його подій закінчується, коли закрито відкрите ним (привезли — заплатили — закрили борг). Складається він із подій, а не з документів, і одна подія входить у кілька розділів: оплата постачальнику — і закупівлі, і банк.
Склад розділу збирає агент: за підсистемами й за шляхами повз їхній склад. Людині — список подій
розділу її словами, на згоду. Файл периметра, вхід інструменту, пише агент.
→ references/perimeter.md.
3.3 Спільна мова — до розбору поштучно
Поки цього немає, розбір об'єктів не починається. Десять заходів без спільного словника дадуть десять онтологій, і потім це не зібрати.
Чотири рішення, у кожного — пропозиція, порахована за цією конфігурацією, і типовий варіант, щоб можна було пройти згодою:
- мова і словник термінів — мовою застосунку, не мовою платформи;
- що вважається однією господарською подією — за розділом обліку: кандидатів дає агент, список подій розділу підтверджує людина (§3.2); жодна механічна ознака сама по собі поділу не дає;
- модель обліку — форма бухгалтерського запису;
- шаблон регістру — збережені підсумки, зрізи й перепроведення не переносяться: це кеш і його інвалідація, а при розрахунку запитом механізм зникає цілком.
Прийняте записується рішенням власника з підставою з пропозиції.
→ references/common-layer.md.
3.4 Розбір: аспекти й глибина
Одиниць змісту чотири, і в кожної свій файл: господарська подія, сутність, слід (те, що події накопичують і по чому потім рахують) і ділянка обліку. Екран, бланк і спільне для подій одного документа — у файлі документа. Одиниця обліку роботи — пара «об'єкт + аспект» (дошка). Не плутати: перше судиться, друге рахується.
Слід отримує власний файл із власним ключем і списком тих, хто в нього пише. Поки список неповний, слід не описано: залишок складається з усіх писачів, а не з одного.
Аспектів чотири: поля, поведінка, форми, бланк. Статуси: не розпочато, зроблено, не потрібно (у переліку немає форм і бланка) і не встановлено — пробували, уперлися в зміст.
Позначка виводиться з артефакту, а не з самовідчуття: розділ у файлі є й називає джерела — зроблено. Інакше дошка стане звітом про гарний настрій.
Глибина береться з ролі об'єкта й тому дається даром:
- документи подій розділу і регістри їхніх рухів — усі аспекти, які в об'єкта є; у чорного ходу регістри не рахуються — він пише куди завгодно;
- ділянки — те, чим розділ користується;
- довідники й переліки, на які вони посилаються, — лише поля;
- далі, і документи без подій розділу, — колонка без таблиці, поки не дійде свій розділ.
Заходи йдуть паралельно, по об'єкту на захід. Питань по ходу не ставити: не встановив — напиши
«не встановлено» і що саме; не вистачило дампу — рядок у чергу й продовжуй. Питання з готових
файлів приносяться людині в чат. → references/analysis.md, references/writing.md.
3.5 Числа рахуємо, а не пам'ятаємо
Жодне твердження про цю конфігурацію не береться з пам'яті й з чужого досвіду: скрипти лежать у
scripts/, відповідь рахується тут і зараз. Вимір, що не дав відповіді, оформлюється як
«матеріал для рішення», а не як рішення. → references/measure.md.
3.6 Нестача — черга, а не зупинка
Список того, що інструмент читає з вивантаження, неповний завжди, і це його нормальний стан. Уперлися — рядок у чергу, накопичилося — дописали читання, перезібрали дамп цілком, заходи продовжилися з більшим знанням.
4. Генерація застосунку
Спека — не кінець шляху. За нею збирається робочий застосунок, і це окремий крок із власним реєстром цілей.
4.1 Реєстр цілей
| ціль | режим | чим робиться | передумова |
|---|---|---|---|
| A2v10 | metaendpoint | скіл a2v10meta |
скіл встановлено (§2.4) |
Список відкритий. Додавання цілі — це один файл у references/targets/ і рядок тут. Якщо
заради нової цілі довелося чіпати §3, значить витягування змісту дізналося про ціль і межу
зламано.
4.2 Що ціль отримує і чого не має права вимагати
Файл цілі — контракт, а не посібник генератора: вхід у генерації один — спека; який діалект платформи приходить входом (службові імена, зарезервовані слова); чого ціль вимагати не має права. Сам генератор живе у своєму скілі.
Дамп на цьому кроці не відкривається. Потяг до нього — ознака того, що у спеці чогось немає: лагодиться спека, а не правило.
Ціль — детектор нестачі, а не замовник формату. «Генерація зупинилася, бо спека не сказала, що відбувається в такому-то випадку» — знахідка, вона платформонейтральна й іде в правила. «Генераторові було б зручніше в іншому порядку полів» — витік межі.
4.3 Гейт — рахується, а не оцінюється
Три лічильники, усі за структурою, жоден — за впевненістю моделі:
- імена — нерозв'язане ім'я в об'єкта чи в його сусідів, вимушене зіткнення імен усередині таблиці, претензія на службове слово платформи;
- повнота — кожен живий ключ із таблиці відповідності згадано у спеці або занесено до таблиці
виключеного (обидві — у теці міграції,
references/writing.md). Незгаданий ключ — діра; - замкненість за посиланнями — кожна сутність, на яку спека посилається, описана. Властивість «усе або нічого»: довідник не заведеться без того, на що посилається. Тому мінімальний шматок, що генерується, — не список об'єктів, а їхнє замикання за посиланнями, і його розмір рахується до того, як планувати захід.
Зміст блокує лише там, де він не розв'язаний. Питання, відповідь на яке залежить від цільової платформи, не питання спеки: вона зобов'язана нести, чим варіанти відрізняються, а не на що вони перетворюються.
Пропорція оманлива. Склад і правила введення виводяться з оголошення майже механічно, і тексту з них багато — файл виглядає написаним. Те, що робить застосунок обліковим, — план рахунків і склад рухів — з оголошення не виводиться зовсім. Файл, у якому є перше й немає другого, дає застосунок, куди можна вводити і який нічого не рахує. Міряти готовність обсягом тексту не можна.
4.4 Застосунок росте додаванням
Кожен розібраний розділ — нові ендпоінти в тому самому застосунку, а не перезбірка. Згенероване далі живе як звичайний код своєї платформи.
Генерувати можна раніше, ніж розібрано все: є поля — є таблиця і список, форми уточнюють екран, поведінка додає правила. Людина бачить свій застосунок у першу годину.
4.5 Приймання
Правильність перенесення встановлюється звіркою прогонів обох систем на реальних даних, а не читанням тексту. Заради цього рядки цілі зберігають зворотне посилання на запис джерела: звірка можлива рівно доти, доки відповідність не втрачено.
Диспетчер
| задача | куди |
|---|---|
| що це, з чого почати | §1, references/intro.md |
| поставити інструмент розбору, команди | references/confdump.md |
| що лежить у дампі | references/dump-layout.md |
| що беремо в роботу: розділи й ділянки обліку | references/perimeter.md |
| спільні рішення проєкту | references/common-layer.md |
| як організовано роботу, дошка аспектів | references/fanout.md |
| розібрати об'єкт | references/analysis.md, references/kinds.md |
| написати файл спеки | references/writing.md |
| імена в цільовій платформі | references/names.md |
| порахувати за конфігурацією | references/measure.md, scripts/ |
| згенерувати застосунок | references/targets/a2v10.md |
| як це виглядає на папері | examples/ — подія, сутність, слід, периметр, дошка, стан проєкту |
Де скіл закінчується
Працювати можна за всім, що написано вище; тут названо місця, де правил немає, — щоб це з'ясувалося до заходу, а не посеред нього.
- роди об'єктів понад пройдені — звіти, обробки, регістри накопичення й бухгалтерії як об'єкти
розбору. Рід поза списком розбирається родонейтральною процедурою, і це пишеться у файлі, а не
замовчується (
references/kinds.md, останній розділ); - зіткнення імен усередині таблиці інструмент не рахує. Решту гейта імен він рахує, це —
перевіряє модель, перед передачею на генерацію (
references/names.md); - деталі режиму metaendpoint живуть у скілі цілі. Потрібне цілі щось поза контрактом —
спочатку перевірити, знахідка це чи витік межі (
references/targets/a2v10.md).