Эксперимент с вайбкодингом можно считать законченным. Цель эксперимента состояла в том, чтобы понять насколько это жизнеспособный метод разработки, насколько он эффективен и его ограничения.
В качестве задачи я выбрал разработку iOS приложения. Во-первых, я вообще не интересовался ею последние 10 лет, а во-вторых, мне его не хватало. Суть приложения в том, чтобы автоматизировать рутинные операции с помощью LLM. В моем случае это исправление моих корявых текстов на английском и украинском, перевод на английский и болгарский и саммари веб-страниц. Разработка подобнго для Raycast заняла у меня один вечер. То есть проблема состояла именно в разработке под iOS. И эту часть должна была полностью на себя взять LLM. А моя задача была в том, чтобы LLM минимально помогать.
Итог следующий: приложение удалось создать за 60 часов. Оно работает и выполняет свои функции. Это 6 экранов, кастомный внешний вид и 6500 ncloc swift-кода. У него с десяток незакрытих проблем, но с ними можно жить. Оно загружено в TestFlight, откуда я могу его раздавать. И оно, скорее всего, не пройдет модерацию из-за несоответствия гайдлайнам 🙂
Выводы:
- Я точно не смог бы самостоятельно разработать такое приложение за 60 часов. Слишком много всего пришлось бы изучать.
- Я потерял часов 15 на битву с xcodegen, выстраивание обвязки вокруг него, swiftlint, swiftformat и так далее. Если бы я сразу взял tuist, то, скорее всего, не потерял бы по паре часов на элементарные задачи, типа “приложения нет в диалоге share из-за неправильной вложенности в YAML” или “иконка приложения не появляется из-за опечатки в названии”.
- С другой стороны, если бы я не пытался сразу сделать окружение, где все можно сделать через CLI, то я бы до сих пор по инструкциям тыкал бы в кнопки в xcode.
- Из этого вытекает важность построения максимально быстрого для LLM цикла change/test. Через cli или MCP, может быть. Чем он будет быстрее и чем лучше будут сообщения об ошибках, тем быстрее будет идти разработка.
- Знакомство с базовыми концепциями, скорее всего, зачительно ускорило бы разработку, за счет избегания ошибок и “костылей”.
- Модель совершенно не умеет генерализировать по имеющемуся коду. Опытный программист обычно задним умом чует места, где лучше заложить абстракцию на будущие изменения (так называемый “технический зазор под будущие костыли”). У меня в базовых инструкциях было требование предлагать 2 метода улучшения кода в конце каждой задачи. И там ни разу не было ничего путного на уровне всей архитектуры. Из-за этого приходилось иногда просить её устраивать ревью архитектуры, и там уже были вполне полезные советы.
- Нужно постоянно дорабатывать инструкции, добавляя туда частые ошибки, новые требования и т.д. И даже это не помогает при длинных сессиях, когда модель начинает “забывать” начало. Например, у меня это были постоянные попытки импортировать код из модуля Common, хотя он был видим и без импортов.
- Нужно постоянно поддерживать проект в правильном состоянии с точки зрения линтера и тестов.
- Иногда проще начать выполнение задачи сначала, чем пытаться разобраться, что не так в текущем решении.
- Поддержка картинок в cursor — это потрясающая фича для объяснения проблем. Вполне можно решать даже вопросы выравнивания и прочих GUI-проблем. Делаешь скриншот, обводишь проблемное место, загружаешь в IDE. Если LLM не запутается с тем, из чего состоит отступ, то может и исправить 😉
- В следующий раз, если я решу разрабатывать с нуля в незнакомой инфраструктуре, это будет:
- очень тщательный выбор тулинга с максимальной валидацией и четкими сообщениями об ошибках
- максимально детальное ТЗ, которое будет постоянно актуализироваться (возможно, стоит отказаться от architecture.md и implementation.md из memory bank)
- короткий и понятный для модели цикл change/test с поятными сообщениями об ошибках
Но тем не менее, приложение написано и:
- работает с указанным ключом OpenAI
- переводит, упрощает, суммирует, исправляет ошибки
- умеет переводить на клингонский и синдарин