- BrainTools - https://www.braintools.ru -
Я открыл демо-версию DatePicker’а, и она выглядела вполне обычно. Поле ввода, кнопка, всплывающий календарь, keyboard navigation, метки для screen reader’ов, макеты для настольных компьютеров и мобильных устройств.
С внешней стороны ничего особенного. Интересным был не сам компонент, а то, как мы его создали.
Привет, коллеги!
Меня зовут Илья, я технический директор компании «Исходный код». Наша frontend-команда последние шесть месяцев занималась улучшением доступности компонентов React (a11y). Мы хотели проверить простой вопрос на задаче, которая снаружи выглядит небольшой, но внутри очень быстро разрастается: сможет ли AI-агент создать доступный DatePicker производственного уровня для React и TypeScript?
Ответ — да.
Более точный ответ — да, если рассматривать AI как часть инженерной системы, а не как волшебную машину для печати кода.
Open-source проект доступен по ссылке [1] на Github. Демо-версия DatePicker’а доступна по этой ссылке [2].
DatePicker кажется простым, но это не так.
Сначала появляется сетка календаря и выбранное значение, затем следуют: keyboard navigation, управление фокусом, screen reader’ы, контролируемое состояние, локализация, мобильная верстка, проверки доступности (a11y) и все те мелкие состояния, которые возникают, когда реальные пользователи дважды нажимают или переключаются с помощью клавиши Tab, а затем вновь открывают всплывающее окно или очищают значение.
Мы сравнили два подхода:
80% работы доверяем AI, остальные 20% делаем руками (то, что мы делали в предыдущей статье [3]). Вы даете модели подробную подсказку, получаете большую часть компонента, а остальное дорабатываете вручную.
Системное проектирование с помощью AI-агента. Вы готовите требования, архитектурные правила, задачи, тесты, проверки, и только потом позволяете агенту писать код. При этом, модель дорабатывает результат через итерации и prompt engineering. Подход хорошо описан в документации к инструменту по ссылке [4].
Оба подхода могут работать, разница только в том, где они дают сбой. Давайте посмотрим на них поближе.
Очевидный шаг — дать модели Claude четкий запрос на основе WAI-ARIA APG [5] и попросить ее сгенерировать DatePicker.
Для прототипа этого может быть достаточно, ведь модель знает, как выглядит сетка календаря, она может писать компоненты React, обработчики, атрибуты логику [6] keyboard navigation.
Проблема начинается когда первая версия выглядит почти готовой.
Большинство ошибок возникает не внутри отдельного элемента, а на стыках между элементами:
Строгое следование APG может привести к созданию разметки, которая выглядит правильно, но работает с реальными экранными считывателями хуже, чем контролируемое отклонение от руководства.
Диалоговое окно может начать мигать из-за того, что обработчики onBlur и onClick конфликтуют друг с другом.
Разница между атрибутами aria-live="polite" и assertive выглядит незначительной в коде, но становится реальной проблемой UX, когда screen reader начинает озвучивать изменения.
В этом заключается главный недостаток разработки с помощью AI. Модель может писать код, который выглядит правильно, но она не может достоверно оценить поведение [7] системы в целом.
Архитектура также разрастается случайно. Вы исправляете ошибку [8] с фокусом, затем — с состоянием, а потом — с доступностью. Компонент начинает работать, но его внутренняя структура определяется исправлениями. Для прототипа это приемлемо, но для компонента, который должен работать в реальных условиях, это рискованно.
Мы выбрали более медленный путь.
Я не хотел одного большого запроса типа «создай мне DatePicker». Мне нужен был контролируемый процесс, в котором у AI-агента было бы меньше возможностей для импровизации и больше давления, чтобы он следовал инженерным правилам.
Агент работал в конфигурации по типу цикла Ralph на основе codex cli и gpt 5.4-mini.
Мы предоставили ему файл AGENTS.md со строгими правилами проекта. В нем агент описывался как старший frontend-инженер, работающий над доступным DatePicker’ом производственного уровня для React и TypeScript.
Полный promt доступен по ссылке [9].
Затем мы добавили внешнюю память [10]:
Файл PRD.md был основным источником достоверной информации. В нем были зафиксированы требования: API, поддерживающий только элементы с атрибутом controlled, полная keyboard navigation, правильная разметка поведение [11].
Файл tasks.json служил для отслеживания задач. Мы разбили работу на небольшие этапы: создание папок, определение типов даты, написание чистых функций даты, создание компонентов UI, а затем их соединение.
Файл progress.md был рабочим журналом. Агент должен был фиксировать, что изменилось и в каком состоянии находился проект.
И задействовали субагентов:
Специалист по PRD [12]
Архитектор кода [13]
Frontend-специалист [14]
Благодаря этому задача «напиши мне DatePicker» превратилась в процесс, в ходе которого создается и проверяется достойный DatePicker.
Результаты:
Ключевой частью был верификатор. Агент выбирал задачу, писал или изменял код, а затем наш внешний скрипт проверял результат.
Он запускал модульные тесты и тесты доступности с помощью Vitest и Playwright, собирал проект с помощью Vite и проверял типы с помощью tsc -noEmit.
Если что-то давало сбой, агент получал журнал ошибок и должен был исправить текущую задачу. Он не мог двигаться дальше, пока задача не была выполнена успешно. Благодаря этому ошибки оставались локальными.
Агент по-прежнему мог генерировать некорректный код, но не мог незаметно перенести неработающий шаг на следующий этап.
В результате проект естественным образом перешел к трехуровневой архитектуре:
Ядро содержало чистую логику в lib/date и lib/input.
UI содержал «глупые» компоненты без состояния.
Модель связывала состояние, поведение и представление.
Это разделение было сделано не ради красоты, оно снижало затраты на внесение изменений:
Ошибка в вычислении даты относится к чистой функции.
Ошибка фокусировки относится к модельному слою.
Визуальное состояние относится к UI.
Нам больше не приходилось отлаживать весь компонент как один большой блок.
Я не хочу преподносить это как волшебство, даже хорошая архитектура по-прежнему давала сбои в некоторых местах. Однажды небольшое изменение в расчете недели вызвало каскадную проблему в DatePicker’е, она возникла из слоя, откуда мы этого не ожидали. Это показало нам полезный предел: одних слоев недостаточно, большой системе также нужны контракты между слоями и проверка этих контрактов.
Теперь мы более ответственно подходим к границам. У слоя должно быть не только название, но и контракт, и этот контракт должен тестироваться.
Настоящая разница заключается в стоимости изменений.
Создание кода с помощью AI изначально обходится недорого. Достаточно составить один четкий promt, чтобы получить рабочую v1.0. Для минимально жизнеспособных продуктов (MVP), хакатонов, экспериментов и одноразовых прототипов это зачастую является правильным выбором.
Стоимость проявляется позже.
Без архитектурных правил модель может сгенерировать код, который сегодня работает правильно, а завтра станет источником проблем. Добавление выбора времени, выбора диапазона или настраиваемого форматирования может превратиться в рефакторинг вместо простого расширения.
Системная инженерия изначально обходится дорого.
Вы тратите время на PRD, декомпозицию задач, правила агентов, верификацию и тестирование. Вы также тратите больше токенов.
Окупаемость проявляется, когда компонент меняется.
Нужен выбор времени? Мы расширяем ядро, добавляем компонент UI и обновляем уровень модели. Остальные части остаются практически нетронутыми. Изменения не бесплатны, но они предсказуемы. Именно эта предсказуемость и является главной ценностью.
Я бы не стал применять системное проектирование с помощью AI-агента повсеместно.
Подход «80% работы доверяем AI, остальные 20% делаем руками» хорошо подходит, когда цена ошибки низкая: прототипы, по ссылке [15].
Cистемное проектирование с помощью AI-агента лучше подходит, когда цена ошибки высокая: системы дизайна, общие компоненты UI, интерфейсы с высокими требованиями к доступности, основная логика приложения и долговечные продукты.
Выбор заключается в том, какой риск вы готовы взять на себя: подход 80/20 переносит риск в будущее, а системное проектирование окупается раньше, снижая этот будущий риск.
AI не устранил инженерную работу из этой задачи, а поднял ее на уровень выше: мы написали меньше кода руками, и в то же время уделили больше внимания [16] замыслу, архитектуре, верификации и контролю отклонений — компромисс кажется правильным.
AI может выполнять четкие задачи и по-прежнему не может решать: что следует создать, соответствует ли результат реальному замыслу и проверяют ли «зеленые» тесты то, что нужно — роль человека в этом процессе не исчезает, а становится в большей степени связанной с определением направления, установлением границ, заключением соглашений и верификацией.
Создание компонента DatePicker’а с использованием AI — это сложно не потому, что React сложен, а потому, что у компонента есть множество мелких требований: состояние, фокус, поведение клавиатуры, вывод для screen reader’ов, логика даты, макет и контролируемое поведение API.
Для меня это главный урок:
Один promt может сгенерировать огромное количество кода, а система может предотвратить отклонение этого кода от заданного курса.
Будущее AI в разработке — это не только более совершенные модели, а еще и качественная инженерия вокруг моделей.
Я пока не рассматриваю агентов как автономных разработчиков, но вижу в них сильных исполнителей в рамках контролируемой среды.
UPD от 29.06.2026: Заменил слово «DataPicker» на «DatePicker» в названии и тексте.
Автор: inova99
Источник [17]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/32341
URLs in this post:
[1] по ссылке: https://github.com/Codesrc-public-ru/ralf-datapicker
[2] по этой ссылке: https://ralf-datapicker.netlify.app/
[3] то, что мы делали в предыдущей статье: https://habr.com/ru/articles/1052878/
[4] по ссылке: https://api.vc.ru/v2.8/redirect?to=https%3A%2F%2Fgithub.com%2Fsnarktank%2Fralph&postId=2889623
[5] WAI-ARIA APG: https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/
[6] логику: http://www.braintools.ru/article/7640
[7] поведение: http://www.braintools.ru/article/9372
[8] ошибку: http://www.braintools.ru/article/4192
[9] по ссылке: https://github.com/Codesrc-public-ru/ralf-datapicker/blob/main/AGENTS.md
[10] память: http://www.braintools.ru/article/4140
[11] поведение: http://www.braintools.ru/article/5593
[12] Специалист по PRD: https://subagents.cc/agents/prd-specialist
[13] Архитектор кода: https://subagents.cc/agents/code-architect
[14] Frontend-специалист: https://subagents.cc/agents/frontend-developer
[15] по ссылке: https://%D0%9F%D0%BE%D0%B7%D0%BD%D0%B0%D0%BA%D0%BE%D0%BC%D0%B8%D1%82%D1%8C%D1%81%D1%8F%20%D1%81%20%D0%BD%D0%B0%D1%88%D0%B8%D0%BC%20%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%BC%20%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%BE%D0%BC%20%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%20%D0%BF%D0%BE%20%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B5
[16] внимания: http://www.braintools.ru/article/7595
[17] Источник: https://habr.com/ru/articles/1052932/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1052932
Нажмите здесь для печати.