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,
  • перекладає, спрощує, підсумовує та виправляє помилки,
  • і так, він може перекладати навіть клінгонською.