Многоцветный кубик-робот сидит на ноутбуке рядом с монитором, отображающим код.

Чувствуете этот запах? Скрытый технический долг в разработке ИИ.

Почему скорость без стандартов приводит к созданию уязвимых продуктов на основе искусственного интеллекта

Делиться

Изображение предоставлено автором.

Не каждый может «почувствовать» их с первого раза. На практике «запахи кода» — это предупреждающие знаки, указывающие на будущие проблемы. Код может работать сегодня, но его структура намекает на то, что его будет сложно поддерживать, тестировать, масштабировать или обеспечивать безопасность. «Запахи» не обязательно означают ошибки ; это индикаторы проектного долга и долгосрочного риска для продукта.

Эти «запахи» обычно проявляются в виде замедленной доставки и повышенного риска изменений, более частых регрессий и производственных инцидентов, а также менее надежных результатов ИИ/машинного обучения, часто обусловленных утечками, предвзятостью или дрейфом, которые подрывают оценку и обобщение.

Путь от прототипа к серийному производству

Большинство этапов разработки продуктов на основе данных/искусственного интеллекта могут различаться, но обычно они следуют схожему пути. Как правило, мы начинаем с прототипа: сначала набрасывается идея, а затем следует небольшая реализация для демонстрации ее ценности. Такие инструменты, как Streamlit , Gradio или n8n, можно использовать для представления очень простой концепции с помощью синтетических данных . В этих случаях вы избегаете использования конфиденциальных реальных данных и снижаете опасения по поводу конфиденциальности и безопасности , особенно в крупных компаниях , где важна конфиденциальность или где действуют строгие правила регулирования.

Позже вы переходите к этапу проверки концепции (PoC), где используете реальную выборку данных и углубляетесь в разработку функций, тесно сотрудничая с бизнесом. После этого вы переходите к созданию продукта , разрабатывая минимально жизнеспособный продукт (MVP) , который развивается по мере проверки и получения бизнес-ценности.

В большинстве случаев прототипы и доказательные концепции создаются быстро, а искусственный интеллект еще больше ускоряет их разработку. Проблема в том, что такой код редко соответствует производственным стандартам. Прежде чем он станет надежным, масштабируемым и безопасным, обычно требуется рефакторинг на всех уровнях : инженерном (структура, читаемость, тестирование, удобство сопровождения), безопасности (контроль доступа, защита данных, соответствие требованиям) и качестве машинного обучения/искусственного интеллекта (оценка, мониторинг отклонений, воспроизводимость).

Типичные запахи, которые вы видите… или нет 🫥

Этот скрытый технический долг (часто проявляющийся в виде «запахов кода») легко упустить из виду, когда команды стремятся к быстрым результатам , а «кодирование в соответствии с духом проекта» может его усугубить. В результате могут возникнуть такие проблемы, как:

  • Дублирование кода: одна и та же логика скопирована в нескольких местах, поэтому исправления и изменения со временем становятся медленными и непоследовательными.
  • «Божественный скрипт» / «божественная функция»: один огромный файл или функция делает всё, что затрудняет понимание, тестирование, проверку и безопасное изменение системы, поскольку всё тесно взаимосвязано. Это нарушает принцип единственной ответственности [1]. В эпоху агентов появляется паттерн «божественный агент», где единая точка входа агента обрабатывает маршрутизацию, получение данных, подсказки, действия и обработку ошибок — всё в одном месте.
  • Разрастание правил : поведение разрастается в длинные цепочки if/elif для новых случаев и исключений, что приводит к необходимости многократного редактирования одной и той же основной логики и увеличению регрессий. Это нарушает принцип открытости-закрытости (OCP) : вы постоянно изменяете ядро вместо того, чтобы расширять его [1]. Я наблюдал это на ранних этапах разработки агентов, когда маршрутизация намерений, обработка этапов лидов, правила, специфичные для каждой страны, и исключения для особых случаев быстро накапливаются в длинные цепочки условий.
  • Жестко заданные значения: пути, пороговые значения, идентификаторы и специфические для среды параметры встроены в код, поэтому для внесения изменений требуется редактирование кода в нескольких местах, а не простое обновление конфигурации.
  • Неправильная структура проекта (или расположение папок): логика приложения, оркестрация и конфигурация платформы сосуществуют, размывая границы и затрудняя развертывание и масштабирование.
  • Скрытые побочные эффекты: функции выполняют дополнительную работу, которую вы не ожидаете (изменение общего состояния, запись файлов, фоновые обновления), поэтому результаты зависят от порядка выполнения, и ошибки становится трудно отследить.
  • Отсутствие тестов: отсутствуют автоматизированные проверки для выявления отклонений после изменений в коде, подсказках, конфигурации или зависимостях, поэтому поведение может незаметно меняться до тех пор, пока система не выйдет из строя. (К сожалению, не все понимают, что тесты обходятся дёшево, а ошибки — нет).
  • Несогласованность в именовании и структуре: затрудняет понимание кода и обучение других пользователей, замедляет проверку кода и делает поддержку зависимой от первоначального автора .
  • Скрытые/перезаписанные правила: поведение зависит от непротестированных, неверсионированных или слабо управляемых входных данных, таких как подсказки , шаблоны, настройки и т. д. В результате поведение может изменяться или перезаписываться без возможности отслеживания.
  • Пробелы в безопасности (отсутствующие меры защиты): На ранних этапах часто игнорируются такие аспекты, как проверка входных данных, права доступа, обработка секретной информации или контроль персональных данных.
  • Запрятанная устаревшая логика: старый код, такой как конвейеры обработки данных, вспомогательные функции, утилиты и т. д., остается разбросанным по всей кодовой базе еще долго после изменения продукта. Этому коду становится сложнее доверять, поскольку он содержит устаревшие предположения, дублированную логику и неработающие пути, которые все еще выполняются (или незаметно исчезают) в продакшене.
  • Слепая работа (отсутствие оповещений/обнаружения): сбои остаются незамеченными до тех пор, пока пользователь не пожалуется, кто-то вручную не проверит журналы CloudWatch или не произойдет сбой в работе нижестоящего задания. Журналы могут существовать, но никто активно не отслеживает важные сигналы, поэтому инциденты могут оставаться незамеченными. Это часто происходит, когда внешние системы изменяются вне контроля команды или когда слишком мало людей понимают систему или данные.
  • Ненадежные интеграции: бизнес-логика зависит от конкретных деталей API/SDK (имена полей, обязательные параметры, коды ошибок), поэтому небольшие изменения от поставщика приводят к разрозненным исправлениям по всей кодовой базе вместо одного изменения в адаптере. Это нарушает принцип инверсии зависимостей (DIP) [1] .
  • Разница в среде разработки (тестовая среда ≠ производственная): у команд есть среды разработки, тестирования и производственной среды, но тестовая среда не является по-настоящему производственной : разные конфигурации, права доступа или зависимости, что создает ложное чувство уверенности : перед релизом все выглядит хорошо, но реальные проблемы появляются только в производственной среде (часто заканчиваясь откатом изменений).

И этот список можно продолжать бесконечно…

Проблема не в том, что прототипы плохи. Проблема в разрыве между скоростью создания прототипов и ответственностью за их внедрение в производство, когда команды по той или иной причине не инвестируют в методы, которые делают системы надежными, безопасными и способными к развитию .

Также полезно расширить понятие «запахи кода» на «запахи модели и конвейера »: предупреждающие знаки того, что система может выдавать уверенные, но вводящие в заблуждение результаты, даже когда агрегированные метрики выглядят отлично. Распространенные примеры включают в себя пробелы в справедливости (показатели ошибок в подгруппах постоянно хуже), перелив/утечку (оценка случайно включает будущую или реляционную информацию, которой не будет на момент принятия решения, что приводит к несоответствию между разработкой и производством [7]) и/или мультиколлинеарность (коррелированные характеристики, которые делают коэффициенты и объяснения нестабильными). Это не академические крайние случаи; они надежно предсказывают последующие сбои, такие как слабая обобщаемость, несправедливые результаты, ненадежные интерпретации и болезненные сбои в производстве.

Если каждый разработчик решает одну и ту же проблему независимо и по-разному (без общего стандарта), это всё равно что иметь несколько пультов дистанционного управления (каждый с разным поведением) для одного и того же телевизора. Принципы разработки программного обеспечения по-прежнему важны в эпоху «вайб-кодирования». Именно они делают код надежным, поддерживаемым и безопасным в использовании, являясь основой для реальных продуктов.

Теперь возникает практический вопрос: как снизить эти риски, не замедляя работу команд?

Почему ИИ ускоряет появление «запахов кода»

Генераторы кода на основе ИИ не знают автоматически, что наиболее важно в вашем коде. Они генерируют результаты на основе шаблонов, а не контекста вашего продукта или бизнеса. Без четких ограничений и тестов вы можете получить пять минут «генерации кода», за которыми последуют сто часов отладки ☠️.

При неосторожном использовании ИИ может даже усугубить ситуацию:

  • Это чрезмерно упрощает или исключает важные части.
  • Это создает лишний шум: ненужный или дублирующийся код и многословные комментарии.
  • В больших кодовых базах происходит потеря контекста (поведение, проявляющееся в процессе выполнения).

В недавней статье MIT Sloan отмечается, что генеративный ИИ может ускорить кодирование, но он также может затруднить масштабирование и улучшение систем с течением времени, когда быстрые прототипы незаметно превращаются в производственные системы [4].

В любом случае, рефакторинг — дело недешевое , независимо от того, был ли код написан человеком или создан с помощью неправильно используемого ИИ, и затраты обычно проявляются позже в виде замедления разработки, сложного обслуживания и постоянного решения проблем . По моему опыту, у обоих случаев часто одна и та же первопричина: слабые основы разработки программного обеспечения.

Некоторые из самых неприятных проблем вовсе не технические, а организационные . Команды могут иметь незначительные долги 😪, потому что это не сразу ощущается, но скрытые издержки проявляются позже: ответственность и стандарты не масштабируются. Когда первоначальные авторы уходят, получают повышение или просто переходят на другую работу, плохо структурированный код передается кому-то другому 🫩 без общих соглашений по читаемости, модульности, тестам или документации. Результат предсказуем: поддержка превращается в археологические раскопки, разработка замедляется, риски возрастают, и человек, который наследует систему, часто наследует и вину.

Контрольные списки: краткий перечень рекомендаций

Это сложная тема, требующая экспертного мнения опытных инженеров. Контрольный список не заменит разработку платформы, безопасность приложений или опытных экспертов, но он может снизить риски, сделав основные моменты последовательными и затруднив их пропуск.

1. Недостающий элемент: проектирование по принципу «сначала проблема».

Подход «сначала проектирование / сначала проблема» означает, что прежде чем создавать продукт на основе данных или систему искусственного интеллекта (или постоянно добавлять функции в подсказки или правила if/else), вы четко определяете проблему, ограничения и возможные сбои. И это касается не только проектирования продукта (что вы создаете и зачем), но и проектирования программного обеспечения (как вы его создаете и как оно развивается). Такое сочетание трудно превзойти.

Также важно помнить, что технологические команды (инженеры ИИ/машинного обучения, специалисты по обработке данных, специалисты по контролю качества, специалисты по кибербезопасности и специалисты по платформам) являются частью бизнеса, а не отдельной структурой. Слишком часто высокотехнические должности рассматриваются как оторванные от более широких бизнес-задач . Это остается проблемой для некоторых руководителей предприятий, которые могут воспринимать технических экспертов как всезнаек, а не как профессионалов (что не всегда верно) [2].

2. Контрольные параметры кода: проверка качества, безопасности и отклонения от нормы поведения.

На практике технический долг растет, когда качество зависит от того, насколько хорошо люди «помнят» стандарты. Контрольные списки делают ожидания явными, повторяемыми и масштабируемыми для разных команд, но автоматизированные механизмы контроля идут дальше: вы не можете объединить код в продакшн, если основные требования не соблюдены . Это гарантирует минимальный базовый уровень качества и безопасности при каждом изменении.

Автоматизированные проверки помогают предотвратить попадание наиболее распространенных проблем прототипа в производство. В эпоху ИИ, когда код генерируется быстрее, чем его можно проверить , механизмы контроля кода действуют как ремень безопасности, обеспечивая последовательное соблюдение стандартов. Практический способ — запускать проверки как можно раньше, а не только в CI. Например, хуки Git, особенно pre-commit, могут запускать валидацию еще до того, как код будет зафиксирован [5]. Затем конвейеры CI запускают полный набор проверок для каждого запроса на слияние, а правила защиты ветвей могут требовать прохождения этих проверок до разрешения слияния, обеспечивая соблюдение качества кода даже при пропуске стандартов.

Надежный базовый уровень обычно включает в себя:

  • Линтеры (например, ruff): обеспечивают единообразный стиль и выявляют распространенные проблемы (неиспользуемые импорты, неопределенные имена, подозрительные шаблоны).
  • Тесты (например, pytest): предотвращают скрытые изменения поведения, проверяя, что ключевые функции и конвейеры по-прежнему работают должным образом после редактирования кода или конфигурации.
  • Сканирование секретов (например, Gitleaks): блокирует случайные публикации токенов, паролей и ключей API (часто жестко закодированных в прототипах).
  • Сканирование зависимостей (например, Dependabot / OSV): выявляет уязвимые пакеты на ранней стадии, особенно когда прототипы быстро подключают библиотеки.
  • Оценки LLM (например, регрессия подсказок): если подсказки и настройки модели влияют на поведение, обрабатывайте их как код, проверяя входные данные и ожидаемые выходные данные, чтобы выявить отклонения [6].

Это краткий список, но по мере развития систем команды часто добавляют дополнительные меры защиты, такие как проверка типов для раннего выявления ошибок интерфейса и ошибок типа «None», статический анализ безопасности для выявления рискованных шаблонов, ограничения покрытия и сложности для предотвращения непротестированного кода, а также интеграционные тесты для обнаружения критических изменений между сервисами. Многие также включают сканирование инфраструктуры как кода и образов контейнеров для выявления небезопасных облачных сред, а также мониторинг качества данных и моделей/LLM для обнаружения отклонений в схеме и поведении, и многое другое.

Как это помогает

Сгенерированный ИИ код часто содержит шаблонный код, остатки кода и рискованные сокращения. Защитные механизмы, такие как линтеры (например, Ruff), быстро выявляют предсказуемые проблемы: некорректные импорты, мертвый код, шумные сравнения изменений, рискованные шаблоны исключений и распространенные уязвимости Python. Инструменты сканирования помогают предотвратить случайные утечки секретной информации и уязвимые зависимости, а тесты и оценки делают изменения в поведении видимыми, запуская наборы тестов и инициируя регрессионный анализ каждого запроса на слияние перед внедрением в производство. В результате — более быстрая итерация с меньшим количеством неожиданностей в производственной среде.

Освободите ограждения

Помимо проверки запросов на слияние (pull request) перед выпуском в продакшн (production), команды также используют тестовую среду в качестве механизма контроля жизненного цикла: это среда, подобная производственной, с контролируемыми данными для проверки поведения, интеграций и стоимости перед релизом.

3. Человеческие ориентиры: общие стандарты и объяснимость

Передовые инженерные практики, такие как проверка кода, парное программирование, документирование и общие командные стандарты, снижают риски, связанные с кодом, сгенерированным ИИ. Распространенная ошибка в программировании на Vibe заключается в том, что автор не может четко объяснить, что делает код, как он работает или почему он должен работать. В эпоху ИИ крайне важно формулировать намерения и ценности простым языком и кратко документировать решения, а не полагаться на многословные результаты работы ИИ. Речь идет не о запоминании синтаксиса, а о проектировании, передовых практиках и дисциплине совместного обучения, потому что единственная константа — это перемены.

4. Ответственный ИИ по замыслу.

Контрольные меры — это не только проверка стиля кода и CI. Для систем искусственного интеллекта контрольные меры необходимы на протяжении всего жизненного цикла, особенно когда прототип превращается в реальный продукт. Практический подход — это контрольный список «Ответственный ИИ по умолчанию», охватывающий минимальный уровень контроля от подготовки данных до развертывания и управления.

Как минимум, он должен включать:

  • Подготовка данных: защита конфиденциальности, контроль качества данных, проверка на предвзятость/справедливость.
  • Разработка модели: соответствие бизнес-целям, объяснимость, тестирование на устойчивость.
  • Отслеживание экспериментов и версионирование: воспроизводимость результатов за счет контроля версий наборов данных, кода и моделей.
  • Оценка модели: стресс-тестирование, анализ подгрупп, оценка неопределенности, где это уместно.
  • Развертывание и мониторинг: отслеживайте отклонения/задержки/надежность отдельно от бизнес-показателей эффективности; определяйте правила оповещений и переобучения.
  • Управление и документация: журналы аудита, четкое определение ответственных лиц и стандартизированная документация для согласований, анализа рисков и отслеживания.

Одностраничный документ, представленный на рисунке 1, — это лишь первый шаг. Используйте его в качестве отправной точки, а затем адаптируйте и расширяйте его, учитывая свой опыт и контекст вашей команды.

Одностраничный документ, представленный на рисунке 1, — это лишь первый шаг. Используйте его в качестве отправной точки, а затем адаптируйте и расширяйте его, учитывая свой опыт и контекст вашей команды.

5e9503b95775e00c2fe0e71264ad32aa

5. Состязательное тестирование

Существует обширная литература по проблеме состязательных входных данных. На практике команды могут проверять устойчивость системы, вводя в нее входные данные (в LLM и классическом машинном обучении), с которыми система никогда не сталкивалась в процессе разработки (некорректные данные, шаблоны, похожие на инъекции, экстремальные длины, странные кодировки, граничные случаи). Ключевым моментом является культура: состязательное тестирование должно рассматриваться как нормальная часть разработки и обеспечения безопасности приложений, а не как разовое мероприятие.

Это подчеркивает, что оценка не является разовым событием в автономном режиме: команды должны проверять модели с помощью поэтапных процессов выпуска и постоянно поддерживать наборы данных оценки, метрики и проверки подгрупп, чтобы выявлять сбои на ранней стадии и снижать риски до полного развертывания [8].

Заключение

Прототип часто выглядит небольшим: блокнот, скрипт, демонстрационное приложение. Но как только он соприкасается с реальными данными, реальными пользователями и реальной инфраструктурой, он становится частью графа зависимостей, сети компонентов, где небольшие изменения могут иметь неожиданно большой радиус воздействия.

Это важно для систем искусственного интеллекта, поскольку жизненный цикл включает в себя множество взаимозависимых движущихся частей, и команды редко имеют полную информацию обо всех них, особенно если они не планируют это с самого начала. Отсутствие такой информации затрудняет прогнозирование последствий, особенно когда задействованы данные, модели или сервисы третьих сторон.

Что это часто включает в себя:

  • Зависимости программного обеспечения: библиотеки, контейнеры, этапы сборки, базовые образы, средства непрерывной интеграции.
  • Зависимости во время выполнения: нижестоящие сервисы, очереди, базы данных, хранилища признаков, конечные точки моделей.
  • Зависимости, специфичные для ИИ: источники данных, хранилища векторных представлений/векторов, подсказки/шаблоны, версии моделей, тонкая настройка, базы знаний RAG.
  • Зависимости в области безопасности: IAM/права доступа, управление секретами, сетевые средства контроля, управление ключами и политики доступа.
  • Зависимости в управлении: требования к соблюдению нормативных требований, возможность аудита, а также четкие процессы определения права собственности и утверждения.

Для бизнеса это не всегда очевидно. Прототип может выглядеть «готовым», потому что он запускается один раз и выдает результат, но производственные системы ведут себя скорее как живые организмы: они взаимодействуют с пользователями, данными, поставщиками и инфраструктурой, и им требуется постоянное обслуживание, чтобы оставаться надежными и полезными. Сложность развития этих систем легко недооценить, потому что большая часть процесса остается невидимой, пока что-нибудь не сломается .

Здесь быстрые победы могут ввести в заблуждение. Скорость может скрывать взаимозависимость, отсутствие контрольных точек и операционные пробелы, которые проявляются лишь позже в виде инцидентов, регрессий и дорогостоящих переделок. Эта статья, неизбежно, не охватывает всего, но цель состоит в том, чтобы сделать эту скрытую сложность более наглядной и поощрять подход, ориентированный на проектирование, который масштабируется за пределы демонстрации.

Ссылки

[1] Мартин, Р. К. (2008). Чистый код: Справочник по гибкому программному обеспечению. Prentice Hall.

[2] Хант, А., и Томас, Д. (1999). Прагматичный программист: от подмастерья к мастеру. Аддисон-Уэсли.

[3] Канат-Александр, М. (2012). Простота кода: основы программного обеспечения. O'Reilly Media.

[4] Андерсон, Э., Паркер, Г., и Тан, Б. (2025, 18 августа). Скрытые издержки кодирования с использованием генеративного ИИ (Перепечатка 67110). MIT Sloan Management Review.

[5] iosutron. (2023, 23 марта). Создавайте лучший код!!. Затерянные в технологиях . WordPress.

[6] Arize AI. (без даты). Полное руководство по оценке LLM: Практическое руководство по разработке и внедрению стратегий оценки для приложений ИИ. Получено 10 января 2026 г. с сайта Arize AI.

[7] Гомес-Гонсалвеш, Э. (2025, 15 сентября). Не заглядывайте вперед: обнаружение мошенничества в графах с учетом времени. На пути к науке о данных. Получено 11 января 2026 г. с сайта Towards Data Science.

[8] Шанкар, С., Гарсия, Р., Хеллерстайн, Дж. М., и Парамесваран, А. Г. (2022, 16 сентября). Операционализация машинного обучения: исследование на основе интервью. arXiv:2209.09125. Получено 11 января 2026 г. с arXiv.

Источник: towardsdatascience.com

✅ Найденные теги: Запах, ИИ, новости, Разработка, Технический Долг, Чувствуете

ОСТАВЬТЕ СВОЙ КОММЕНТАРИЙ

Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Человек спит в кровати под красным пледом, солнечный свет падает на подушку.
Человек в смокинге держит планеты Земля и Марс, символизируя космические достижения.
Твердотельный аккумулятор Donut на выставке, показывает замещающий литий-ион стоимость.
Человек рядом с изображением двойной спирали ДНК на фоне природы.
Залитый солнцем лес с деревьями и болотистой водой, покрытой зелёной растительностью.
Пленка NeoFilm 100 на деревянном столе в окружении упаковок.
Деревянный минималистичный сундук с подсветкой в интерьере.
Обложка отчета о преодолении разрыва в операционном ИИ от MIT Technology Review.
Твит о разработке в 2026: выполнение сложных задач до пробуждения США, чтобы избежать проблем с ИИ.
Image Not Found
Человек в смокинге держит планеты Земля и Марс, символизируя космические достижения.

Почему SpaceX может выйти на биржу и с чем это может быть связано

Мы ведь явно не воспринимаем всерьез центры обработки данных в космосе? Элизабет Лопатто, старший репортер. Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной странице вашего сайта. Все…

Мар 5, 2026
Твердотельный аккумулятор Donut на выставке, показывает замещающий литий-ион стоимость.

Согласно результатам испытаний, твердотельная батарея Donut Lab способна выдерживать (экстремальные) температуры.

Разработанная финским стартапом батарея не только выдержала экстремальные условия высокой температуры, но и фактически увеличила свою емкость. Эндрю Дж. Хокинс, редактор раздела «Транспорт». Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в…

Мар 5, 2026
Пленка NeoFilm 100 на деревянном столе в окружении упаковок.

Цифровая камера OPT NeoFilm 100 в формате плёнки

Компактная камера OPT NeoFilm 100 выполнена в виде классической 35-мм плёнки, но внутри скрывается не аналоговый механизм, а цифровая «начинка», способная снимать фото и видео.  Камера оснащена 1-мегапиксельным сенсором, который позволяет получать изображения с разрешением до 3…

Мар 5, 2026
Деревянный минималистичный сундук с подсветкой в интерьере.

«Умная» кровать-трансформер Roll

Хорватский дизайнер Лука Булян разработал проект складной кровати Roll, которая по нажатию кнопки сворачивается в аккуратный деревянный шкаф. Главная идея строится на принципе ежедневного скручивания матраса без потери его свойств. Конструкция оснащена тихим электродвигателем и плавным механизмом…

Мар 5, 2026

Впишите свой почтовый адрес и мы будем присылать вам на почту самые свежие новости в числе самых первых