Одна идея этого урока: лучшая часть системы – та, что даёт много пользы через простой интерфейс.
Знакомая ситуация
Ты добавляешь в приложение школы оплату. Агент справился: платежи проходят. Но через месяц ты решаешь сменить платёжного провайдера – и выясняется, что его название, валюты и обработка ответов размазаны по боту, лендингу и личному кабинету. «Поменять провайдера» превращается в ремонт половины приложения.
В твоих инструкциях агенту уже есть фраза «мысли глубокими самодостаточными модулями». Этот урок – фундамент под ней: что именно делает модуль глубоким и почему это работает.
Глубокий модуль (deep module) – это часть системы, которая прячет много работы за маленьким простым интерфейсом. Ценность модуля = польза внутри минус сложность интерфейса снаружи.
Интерфейс и реализация
У любого модуля – будь то «оплата», «уведомления» или «расписание» – есть две стороны:
1
Интерфейс interfaceВсё, что остальная система обязана знать, чтобы модулем пользоваться: какие операции есть, что им дать на вход, что вернётся. Это «кнопки на пульте».
2
Реализация implementationКак модуль устроен внутри и делает свою работу. Это «электроника под крышкой» – снаружи её не видно, и это хорошо.
Глубина – это соотношение сторон. Модуль «оплата» с одной операцией «создать платёж» может внутри выбирать провайдера, конвертировать валюты, ловить вебхуки (webhook – ответный сигнал от платёжной системы) и повторять неудавшиеся попытки. Снаружи – одна кнопка, внутри – много пользы. Это глубокий модуль. А модуль, который снаружи требует знать столько же, сколько делает внутри – мелкий (shallow): пользы от него как от пульта, где по кнопке на каждый транзистор.
Что модуль прячет
Механизм, который создаёт глубину – сокрытие информации (information hiding): каждое знание системы живёт ровно в одном модуле. Какие провайдеры бывают, как считать комиссию, в каком формате приходит ответ – всё это знает только «оплата». Остальные части даже не догадываются.
Противоположность – утечка деталей (information leakage): одно и то же знание расползлось по нескольким местам. Если формат ответа провайдера известен и боту, и лендингу – при смене провайдера придётся править оба, и это то самое «изменение против шерсти» из урока 1. Утечку выдаёт вопрос: «если это изменится, сколько мест придётся трогать?» Ответ больше одного – знание утекло.
Как думают три уровня
ДжунКлеит всё со всем: страница заказа сама ходит к платёжному провайдеру, бот сам считает комиссию. Модулей нет, детали торчат наружу, каждое изменение задевает всех. Так же делает ИИ-агент без направления – кратчайшим путём.
МидлУже делит систему на модули, но мелкие: обёртка на каждую операцию, прослойка на прослойке. Оустерхаут зовёт это «классит» (classitis) – модулей много, а прятать им нечего. Интерфейсов стало больше, сложность выросла, хотя выглядит «аккуратно».
СеньорПроектирует интерфейс до реализации: сначала решает, какой должна быть «кнопка», чтобы ей было удобно пользоваться – потом прячет под неё всю грязную работу. Главный вопрос к любому модулю: «что он прячет?» Если ответа нет – модуль не нужен.
Важный сдвиг мышления: сеньор готов сделать внутри сложнее, чтобы снаружи стало проще. Сложность, спрятанная в одном модуле, оплачивается один раз. Сложность в интерфейсе оплачивает каждый, кто модулем пользуется – включая твоего агента в каждой следующей сессии.
Проверь себя
1. Агент спроектировал модуль «уведомления»: снаружи доступны операции «подключиться к Telegram», «сформировать текст», «выбрать канал», «отправить», «обработать ошибку отправки». Что скажет сеньор?
Пять операций – это пять вещей, которые обязан знать и правильно вызвать каждый, кто хочет просто отправить сообщение. Каналы, тексты и ошибки – работа самого модуля. Одна кнопка снаружи, вся кухня внутри – вот что делает модуль глубоким.
2. Ты решил сменить платёжного провайдера. При хорошем дизайне модуля «оплата» что придётся менять?
В этом весь смысл сокрытия информации: знание «какой у нас провайдер» живёт только внутри модуля, поэтому замена – локальная операция. Если пришлось править места вызова – знание утекло. А «переходник поверх старого» добавляет прослойку без пользы: старая сложность остаётся, плюс новый слой.
3. Агент разбил оплату на шесть мини-модулей: «проверка данных», «запись в журнал», «отправка», «приём ответа»... Каждый – крошечный и просто передаёт данные следующему. Это хорошая модульность?
Классический «классит»: делить систему полезно только тогда, когда каждая часть что-то прячет. Здесь шесть публичных интерфейсов вместо одного, а вся цепочка всё равно видна снаружи. Мелкость каждой части не компенсирует сложность их связей. Папка тем более ничего не меняет – это про раскладку файлов, а не про интерфейсы.
Что говорить агенту уже сегодня
Перед новой частью системы: сначала спроектируй интерфейс модуля: какие операции видны снаружи и что он прячет внутри
Тест на глубину: что именно прячет этот модуль? если ничего – объясни, зачем он нужен
При выборе из вариантов: выбери вариант с самым простым интерфейсом, даже если реализация внутри будет сложнее
Уборка: найди в проекте мелкие модули-обёртки без собственной пользы и предложи, что с чем объединить