Craftify
Компілюється — значить працює
Експеримент з “vibecoding” можна вважати завершеним. Метою експерименту було оцінити, наскільки життєздатним є цей метод розробки, наскільки він може бути ефективним і якими є його обмеження.
Як тестове завдання я обрав розробку iOS-застосунку. По-перше, тому що я не цікавився iOS-розробкою останні 10 років. По-друсте, тому що мені справді був потрібен такий застосунок. Його основна ідея — автоматизувати рутинні операції за допомогою LLM. У моєму випадку це виправлення моїх незграбних текстів англійською та українською мовами, переклад їх англійською та болгарською, а також самарі вебсторінок. Я вже зібрав щось подібне для Raycast за один вечір. Тож справжнім викликом була саме iOS-розробка. І ця частина мала повністю контролюватися LLM, за моєї мінімальної допомоги.
Ось підсумок: мені вдалося створити застосунок за 60 годин. Він працює і виконує свою задачу. У ньому 6 екранів, кастомний UI та близько 6500 рядків коду на Swift (за cloc). У ньому близько десятка невирішених проблем, але нічого критичного. Він завантажений у TestFlight, тож я можу ним поділитися. Хоча, швидше за все, він не пройде перевірку в App Store через невідповідність гайдлайнам :)
Висновки:
- Я б ні за що не зміг зібрати такий застосунок самотужки за 60 годин. Мені б довелося вивчити занадто багато всього.
- Я витратив близько 15 годин на боротьбу з xcodegen, створення обгорток для інструментів навколо нього, інтеграцію swiftlint, swiftformat тощо. Якби я з самого початку обрав Tuist, я б, імовірно, не витрачав години на банальні речі на кшталт «застосунок не відображається в share sheet через неправильну вкладеність YAML» або «іконка застосунку не відображається через друкарську помилку в назві».
- З іншого боку, якби я не намагався налаштувати середовище, де все запускається через CLI, я б досі копався в кнопках Xcode, слідуючи туторіалам.
- Це підкреслює важливість побудови максимально швидкого циклу змін/тестування для LLM — через CLI або, можливо, MCP. Чим він швидший і чим кращі повідомлення про помилки, тим швидше йде розробка.
- Наявність базових концептуальних знань суттєво прискорила б процес, допомагаючи уникнути помилок і “костилів”.
- У моделі немає відчуття узагальнення існуючого коду. Досвідчений розробник часто інтуїтивно відчуває, де потрібно закласти абстракції, щоб врахувати майбутні зміни (так званий «технічний буфер для майбутніх хаків»). У мене була постійна інструкція для LLM пропонувати два способи покращення коду в кінці кожного завдання — і жодного разу вона не запропонувала нічого значущого на архітектурному рівні. Мені доводилося спеціально запитувати архітектурні рев’ю, щоб отримати дійсно корисні пропозиції.
- Потрібно постійно вдосконалювати інструкції, додаючи туди типові помилки, нові вимоги тощо. І навіть це не допомагає під час довгих сесій — модель починає «забувати» ранній контекст. У моєму випадку вона постійно намагалася імпортувати код з модуля Common, хоча він і так був видний без імпорту.
- Проєкт має постійно підтримуватися у валідному стані з точки зору лінтера та тестів.
- Іноді простіше почати задачу з нуля, ніж розбиратися, що не так з поточним рішенням.
- Підтримка зображень у Cursor — це кілер-фіча для пояснення проблем. Так можна вирішувати навіть проблеми з вирівнюванням UI та версткою. Робиш скриншот, виділяєш проблемну область, завантажуєш в IDE — і якщо LLM не заплутається в тому, що викликає проблему з відступами, вона може навіть її виправити ;)
- Наступного разу, коли я занурюся в розробку з нуля в незнайомій інфраструктурі, я:
- ретельно оберу інструментарій, що пропонує максимум валідації та зрозумілі повідомлення про помилки,
- підготую максимально детальну специфікацію, яка постійно оновлюється (можливо, варто прибрати
architecture.mdтаimplementation.mdз пам’яті), - налаштую короткий і зручний для моделі цикл змін/тестування з чітким зворотним зв’язком щодо помилок.
Тим не менш, застосунок написаний і:
- працює з вказаним ключем OpenAI,
- перекладає, спрощує, підсумовує та виправляє помилки,
- і так, він може перекладати навіть клінгонською.