Перейти до основного вмісту
megapromotingПоговорімо

Експертиза · Програмне забезпечення на замовлення

Система, побудована під те, як працює ваша організація, а не під загальний випадок.

Ми будуємо системи з нуля, коли жоден продукт на ринку не підходить: платформи з кількома застосунками та спільною базою даних, конектори до систем без API, конвеєри, що читають документи й грошові рухи, і програми, результатом яких є не екран, а виробниче досьє. Наприкінці ми передаємо репозиторій, документ введення в експлуатацію та доступи.

Вже збудованоAm ales patru sisteme proprii din discipline diferite, tocmai ca să nu arate ca patru variante ale aceluiași site, și am rulat testele fiecăruia azi. Un monorepo cu 3 aplicații și 12 pachete, 486 de fișiere TypeScript și 68 de fișiere de test, 151 de comituri, arbore de lucru curat. Un sistem de interogare a două portaluri B2B fără API public: 38 de teste trecute în 0,52 s, pe răspunsuri reale salvate ca fixturi. O conductă care citește notificări bancare din e-mail și PDF și le scrie în Postgres cu deduplicare prin amprentă. Și un generator de documentație de inginerie, în Python, cu 44 de teste trecute în 0,50 s. Cifrele sunt din rulările mele de pe 6 septembrie 2026, nu din README-uri.

«На замовлення» означає, що систему пишуть під те, як люди вже працюють, а не навпаки. Є вартість, яку чесно сказати наперед: хтось має її підтримувати, і цим хтось є ми або ваша команда. Тому перше питання, яке ми вам ставимо, не в тому, що ви хочете побудувати, а в тому, чи є продукт, який уже робить 80% роботи. Якщо є, ми так і скажемо, навіть якщо це означає, що роботу отримає не ми. Те, що лишається після цього питання — частина, яку не купують — це саме те, що ми добре будуємо.

Масштабніше це видно з чотирьох різних систем, ніж із переліку технологій. Перша — платформа для закладу сценічних мистецтв: монорепозиторій із трьома застосунками (публічний сайт, адміністративний кабінет, API) та дванадцятьма спільними пакетами — квитки, комерція, контент, повідомлення, повернення, безпека. Друга на запит опитує B2B-портали туроператорів, які не публікують жодного API: програмна автентифікація, повернення до логіну, коли сесія спливає, і аналізатор, протестований на реальних відповідях, захоплених у файли. Третя читає банківські повідомлення з e-mail і PDF-виписки та розкладає їх у Postgres. Четверта не має екрана взагалі: це програма, яка генерує модель, перелік матеріалів і креслення промислової машини.

Що утримує таку систему на ногах, так це не стек, а правила, записані до першого екрана. У платформі для установи видовищ контракт на впровадження фіксує в тексті речі, які інакше обговорюються на кожній нараді: гроші тримаються в цілих дрібних одиницях разом із валютою; доступність місця визначається лише стійким резервуванням у базі даних, ніколи не кешем; критичні замовлення мають ключі ідемпотентності; шляхи P0 і P1 fail-closed, а не fail-open; дані картки ніколи не зберігаються. Ці правила записують на початку, бо, записані наприкінці, вони означали б переписування системи.

Наприкінці передають три речі, а не одну: репозиторій з усією його історією, документ, що описує, як запускати на порожньому сервері, і доступи. У нашому каталозі проєктів є 150 git-репозиторіїв, 103 файли README і 19 документів з впровадження або передання — пораховано сьогодні, а не оцінено. Правило власності ми записуємо в контракт до старту, і воно просте: код, написаний спеціально для вас, належить вам, сторонні бібліотеки залишаються під своєю ліцензією, а наші повторно використовувані компоненти та наші продукти ліцензуються, а не передаються. Якщо частину роботи краще розв’язати за допомогою нашого продукту, ми прямо так і кажемо, щоб ви від початку знали, що купуєте і що отримуєте.

Що входить

Робота, за складовими

Ми записуємо правила домену до першого екрана

Контракт на впровадження в тексті, який фіксує словник і інваріанти: що означає зарезервоване місце, що означає отриманий платіж, що переходить у fail-closed, коли сервіс не відповідає. У платформі для установи видовищ правила є явними — гроші в цілих дрібних одиницях плюс валюта, доступність лише зі стійких резервувань у базі даних, ключі ідемпотентності на критичних замовленнях, кеш ніколи не є джерелом істини для запасу, дані картки ніколи не зберігаються. Це правила, які перевіряються в коді, а не принципи.

Будуємо ядро на тестах, що запускаються без живої системи

Реальні відповіді зовнішніх систем зберігаються як фікстури, і аналізатор тестується на них, а не на порталі, який може бути недоступним саме в той день, коли ви працюєте. У системі запитів до порталів авіарейсів набір тестів виконується за 0,52 секунди і проходить повністю; тести, які справді торкаються порталів, позначаються окремо і вимагаються явно. Таке саме розділення є в усіх чотирьох системах: те, що можна перевірити на столі, перевіряється на столі.

Передаємо репозиторій, запуск і доступи

Не zip-файл. Репозиторій з історією комітів, документ, що описує, як підняти систему на чистій машині — база даних, змінні середовища, системний сервіс, вебсервер спереду — і доступи, які роблять її вашою. У нашому каталозі проєктів сьогодні є 150 git-репозиторіїв, 103 README і 19 документів типу DEPLOY або HANDOVER; такий спосіб передання — це звичка, а не виняток.

Коли в іншої системи немає API, ми кажемо, який ризик ви берете

B2B-портали, які ми опитуємо, не публікують програмний інтерфейс, тож автентифікація виконується як у користувача, з cookie сесії та ключем підключення, і автоматично відновлюється після закінчення строку дії. Ризик записаний у README проєкту, а не виявлений пізніше: програмна автентифікація — це сіра зона щодо умов використання порталу, а для інтенсивного виробничого навантаження правильне рішення — попросити в оператора його офіційний API. Клієнт має право дізнатися це до підписання, а не після.

Документи потрапляють лише один раз, навіть якщо ми читаємо їх десять разів

Кожна транзакція, витягнута з банківського повідомлення або з PDF-виписки, отримує зовнішній ідентифікатор, обчислений як відбиток SHA-256 над її полями, а вставка в Postgres виконується з `ON CONFLICT (external_id) DO NOTHING`. Практичний наслідок: поштову скриньку можна перечитувати скільки завгодно разів, а баланс не дублюється. Без цього правила будь-який конвеєр інгестії починає породжувати дублікати, тобто проблему обліку.

Класифікація за моделлю виконується за допомогою інструментів, а не вільним текстом

Модель не пише речення, яке потім вгадуємо ми: вона отримує сім інструментів — платіж від клієнта, зарплата, податок, платіж кредиторові, операційні витрати, невідомо — і має вибрати один, зі ступенем упевненості від 0 до 1. Для приблизного зіставлення назв контрагентів є окремий резерв, на основі векторної подібності. «Невідомо» — це легітимний вихід, із причиною, а не прихована помилка.

Іноді результат — не екран, а папка

Власна система на Python генерує тривимірну модель промислової машини, перелік матеріалів зі статусом звільнення по кожній позиції, план перевірки, схему кабелів і PDF-креслення — з однієї команди, щоб жодна частина пакета не відставала від моделі. У ній 44 тести, які проходять за пів секунди і перевіряють інженерні правила, а не лише код: що активний об’єм точно один кубічний метр, що жодна позиція в переліку матеріалів не лишається без рядка перевірки, що машина ніколи не екструдує в стані спокою.

Безперервне вимірювання — це інша дисципліна, ніж запит за потреби

Власна система одночасно захоплює кілька радіостанцій за допомогою `ffmpeg`, локально транскрибує за допомогою моделі з відкритим кодом, потім шукає рекламу з прозорим балом за групами сигналів українською та російською мовами, з налаштовуваним порогом, і групує ту саму рекламу, що виходить на різних станціях, за аудіовідбитком типу chromaprint — бо транскрипції розходяться, а звук ідентичний. Має 81 тест, які проходять за 1,14 секунди. Система, що працює без нагляду, потребує лічильників покриття, повторних спроб з орендою завдань і автотесту, інакше мовчить, коли ламається.

Ми також говоримо, чого не будуємо

Ми не будуємо з нуля те, що вирішується наявним продуктом, нашим або чужим, лише тому, що робота була б більшою. Ми не беремо на себе системи, які не можемо запускати локально, з тестовими даними, до кінця першого етапу. І ми не запускаємо систему, що залежить від зовнішнього постачальника, перш ніж перевіримо, який у того постачальника є публічний порт — ця перевірка перша, а не остання.

Як це виглядає

Шлях, крок за кроком.

01

Визначаємо сферу та пишемо правила

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

02

Будуємо ядро, разом із його тестами, до екранів

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

03

Накладаємо інтерфейс та інтеграції поверх ядра

Адміністративний кабінет, публічні екрани, точки входу для інших систем. Тут підключаються зовнішні постачальники, кожен зі своїм адаптером і варіантом симуляції, щоб систему можна було запускати повністю без реальних облікових записів. Ми також передаємо локальний режим запуску, з базою даних і сервісами, піднятими з контейнерів.

04

Запускаємо та передаємо

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

IntrareVerificareDeciziePublicareNimic nu trece mai departe neverificat.ORDINEA E ARGUMENTUL
Trei pași și ordinea lor, care e jumătate din lucrare. Întâi regulile domeniului scrise în text — ce înseamnă un loc rezervat, cum se țin banii, ce cade închis când un serviciu tace. Apoi nucleul cu testele lui, care rulează pe răspunsuri reale salvate ca fixturi, fără sistemele vii. La final punerea în funcțiune și predarea: depozit, documentul pentru o mașină goală, accese. Săgeata înapoi de la pasul trei la pasul unu e reală: ce se descoperă la punerea în funcțiune schimbă regulile, nu se ascunde sub ele.

Дані

Чого торкаємося, де воно лежить і скільки лишається

Запитання, які ставить кожен, у кого є відповідальний за захист даних, — поставлені тут раніше, ніж їх поставить він.

Де працює та хто тримає ключ
Система працює на інфраструктурі, письмово узгодженій на початку: ваш сервер, сервер, яким керуємо ми, або спільно обраний хостинг-постачальник. Чотири системи вище працюють по-різному між собою — одна як системна служба за вебсервером, одна з контейнерів, одна як запланований процес на локальній машині, одна лише за командою, на робочій станції. Вибір робиться з обмежень даних, а не зі звички.
Облікові дані не лежать у коді і, де можливо, навіть не на диску
Паролі та ключі читаються з змінних середовища, а файл, що їх містить, обмежується поточним користувачем. У конекторі до зовнішньої системи токен сесії зберігається лише в пам’яті й відновлюється після завершення строку дії або після першої відмови — пароль і токен не записуються в жоден файл. Правило перевіряється під час ревізії: ключ, що потрапив у репозиторій, — це інцидент, а не дрібна помилка.
Дані, що надходять із документів
Коли система читає електронні листи або PDF, вона торкається реальних бізнес-даних: сум, календарних дат, назв контрагентів, номерів рахунків. Вони зберігаються в базі даних бенефіціара, з власним ідентифікатором, який не може повторюватися, для кожного запису, і можуть бути відтворені з джерела. Те, що передається зовнішній моделі, якщо така використовується, — це опис транзакції, а не весь документ і не вкладення.
Що зберігається і як довго
Термін зберігання встановлюється для кожного типу даних окремо, а не загально, і прописується до введення в експлуатацію: бізнес-записи — за юридичними зобов’язаннями бенефіціара, технічні журнали — на коротке вікно, проміжні файли — аудіозаписи, завантажені вкладення — з автоматичним очищенням. Система, яка не має політики видалення, через шість місяців стає більшим ризиком, ніж проблема, яку вона вирішувала.
Що залишається у нас після передання
Після передання наш доступ до ваших систем існує лише якщо є договір на технічне обслуговування, який цього вимагає, і відкликається, коли він завершується. Робочі копії на наших робочих станціях видаляються на вимогу. Що ми зберігаємо за будь-яких умов — це загальні компоненти, які ми написали і які не містять ваших даних, — і про них ми заявляємо від самого початку, щоб наприкінці не було сюрпризів.

Випадок

Система запитів для двох порталів, які не мають жодного API

Ситуація

Туристичній агенції потрібно було, за запитом, мати доступ до наявності місць і тарифів на чартерні рейси в B2B-порталах двох туроператорів. Портали спроєктовані для людського ока: ви входите, шукаєте, читаєте таблицю. Публічного програмного інтерфейсу не існує, а інформацію вручну перечитував кілька разів на день одна людина.

Що ми збудували

Ми написали клієнт, який програмно автентифікується і сам відновлює сесію, коли вона спливає, аналізатор, що перетворює відповіді на об’єкти, і шар ідентифікаторів для аеропортів, де код складається з міста і порту, а деякі виклики окремо вимагають ці дві частини. Поверх цього: команду для термінала, яка повертає повний маршрут із доступністю та ціною, режим пакетних запитів із паузами між ними, щоб не заблокувати обліковий запис, і дві JSON-точки входу на випадок, якщо інша платформа захоче споживати результат. Аналізатор тестується на реальних відповідях, збережених як фікстури в репозиторії, а тести, які справді звертаються до порталів, позначені окремо і не запускаються за замовчуванням.

Що вийшло

Набір проходить повністю: 38 перевірок за 0,52 секунди, без звернення до порталів. Один запит повертає в одній відповіді доступність у чотирьох станах, які використовує портал, і тариф із класом та багажем, у потрібній валюті. Результат можна споживати з командного рядка, як JSON, або через дві HTTP-точки входу.

Чого цей випадок не каже

Програмна автентифікація залишається сірою зоною щодо умов використання порталів, і це написано в README проєкту, а не виявлено після передання. Для інтенсивного виробничого навантаження наша рекомендація чітка: слід запитати офіційний API у операторів. Система робить точкові запити та ставить паузи між ними саме для того, щоб не стати інструментом масового витягування даних.

Питання

Про що нас питають, перш ніж зателефонувати

Чому на цій сторінці немає жодної ціни?

Тому що ми не могли б написати її чесно. Обсяг роботи для системи на замовлення визначається трьома речами, яких ми не знаємо, доки не подивимося: скільки зовнішніх систем потрібно зачіпати і чи має якась із них API, скільки правил бізнесу вже десь записано і скільки треба буде виявити від людей, і хто підтримуватиме систему після передання. Цифра, названа до того, як ми побачили систему, — це ворожіння з рахунком. Що ми можемо швидко зробити — це перший етап: прочитати, окреслити межі, написати правила, — який правильно оцінюється і залишається корисним, навіть якщо ви зупинитеся на ньому.

Хто врешті володіє кодом?

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

Що стається, якщо ми хочемо продовжити з кимось іншим?

Передання має зробити це можливим без нас, інакше це не було переданням. Тому документ введення в експлуатацію пишеться для порожньої машини і не передбачає нічого з нашої голови, а тести залишаються в репозиторії, щоб наступна команда знала, що ламається, коли вона щось змінює. Чого ми не можемо обіцяти — це що складну систему можна прийняти без зусиль; ми можемо обіцяти лише, що їй не бракує нічого з того, що потрібно для прийняття.

Чи можу я побачити систему, побудовану вами, щоб оцінити якість?

Частково, і правильно сказати, де це закінчується. Системи, побудовані для клієнтів, не наші, щоб ми їх показували, а внутрішні містять реальні бізнес-дані. Що ми можемо зробити перед вами, на екрані, — це інше: відкрити репозиторій, показати вам правила предметної області, написані текстом, запустити набори тестів — 38 за пів секунди на одному, 81 трохи більш ніж за секунду на іншому, 44 на третьому — і разом прочитати код, який робить заяву, яку ви ставите під сумнів. Цей сайт, у свою чергу, є власною системою, яку можна оглянути зовні.

Наша стара система не має API. Чи можна щось зробити?

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

Ви використовуєте штучний інтелект, щоб писати код?

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

Що ви робите, коли посередині виявляється, що початкова ідея була хибною?

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

Наскільки великим може бути проєкт?

З одного боку — система з трьома застосунками і дванадцятьма спільними пакетами в одному репозиторії, 486 файлами TypeScript, 68 файлами тестів і 151 комітом, із реляційною базою даних, окремою ефемерною координацією від джерела істини та спільними контрактами між застосунками. З іншого — система з одним процесом і двадцятьма точками входу, яка рівно така, як треба. Масштабність — не обіцянка про будь-який розмір, а спостереження, що ми працювали на обох кінцях.

Ви також робите обслуговування після поставки?

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

На чому ґрунтуються твердження вище (15 джерел)

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

Що вам хотілося б налагодити?

Розкажіть про свій процес. Разом визначимо, що варто збудувати, що можна підключити і як перевіримо результат.

Поговорімо