Одна идея этого урока: архитектура – это прежде всего решение, где проходят границы и что через них проходит.
Знакомая ситуация
Твой платёжный провайдер поднял комиссию, и ты решил перейти на другого. Просишь агента: «замени платёжку». Ответ обескураживает: «Придётся править страницу оплаты, логику доступов, телеграм-бота и три отчёта – вызовы старой платёжки разбросаны по всему проекту».
Замена одного внешнего сервиса превратилась в операцию на всём организме. Это значит, что у платёжки в твоём приложении не было границы.
Архитектура – это не выбор технологий. Это решение, где провести границы (boundaries) между частями системы и какой минимум информации пропускать через каждую. Проведи границу правильно – и то, что за ней, можно менять, не трогая остальное.
Граница и контракт – простыми словами
Граница (boundary) – линия, которая отделяет одну часть системы от другой. Контракт (contract, он же API) – договорённость о том, что через эту линию проходит: «ты мне – запрос "принять оплату на сумму X", я тебе – ответ "оплачено" или "отказ"».
Всё, что внутри границы, – частное дело этой части. Какой провайдер, какие запросы он шлёт, как выглядят его ошибки – снаружи никто знать не должен. Это прямое продолжение идеи глубоких модулей из урока 2: простой контракт снаружи, вся возня внутри.
Четыре главные границы почти любого твоего приложения:
1
Интерфейс пользователя UIЭкраны, кнопки, сообщения бота. Меняется чаще всего – дизайн, тексты, каналы.
2
Логика business logicПравила твоего бизнеса: кому дать доступ, когда напомнить, что считать оплатой. Сердце приложения.
3
Данные dataЧто и где хранится: ученики, платежи, доступы. Самая инертная часть – об этом весь следующий урок.
4
Внешние сервисы external servicesПлатёжки, LLM-API, телеграм, почтовые рассылки. Ты их не контролируешь: они меняют цены, правила и иногда исчезают.
Проверка хорошей границы одна: переживёт ли она замену того, что за ней? Если завтра сменить провайдера оплаты, LLM-модель или дизайн лендинга – сколько мест придётся править? В идеале одно: то, что внутри границы.
Граница доверия: всё снаружи – под подозрением
Есть особый вид границы – граница доверия (trust boundary). Она отделяет то, что ты контролируешь, от того, что приходит извне: данные из формы на лендинге, сообщение в телеграм-боте, ответ LLM, вебхук от платёжки.
Правило сеньора: всё, что пересекает границу доверия снаружи внутрь, – проверяй. Пользователь пришлёт ерунду в поле «телефон». LLM вернёт ответ не в том формате. Платёжка пришлёт вебхук дважды. Это не редкие сбои, а нормальная жизнь – ты уже видел это в уроке про краевые случаи. Граница доверия – то место, где такие проверки должны жить, а не размазываться по всему коду.
Как думают три уровня
Джун · границ нетВсё в одной куче: вызов платёжки прямо в коде страницы, запрос к LLM прямо в обработчике кнопки. Работает – и ладно. Любая замена снаружи превращается в раскопки по всему проекту.
Мидл · границы по шаблонуРаскладывает код по папкам, как велит фреймворк: «контроллеры», «модели», «сервисы». Порядок есть, но границы проведены по типам файлов, а не по смыслу – замена платёжки всё равно трогает пять папок.
Сеньор · границы по точкам замен и рисковСпрашивает: «что здесь с наибольшей вероятностью заменят или что подведёт?» – и проводит границы именно там. Платёжка, LLM-провайдер, канал уведомлений – за отдельными границами с простым контрактом. Всё внешнее – ещё и за границей доверия.
Проверь себя
1. Ты запускаешь планировщик для учеников школы. Где сеньор в первую очередь проведёт границу?
Границы проводят там, где вероятны замены и риски, – а это почти всегда внешние сервисы: у них меняются цены, лимиты и правила. Размер файлов – вопрос удобства чтения, не архитектуры. И маленькие приложения растут: границы дешевле всего провести в начале.
2. Агент говорит: «Чтобы страница курса работала быстрее, я буду обращаться из неё напрямую к базе данных, минуя слой логики». Что ответит сеньор?
Обход границы – это скрытая связь между частями, которые не должны знать друг о друге. «Только одно исключение» – так границы и умирают: следующее исключение сошлётся на это. Если скорость правда проблема, её решают внутри границы (кэш, оптимизация запроса), не ломая контракт.
3. Телеграм-бот принимает от пользователя e-mail для выдачи доступа. Где по уму должна жить проверка, что это вообще e-mail?
Всё, что пришло снаружи, проверяется один раз – на входе, на границе доверия. Дальше система работает уже с проверенными данными. Проверять «везде для надёжности» – значит размазать одну и ту же логику по всему проекту (привет, дублирование), а не проверять вовсе – значит пустить мусор внутрь.
Что говорить агенту уже сегодня
Перед стартом проекта: покажи главные границы приложения: UI, логика, данные, внешние сервисы – и что проходит через каждую
Про внешние сервисы: изолируй платёжку (и LLM-API) за отдельным модулем, чтобы провайдера можно было заменить, не трогая остальное
Тест на прочность: если завтра сменим провайдера X – сколько мест в коде придётся править? сделай так, чтобы одно
Про безопасность: всё, что приходит снаружи – от пользователей, вебхуков, LLM – проверяй на границе, до основной логики