ИИ изменил способ написания кода, но не значение его качества
Для кого нужны комментарии в коде для ИИ-агентов, если агент сам пишет и читает код? Они нужны и людям, и агентам, когда сам код не может объяснить правило. В Webdelo мы следуем простому принципу: задавайте типы там, где это возможно, давайте осмысленные имена и комментируйте то, что нельзя понять из кода.
Агент для программирования (кодинг-агент) - это ИИ-инструмент, который читает файлы и предлагает или вносит изменения. Понятные имена, типы и комментарии помогают ему понять, что эти изменения не должны нарушать. Сложная B2B-система может работать годами, а поддерживать её будут люди вместе с агентами.
Это наш инженерный взгляд, основанный на работе с ERP, CRM и B2B-платформами. Исследования ниже подтверждают пользу содержательного контекста. А порядок, в котором мы добавляем этот контекст в кодовую базу, - собственный практический подход Webdelo.
Компилятор и ИИ-агенты для программирования: корректный код не всегда понятен
Компилятор или интерпретатор следует правилам языка. Агент для программирования также использует имена, типы, комментарии, тесты и контекст репозитория, чтобы понять замысел. Код может выполняться правильно, но при этом его замысел остаётся неясным.
Переименование $availableCredit в $x1 не меняет расчёт. Но оно убирает подсказку о смысле значения. Агенту нужна эта подсказка, чтобы решить, где следует внести запрошенное изменение: в проверках кредитного лимита или в логике взаиморасчётов.
В статье о CodeT5 2021 года заданные разработчиками идентификаторы рассматриваются как значимые сигналы при обучении модели. В статье 2024 года "Коду нужны комментарии" сообщается об улучшениях при обучении на данных, дополненных комментариями. Обе работы посвящены обучению моделей. Ни одна из них не обосновывает правило комментировать каждый метод.
Согласно публичным описаниям, Claude Code и Codex работают с исходными файлами и извлекают нужный контекст по мере необходимости. Их документация не описывает обязательный этап, на котором все комментарии удаляются, а идентификаторы переименовываются до того, как модель увидит код. Но это также не означает, что агент читает весь репозиторий для каждой задачи.
Где хранить знания: сначала типы и имена, затем комментарии
Мы размещаем знания о бизнесе там, где инструменты могут их проверить, а читатели - найти. На первом месте стоят доменные типы, затем осмысленные имена и структура. Комментарии сохраняют причины решений, которые эти средства не могут выразить.
Например, при интеграции с crm системой могут использоваться и идентификаторы клиентов, и идентификаторы расчётных счетов. И те и другие могут быть целыми числами, но они не взаимозаменяемы. Отдельные типы делают это различие явным и позволяют его проверять.
Мы выстраиваем документирование кода в таком порядке:
- Доменные типы: представляют бизнес-понятия и обеспечивают соблюдение их правил.
- Имена и структура: показывают, что означает значение или операция.
- Тесты и контракты: проверяют ожидаемое поведение и требования интерфейсов.
- Комментарии о причинах: объясняют решения, которые нельзя понять из кода рядом.
- Документация репозитория: объясняет правила, охватывающие несколько модулей.
PHP: от примитивов и PHPDoc к доменным типам
Рассмотрим несколько вариантов объявления метода в интерфейсе взаиморасчётов. Первый использует встроенные типы, но оставляет важные вопросы без ответа:
public function settle(
int $accountId,
int $amount,
string $currency,
int $status
): void;
Сумма указана в рублях или копейках? Какие статусы допустимы? Объявления типов и строгая типизация в PHP не отвечают на эти вопросы о бизнес-правилах. declare(strict_types=1) управляет приведением скалярных типов, а не проектированием предметной области или полноценной статической типизацией.
PHPDoc может добавить недостающую информацию:
/**
* @param int $accountId Settlement account ID, not customer ID.
* @param int $amount Amount in minor units.
* @param string $currency Supported three-letter currency code.
* @param int $status 0 = pending, 1 = approved, 2 = settled.
*/
public function settle(
int $accountId,
int $amount,
string $currency,
int $status
): void;
Теперь у читателя есть ответы, но сами описания не обеспечивают соблюдение правил. Вызывающий код всё ещё может передать идентификатор клиента вместо идентификатора счёта.
В третьем варианте эти понятия получают собственные типы:
enum SettlementStatus
{
case Pending;
case Approved;
case Settled;
}
// Closed batches must remain unchanged for reconciliation.
public function settle(
SettlementAccountId $account,
Money $amount,
SettlementStatus $status
): void;
Money - это объект-значение: он хранит сумму вместе с валютой. Такой подход описывает паттерн Money Мартина Фаулера. SettlementStatus использует перечисление PHP, чтобы задать закрытый набор значений.
Эти объявления задают только интерфейс. Объекты-значения должны проверять входные данные. А реализация взаиморасчётов должна обеспечивать соблюдение правил работы с пакетами операций и переходов между статусами. Оставшийся комментарий объясняет, почему существует одно из этих правил.
То же различие важно для Go и Java. Тип int, long или универсальный EntityId может удовлетворять требованиям языка, но почти ничего не говорить о бизнес-смысле.
Когда PHPDoc действительно добавляет информацию
Мы сохраняем PHPDoc, когда он сообщает то, что нельзя выразить встроенными типами. Инструменты статического анализа также могут проверять некоторые аннотации PHPDoc.
- Устаревшие интерфейсы, в которых встроенные типы указаны не полностью.
- Структуры массивов, описывающие обязательные ключи и их значения.
- Обобщённые типы коллекций для статического анализа.
- Контракты, единицы измерения и ограничения внешних API.
- Исключения и побочные эффекты, которые должен учитывать вызывающий код.
@param OrderStatus $status Order status ничего не добавляет к параметру, у которого уже указан тип. При проверке мы задаём простой вопрос: сообщает ли эта строка то, чего нет в сигнатуре?
Хорошие комментарии в коде объясняют почему, а не что
Полезный комментарий сохраняет информацию, которую нельзя достоверно вывести из кода рядом. Это может быть бизнес-причина, ограничение интеграции или правило безопасности. Повторение названия операции такой информации не добавляет.
Эти примеры из бэкенда показывают разницу. Полезные варианты объясняют решение, которое нужно учитывать при будущих изменениях.
// Redundant: update status.
$order->setStatus(OrderStatus::Settled);
// Useful: Only the provider's confirmed callback authorizes settlement.
$order->setStatus(OrderStatus::Settled);
При интеграции платежей в интернет-магазин часто приходится преобразовывать единицы измерения суммы. Вынесите преобразование в метод с понятным именем. Затем поясните, какое внешнее требование диктует такое представление.
// Redundant: set amount.
$request->amount = $payment->minorUnits();
// Useful: This provider accepts integer minor units, not decimal amounts.
$request->amount = $payment->minorUnits();
В торговой системе нереализованная прибыль или убыток - это прибыль или убыток по ещё открытым позициям. При взаиморасчётах их могут намеренно исключать.
// Redundant: calculate total.
$exposure = $settledTrades->total();
// Useful: Unrealized P&L is excluded because it has not settled.
$exposure = $settledTrades->total();
Без этого объяснения читатель может принять намеренное исключение за пропущенное слагаемое в расчёте.
Комментарий, который предотвращает взаимную блокировку: пример на Go
Мьютекс - это блокировка, которая защищает общие данные от одновременных изменений. В этом упрощённом фрагменте на Go сервис портфеля захватывает блокировку перед вызовом updatePosition().
func (p *Portfolio) ApplyFill(symbol string, quantity int64) {
p.portfolioMu.Lock()
defer p.portfolioMu.Unlock()
p.updatePosition(symbol, quantity)
}
func (p *Portfolio) updatePosition(symbol string, quantity int64) {
// Do not lock here - caller already holds portfolioMu.
p.positions[symbol] += quantity
}
Агент, который видит только вспомогательную функцию, может добавить блокировку для защиты общего словаря. Повторный захват того же мьютекса Go заблокирует вызов на неопределённое время. Добавление отдельного positionMu может вызвать взаимную блокировку, если другой путь выполнения захватывает эти две блокировки в обратном порядке.
Комментарий защищает от ошибки и нового разработчика. Но мы всё равно проверяем все места вызова и тестируем конкурентное выполнение. Комментарий не может гарантировать, что блокировку удерживает нужный код.
Сигнал и шум: почему лишние комментарии мешают ИИ
Объём контекста агента ограничен: он может учитывать лишь определённое количество материала за раз. Повторяющийся PHPDoc и построчный пересказ кода занимают этот объём, не добавляя смысла. Устаревший комментарий опаснее, потому что даёт противоречащую коду версию правил.
Рекомендации Anthropic по контекст-инжинирингу отдают приоритет содержательной информации и извлечению нужных подробностей по мере необходимости. Статья OpenAI об инженерной среде для агентов описывает репозиторий как основной источник достоверной информации и объясняет, почему слишком большие файлы инструкций мешают работе.
Мы применяем эти рекомендации на практике: размещаем правило рядом с кодом, к которому оно относится. Пояснения, касающиеся нескольких модулей, храним в документах репозитория, которые легко найти. Постепенное раскрытие контекста означает, что эти подробные документы открывают тогда, когда они нужны для задачи.
Сокращение $settlementAccount до $x1 убирает семантический сигнал, то есть полезный смысл. Оно не обязательно уменьшает расход токенов, потому что модели по-разному разбивают текст. Мы измеряем результаты проекта, а не обещаем определённый процент экономии токенов, затрат или сокращения ошибок.
Чистый код: какие принципы по-прежнему важны при работе с ИИ-агентами
Принципы именования и комментирования из книги Роберта Мартина "Чистый код" по-прежнему помогают писать код, понятный для ИИ. Имена должны раскрывать замысел, а комментарии - сохранять причины решений или предупреждения. Мы применяем эти идеи избирательно, а не считаем каждую рекомендацию книги обязательной.
Глава "Осмысленные имена" предлагает практические правила, полезные и людям, и агентам:
- Раскрывайте замысел: используйте
settledExposureвместоvalue. - Обозначайте значимые различия: различайте
customerIdиsettlementAccountId. - Используйте имена, которые легко найти поиском: дайте бизнес-ограничению узнаваемое имя константы.
- Не заставляйте читателя мысленно расшифровывать имена: ему не должно быть нужно запоминать, что означает
x1. - Используйте одно слово для одного понятия: не называйте одну операцию взаиморасчётом, клирингом и проводкой, если между ними нет реального различия.
Те же термины должны использоваться и в интерфейсе. При работе над дизайном сайта единые бизнес-термины помогают согласовать подписи на экранах с поведением бэкенда.
Глава "Комментарии" не сводится к правилу "никогда не комментируйте". Комментарии не исправят запутанный код, но объяснения замысла и предупреждения полезны. Даже самодокументируемый код нуждается в пояснениях, если причина решения находится за пределами реализации.
Нужно ли просить ИИ-агентов писать комментарии?
Да, но "комментируй каждый метод" - неверная инструкция. Просите агентов документировать скрытые правила и не пояснять очевидный синтаксис. Короткие и чёткие инструкции проекта помогают соблюдать это требование постоянно.
Лучшие практики Anthropic для Claude Code описывают CLAUDE.md как место для инструкций проекта. Мы отделяем общие инженерные правила от настройки под конкретную модель. Пример такой настройки - тема рекомендаций OpenAI по навыкам и запросам.
Короткий блок инструкций позволяет явно задать наши правила комментирования:
Prefer domain types and meaningful names over explanatory comments.
Comment non-obvious business rules and intentional omissions.
Document architectural rules, lock ownership, and external API quirks.
Explain security and compliance constraints that local code cannot show.
Do not restate signatures or obvious syntax.
Update affected comments with code, and verify rules against tests and docs.
Мы проверяем сгенерированные комментарии как утверждения о системе. Если агент не может установить, почему существует правило, он должен указать на неопределённость, а не придумывать правдоподобное объяснение.
AI First не равен вайб-кодингу
В Webdelo подход AI First означает включение ИИ в инженерную работу под контролем человека. Human in the Loop означает, что инженеры проверяют важные решения и отвечают за результат. Сильная модель может ускорять работу и в плохо спроектированной среде.
Личный аккаунт ИИ-сервиса полезен, чтобы проверить идею или собрать рабочий прототип. Эксплуатация B2B-системы добавляет обязанности, которые не заканчиваются после запуска первой рабочей версии:
- Моделирование предметной области и архитектура с учётом будущих изменений.
- Тесты и контракты интеграций, которые выявляют нарушения в работе.
- Наблюдаемость: журналы событий, метрики и оповещения, которые помогают обнаружить сбои.
- Меры безопасности и чёткие границы доступа.
- Проверка человеком и ответственность за выпуски.
Как Webdelo применяет AI First и Human in the Loop
Мы подготавливаем кодовую базу: вводим доменные типы, осмысленные имена, комментарии о причинах решений и короткие инструкции в репозитории. Агенты помогают с рефакторингом в заданных границах, шаблонным кодом, тестами и изучением кода. Инженеры отвечают за модель предметной области, архитектуру и проверку.
"ИИ не заменяет инженерную дисциплину. Хорошие типы должны выражать бизнес-смысл, а комментарии - объяснять только то, чего не показывает сам код. Наша цель - дать агенту не больше текста, а более качественный контекст. Так ИИ ускоряет работу над сложной системой, не ускоряя накопление технического долга."
Мы работаем с B2B-компаниями среднего бизнеса, особенно в Германии, ЕС и США. Для нас разработка сайтов включает сложные платформы и интеграции, за которые инженеры должны отвечать на всём протяжении их работы. Тот же подход применим к ERP, CRM, высоконагруженным системам и интеграции ИИ.
Границы ответственности важны и тогда, когда автоматизация затрагивает работу с клиентами. В такой области, как сео продвижение сайтов, технические изменения нужно проверять перед выпуском. Для продвижения в Ai публикуемые утверждения о бизнесе должны опираться на надёжный источник. В интернет маркетинге автоматические изменения в отслеживании действий пользователей нужно проверять на соответствие требованиям к их согласию.
Результат для бизнеса: системы, которые безопаснее и эффективнее развивать
Цель бизнеса - система, которая остаётся понятной по мере изменений. Ясный код помогает инженерам и агентам оценить последствия запроса до внесения правок. Это делает поддержку более предсказуемой, но не гарантирует конкретную экономию.
Представьте корпоративный сайт, связанный с клиентским порталом и ERP. Изменение условий допуска клиента к услугам может затронуть каждый уровень. Доменные правила с понятными именами и документированные границы интеграций помогают команде найти эти зависимости до выпуска.
При модернизации мы начинаем с правил, которые труднее всего восстановить по существующему коду. При автоматизации с помощью ИИ определяем, что агент может менять сам, а что требует одобрения. Полезные показатели - объём доработок после проверки, дефекты, дошедшие до эксплуатации, и время на проверку изменения.
Обсудите с Webdelo разработку или модернизацию сложной B2B- или ERP-системы либо внедрение ИИ-автоматизации в инженерные и бизнес-процессы. Начните с процесса, который хотите улучшить, и бизнес-правил, которые он должен сохранять.
Лучше контекст, а не больше текста
Полезные комментарии для ИИ-агентов объясняют то, чего не показывает код. Сначала выражайте бизнес-смысл через типы и имена. Оставляйте комментарии для неочевидных причин и поддерживайте их точность по мере изменения системы.
Корректный код - лишь отправная точка. AI First работает, когда инженеры принимают архитектурные решения, проверяют изменения и отвечают за поведение системы в эксплуатации.
Часто задаваемые вопросы
Что должны объяснять комментарии в коде для ИИ-агентов?
Хороший комментарий объясняет почему, а не что. Он сохраняет то, что нельзя понять из соседнего кода: бизнес-причину, архитектурное правило, ограничение интеграции, условие для параллельной работы или намеренный пропуск. Комментарии вроде "обновить статус" над очевидным кодом ничего не дают. Принцип Webdelo: задавайте типы там, где это возможно, давайте осмысленные имена и комментируйте то, что нельзя понять из кода.
Почему имена и типы важны для ИИ-агента, если код и так работает?
Компилятор следует только правилам языка, поэтому код с именем $x1 выполняется так же, как код с $availableCredit. ИИ-агент дополнительно опирается на имена, типы, комментарии, тесты и контекст репозитория, чтобы понять назначение кода. Без осмысленного имени агент теряет подсказку о том, куда относится изменение. Корректный код не всегда понятен.
Как доменные типы уменьшают потребность в комментариях и PHPDoc?
Доменные типы, такие как SettlementAccountId, Money и SettlementStatus, несут бизнес-смысл, которого нет у int и string. Их проверяют инструменты, поэтому вызывающий код уже не передаст идентификатор клиента вместо идентификатора счёта. Описание в PHPDoc только называет правило, но не заставляет его соблюдать. С доменными типами комментариям остаётся объяснять, почему правило существует.
Когда PHPDoc всё ещё стоит писать?
PHPDoc полезен, когда сообщает то, что встроенные типы выразить не могут. Типичные случаи: унаследованные интерфейсы с неполными типами, структуры массивов, обобщённые типы для статического анализа, контракты, единицы измерения, ограничения внешних API, исключения и побочные эффекты. Строка вроде "@param OrderStatus $status Order status" только повторяет сигнатуру. Помогает простой вопрос на ревью: сообщает ли эта строка что-то, чего нет в сигнатуре?
Как один комментарий может предотвратить взаимную блокировку в коде на Go?
Иногда вызывающий код уже удерживает мьютекс перед вызовом вспомогательной функции. Агент или новый разработчик, который видит только эту функцию, может добавить ещё одну блокировку, чтобы защитить общие данные. Повторный захват того же мьютекса в Go навсегда остановит вызов, а вторая блокировка может привести к взаимной блокировке. Короткий комментарий о том, что блокировку держит вызывающий код, делает это правило видимым, но проверка всех вызовов и тесты на параллельную работу всё равно нужны.
Вредят ли лишние комментарии ИИ-агентам?
Да. Агент может одновременно учитывать только ограниченный объём материала, а повторяющийся PHPDoc и построчный пересказ занимают это место и не добавляют смысла. Устаревшие комментарии ещё опаснее: они дают агенту вторую, противоречащую версию правил. Сокращать имена ради экономии токенов не нужно: осмысленные имена - это полезный сигнал. Webdelo не обещает фиксированный процент экономии токенов, затрат или ошибок.
Нужно ли просить ИИ-агентов писать комментарии и чем AI First отличается от вайб-кодинга?
Да, но не правилом "комментируй каждый метод". В инструкциях проекта стоит просить комментарии только для неочевидных бизнес-правил, архитектурных правил и правил параллельной работы, намеренных пропусков, особенностей внешних систем и требований безопасности или комплаенса. Это часть подхода AI First с Human in the Loop: агенты помогают с ограниченными задачами, а инженеры отвечают за доменную модель, архитектуру и ревью. Сильная модель ускоряет и плохо спроектированную среду, поэтому результат по-прежнему зависит от инженерной дисциплины.