Комментарии пишутся для людей.
// GetUser retrieves a user by ID from the database.
func GetUser(id string) (*User, error) {
Этот комментарий полезен, когда его читает человек. Но когда его читает машина, она ничего не понимает. Не знает, означает ли “retrieves” Read или Search. Не знает, какая сущность скрывается за “user”. Не знает, следует ли эта функция паттерну Service или паттерну Repository.
Потому что комментарий – это повествование.
Когда функций 10 000
Когда функций 10, это не проблема. Человек может прочитать всё.
Когда функций 10 000, всё иначе. Когда кто-то просит “покажи все функции, связанные с оплатой”, ни человек, ни машина не могут их найти. Находятся только те, в названии которых есть “payment”. Если в названии нет – пропускается.
То же самое происходит, когда ИИ-агент модифицирует код. Когда вы просите Claude Code “исправить обработку ошибки PaymentFailed”, агент перечитывает весь код. Каждый раз. Анализирует 10 000 функций с нуля, каждый раз. Сегодня читает тот же код, что читал вчера. Даже с комментариями результат тот же. Потому что комментарии – это повествование для людей. Чтобы машина извлекла смысл из повествования, нужен вывод. Это дорого.
Если комментарии станут индексами
// CreateOrder processes a new order creation.
//
// # Pattern: Service, Transactional
// # Entity: Order
// # Action: Create
// # Input: CreateOrderRequest {items:[]Item, userID:string}
// pre: items>0 userID!=''
// # Output: *OrderResponse, error
// errs: [StockInsufficient, PaymentFailed]
// # Deps: InventorySvc, PaymentGateway
func (s *OrderService) CreateOrder(req CreateOrderRequest) (*OrderResponse, error) {
Этот комментарий могут читать и люди, и машины.
“Все функции с паттерном Service” -> поиск по полю Pattern. Мгновенно. “Все функции, связанные с сущностью Order” -> поиск по полю Entity. Мгновенно. “Функции, генерирующие PaymentFailed” -> поиск по полю errs. Мгновенно.
Полное сканирование превращается в поиск по индексу. O(n) становится O(1).
Людям не нужно писать это вручную
Эти индексы не нужно писать людям.
Когда код изменяется, изменение обнаруживается автоматически. Мониторинг файлов. Изменённая функция выделяется через AST. Механически. Тело функции передаётся маленькой LLM. “Определи паттерн, сущность и действие этой функции.” Результат анализа вставляется в заданном формате. Механически.
Человек ничего не делает. Просто пишет код. Индекс добавляется автоматически.
Во всём конвейере LLM участвует только в одной точке – определение смысла функции. Всё остальное – детерминированный код.
От вывода к правилам
Здесь мы идём на шаг дальше.
Когда маленькая LLM многократно присваивает один и тот же индекс одному и тому же паттерну – это повторение обнаруживается. Если “суффикс Service с receiver method означает Pattern:Service” повторилось 100 раз, это закрепляется как правило. После этого LLM больше не вызывается. Правило обрабатывает.
Вызовы LLM постепенно уменьшаются. Правила постепенно увеличиваются. Стоимость стремится к нулю.
Комментарии превращаются из повествования в индекс, индексы превращаются из ручных в автоматические, а автоматические превращаются из вывода в правила.
Почему это возможно: шаблоны проектирования как кодовая книга
Есть причина, почему это возможно.
В программировании уже существует стандартизированный семантический словарь. Это шаблоны проектирования.
Singleton, Factory, Observer, MVC, Service. С тех пор как GoF систематизировали 23 паттерна в 1994 году, индустрия программного обеспечения расширяла и стандартизировала этот словарь в течение 30 лет.
23 паттерна GoF. Enterprise Application Patterns. Cloud Design Patterns. Go Concurrency Patterns. Всё уже систематизировано.
Этот словарь не является двусмысленным. Singleton – это Singleton. Разные разработчики не интерпретируют его по-разному. Определение согласовано, условия реализации ясны, нарушения выявляются на код-ревью.
Эта система словаря становится кодовой книгой индекса. Не нужно создавать новую. Она уже есть.
В естественном языке этого нет. “Великий” имеет определение в словаре, но каждый человек использует это слово по-разному. В коде Service не используется по-разному каждым разработчиком.
Почему код – самый простой домен
Контекстный конвейер GEUL – уточнение, индексация, верификация, фильтрация, согласованность, исследование – трудно применить к естественному языку. Применить к коду – легко.
Уточнение: естественный язык неоднозначен. Код, если компилятор его принял, имеет определённый смысл. Индексация: сущности в естественном языке зависят от контекста. Сущности в коде уже разобраны AST. Верификация: валидность естественного языка нельзя определить. Валидность кода определяет компилятор. Фильтрация: релевантность в естественном языке требует LLM. Релевантность в коде можно определить механически через граф вызовов. Согласованность: противоречия в естественном языке обнаруживаются только через вывод. Противоречия в коде ловятся системой типов и тестами. Исследование: знания на естественном языке плоские. Код уже имеет иерархию: пакет -> файл -> тип -> метод.
Один и тот же конвейер работает с гораздо меньшими затратами в домене кода. Сначала доказать там, где проще всего, а затем расширять на более сложные области. Это и есть инженерия.
Итог
Комментарии изначально предназначались для людей. Теперь они должны быть и для машин. Комментарии, которые люди могут читать, а машины – искать. Комментарии, которые являются повествованием и одновременно индексом.
Код уже имеет смысл, уже имеет структуру, уже имеет словарь. Не хватает только индекса. И комментарии могут стать этим индексом.