Шаман обещал мамонта 🦣. Племя нашло stop-loss 📉
Глава 3. Грог Сырокаменный 👑 против CRM 🗄️
Интеграция с корпоративными стандартами — четвёртая скала, вслед за тремя, что обтёсывались во второй главе. В крупных системах Java уже связана с базами данных, очередями и мониторингом, поэтому AI-функционал встраивается в существующую инфраструктуру, а не строит «островок хаоса» по соседству, как пещера с сомнительной репутацией 🕳️. Это незаметное, но решающее преимущество: модели не нужен отдельный контур, она встаёт в строй там, где уже стоят проверки, логи и резервное копирование. Ирония в том, что enterprise-инфраструктуру долго ругали за тяжеловесность — а именно она оказалась готовой клеткой для капризной экзотики 🧩.
Как это выглядит на практике? Нужно сгенерировать реалистичные тестовые данные — имена, адреса, профили — с помощью LLM. Модель придумает правдоподобные строки, но без контроля нарушит бизнес-правила: email без «@», телефон в неверном формате или дата рождения, делающая пользователя моложе допустимого возраста. Отдельное развлечение — имена, которые модель придумывает сама: «Грог Сырокаменный III» 👑 звучит красиво, но CRM такого персонажа не переживёт. Есть и порок тоньше: модель любит округлять и причёсывать — адреса выходят аккуратнее, чем есть на самом деле, а аккуратность в тестовых данных подозрительна, потому что тест должен ломать систему кривыми вводами, а не любоваться ровными. Правдоподобие и корректность — разные добродетели, и модель уверенно владеет только первой 🎭.
На Java процесс строится в пять шагов, а не в три (мы же взрослые люди, а не стая). Сначала определяется типизированный объект с аннотациями Bean Validation: у имени запрет на пустоту, у email — свой шаблон, у телефона — формат E.164, у возраста — разумные границы. Затем JSON-схема уходит в промпт со строгой просьбой «верни JSON по этой схеме» — свобода модели ограничивается рамками, как у кота в переноске 🐈. Третьим шагом включается structured output или function calling, чтобы модель физически не могла вернуть что-то вне схемы: не «постарается», а не сможет — разница между обещанием шамана и дубиной вахтёра 🪵. Четвёртым ответ маппится на объект и валидируется. Пятым выполняются семантические проверки, потому что схема прошла — это ещё не значит, что данные корректны: форма кости есть, а мамонта нет 🦴. Возраст в границах, но у младенца он восемьдесят девять; телефон валиден, но принадлежит ресторану напротив; имя выглядит пристойно, но содержит слово, которое юристы запретят показывать скриншотом на конференции. Каждый шаг дешёвый, но пропустить любой — значит перенести его цену в прод, где шаги оплачиваются валютой инцидентов 💸.
public record UserProfile( @NotBlank String name, @Email String email, @Pattern(regexp = “^\+[1-9]\d{1,14}$”) String phone, @Min(18) @Max(99) int age) {}
Если валидация не проходит — тест падает до выполнения, и «мусорные» данные не попадают в прогон 🚫. Падение на входе дешевле падения в середине прогона: вместо получаса раздумий «а что это вообще проверяло» инженер сразу видит причину. AI отвечает за креативность и вариативность, инженерные контракты — за целостность и соответствие требованиям. Тот же принцип работает и для генерации тест-кейсов: строгий формат с идентификатором, предусловиями, шагами, ожидаемым результатом и тегами автоматически превращается в JUnit- и TestNG-тесты и уезжает в CI/CD, не теряя по дороге ни одного шага. Рутину делает модель, качество — инженер: роли разделены, как обязанности охотника и огнехранителя, и перепутать их так же опасно. Если тест всё-таки падает — он падает по делу, с воспроизводимой причиной, а не с настроением «мне сегодня лень» 🥱. Заодно контракт на данные документирует сам себя: новому члену племени не нужно расспрашивать старейшин, что считается корректным профилем 📜. И главное — связка переживает смену модели: завтра вместо одного шамана придёт другой, но схема, валидация и семантические проверки останутся прежними, потому что живут не в промпте, а в коде. Шаман может бубнить что угодно, но в прогон попадают только проверенные кости 🔍.