Аліас+: кілька тисяч слів про армію і моє хобі

💡 Усі статті, обговорення, новини про Mobile — в одному місці. Приєднуйтесь до Mobile спільноти!

Про те, як я заробив $50 за пів року — і задоволений результатом. Про те, як Аліас+ потрапив в App Store за 13 днів, і в Google Play трошки пізніше. Про синдром вічного новачка-самозванця і мій вихід із цього циклу.

Хто я

Привіт, DOU! Мене звати Олексій, нещодавно мені виповнилося 33, з 2022 я у війську.

Програмування ніколи не було моєю роботою, але завжди було моїм хобі. І от, на п’ятому році служби, автоматизувавши все, до чого дотягнулися руки, я продовжую займатись своїми особистими проєктами у вільний від служби час. Мої інструменти — Claude Code і велике бажання створювати щось з нуля до готового продукту.

Як я починав і скільки разів

Я працював у call-центрі інтернет-магазину і про програмування взагалі нічого не знав, окрім того, що починати треба з HTML та CSS. Намагався періодично їх вчити, але, як пізніше виявилось, фронтенд я не люблю.

У тому call-центрі була дивна ситуація з базою знань: якась частина інформації була на Joomla, завдяки якій я дізнався про конструктори сайтів, а в деяких випадках оператори шаруділи роздруківками в пошуках відповідей на питання клієнтів. Тоді в мене це викликало дисонанс. Я вирішив розв’язати цю проблему для себе й інших та створити свою базу знань, де буде усе.

Так почалась битва з Joomla, яку на той момент я програв: окрім відносно зрозумілого натягування шаблонів, там треба було розуміти основи мереж, які на той час для мене були темним лісом. Але, на моє щастя, тоді з’явився Wix, який вимагав від тебе тільки навичок роботи з мишкою і клавіатурою. Не буду затягувати: базу знань я зробив, пошуковик теж був на місці. Але програний бій з Joomla дав мені зрозуміти, що я нічого не знаю про мережі й бекенд, а я хотів створювати готове рішення, а не його частину.

Тим часом моя база знань на Wix розійшлась, і нею почали користуватись усі. Директорка це побачила і запропонувала мені посаду anykey — по суті, молодшого системного адміністратора, — на яку я погодився з невеликим острахом не впоратись.

Зайшовши в новий кабінет, я побачив там його... Марка Лутца, «Изучаем Python». Ну я і сприйняв це як заклик. Роботи було небагато: зазвичай тікети «не працює ПК» означали, що хтось висунув вилку з розетки, аби зарядити телефон, або ж треба було просто натиснути кнопку увімкнення монітора. Користувачі)) Тож у мене було достатньо часу, аби почати вивчення Python.

Грошей на курси в мене тоді не було, а тут халявна книжка, яка на початку йшла доволі важко. Починав я її з початку рази зо три. Я наче усе розумів — як працюють цикли, умови, функції, — але не міг нічого написати. Сидів і дивився на чистий PyCharm з його if __name__ == "__main__" і просто не міг почати писати щось не з книжки. Тоді я робив висновок, що я погано зрозумів геть усе і що треба починати з нуля, і знову повертався на першу сторінку. Паралельно дивився туторіали на YouTube, які теж передивлявся по декілька разів і переписував один і той самий код з екрана.

Без перебільшення, відкатувався на старт десятки разів. Плюсом цього стало те, що я дійсно добре засвоїв базу.

Все змінила реальна задача. Нам потрібен був скрипт, який під час розкатування ОС Linux задавав ПК специфічний hostname, що залежав від кількох параметрів, і відправляв сповіщення в ТГ-бот. І тут я зрозумів, що я знаю, як це зробити — за допомогою штатного пітонівського модуля os і одного URL-запиту.

Тоді до мене й дійшло: мені просто не вистачало реальної проблеми, яку потрібно вирішити, а не нескінченного мавпування туду-листів і розв’язання задач, значущість яких я в жодному разі не применшую. Скрипт був написаний, я отримав свій перший кодофамін.

Основною «проблемою», до якої я не був готовий, було те, що я завжди впирався в щось нове, що треба було вчити, а результату хотілось дуже швидко. Я хотів створювати готові продукти, а не якусь малу їх частину. Так я потрапив у таку собі вікіпедійну пастку, коли одна лиш сторінка містить цілу прірву посилань, а за тими — такі самі сторінки. Фронт, бек, бази даних, мережі, докер...

Я поверхнево вчив усе відразу, але просто фізично не міг отримати глибокого розуміння усього того, за що хапався, адже результат мені був потрібен «сьогодні ввечері». Я вигорав — і знову повертався. В такому режимі я жив декілька років. Навряд чи це було правильною стратегією, та й стратегією як такою.

У нас були овертайми — їх давали всім охочим, незалежно від посади. А оскільки в мене був бекграунд оператора, то я, вже працюючи сисадміном, брав ці овертайми у вільний від основної роботи час і робив, по суті, операторську роботу. Тільки вже з автоматизацією.

Я заавтоматизував до дір усе, до чого міг дотягнутися своїм PyAutoGUI. З його допомогою закривав письмові звернення клієнтів, де платили за кількість таких закритих звернень, і за два тижні назбирав собі на GeForce GTX 1660 SUPER GAMING, яка на той час коштувала непосильні для мене 8 тисяч гривень. Це були перші гроші, які я заробив за допомогою програмування)

Звідки взявся Аліас+

Я познайомився з Аліасом у часи нічних змін, коли я був оператором: тоді треба було не спати і тримати фокус, і ми з групою колег відкрили для себе цю гру. Це було не тільки весело, а й поповнювало словниковий запас.

Коли ти граєш в Аліас, ти не просто пробігаєшся по слову, як під час читання книги, — ти малюєш його образ у себе в голові, крутиш його, шукаєш асоціації, і бажано нестандартні, смішні, хитрі. Я завжди любив гратись зі словами. Якщо я жартую, то це найімовірніше якийсь каламбур та гра з подвійним сенсом. Впевнений, що Аліас тут зіграв не останню роль. Також мені подобалось, як різні люди пояснюють різні слова: я бачив патерн мислення — які асоціації виникають у різних людей, — та й сам брав щось собі на озброєння.

Тоді ще ми грали в російськомовний Аліас.

У 2022, після початку широкомасштабної війни, я деякий час спостерігав за своїм другом, який мобілізувався до лав збройних сил. Спостерігав із погреба. Скажімо так: Льоха із льоху висовувався не часто. росіяни були близько, постійні обстріли. В якийсь момент друг сказав, що у війську відчуває себе безпечніше, ніж удома. Ну, це стало точкою прийняття рішення. Я пройшов співбесіду у військовій частині, отримав відношення і мобілізувався. Так почався мій шлях у війську. Пам’ятаю, як після строкової служби у 2012 казав усім, що в армію я більше ніколи не повернусь))

Періодично ми з різними людьми грали в Аліас, це все ще було цікаво, але чим більше тривала війна, тим рідше ми грали. Мені здається, через те, що звичайні побутові слова ставали все далі від нас. Ніякої драми: у мене не надскладні умови служби, я вважаю, що в мене все добре. Все склалося так, як я і хотів. Просто коли опиняєшся в іншому середовищі, із попереднього випадаєш.

Але цінність Аліаса як гри для мене нікуди не ділась, ба більше — набула нового сенсу: лагідна українізація. Я доволі непогано знаю українську мову, попри те, що зростав у російськомовному Миколаєві, за що дуже вдячний моїй першій вчительці в СЗОШ № 29 Аллі Іванівні і вчительці української мови та літератури Олені Вікторівні. Але українська мова занадто велика, і переходити на неї досить складно — тож тут Аліас стає в пригоді. Тим паче це такий широкий простір для нових каламбурів!

З побратимами ми грали в Аліас нечасто. І в якийсь момент, після ешелону малознайомих нам слів із цивільного життя, один з них сказав:

— Шось він якийсь не згідно-відповідний.

Тоді я, вже маючи за плечима чимало створених і похованих проєктів з Claude Code, кажу: «То давай я зроблю „Північноатлантичний Аліас“!»

— Роби!

Ну я і сів то робити. «Північноатлантичний Аліас» не прижився, бо в Apple могли реджекнути за намагання якось обіграти НАТО в дизайні, та й назва була задовга. Далі був «Доповідаліас» — робоча назва, від крінжу якої пальці на ногах мимоволі підгинаються, коли я це пишу, тому прожила вона добу. І нарешті народився проєкт із назвою, яку не треба пояснювати жодному причетному, — «Аліас+».

Що ж таке Аліас+

Головна.

Перед початком гри треба вибрати назви команд — тут вони називаються підрозділами — і обрати тематики зі специфічними для родів військ словами. Але тематика — не обов’язково рід військ. Нею може бути і напрям, як, наприклад, «Історія»: єдина наразі платна тема за $0,99.

Далі пресет параметрів гри — Швидкий, Стандартний, Довгий. Кожен пресет це набір налаштувань, які впливають на гру:

  • тривалість раунду;
  • скільки очок треба сумарно набрати для завершення гри;
  • стоп-слова — на картку додаються слова, які теж не можна використовувати для пояснення, як і однокореневі;
  • «догана» — за пропуск слова знімається бал;
  • останнє слово для всіх;
  • складність;
  • теги — сленг, абревіатури.

Також є особистий словник, адже майже в кожному підрозділі є свій локальний сленг, який хлопці і дівчата зможуть використати для гри.

Лишилось обрати режим гри. Їх два: кімната — по Bluetooth чи Wi-Fi, або класика — передача одного телефону з рук у руки. Всупереч моїм очікуванням, люди частіше грають у класичний режим, хоч мені і здавалось, що кожному буде зручніше використовувати особистий телефон. І це те місце, де можна було зекономити купу токенів і часу, адже на «кімнати» пішла третина кодової бази — 31% рядків і 63 коміти, більше, ніж на будь-яку іншу частину проєкту. Хороший урок: така собі оверінноваційність виявилась потрібною тільки мені, а те, як грати в Аліас, уже закладено в людський геном — просто передай телефон.

Ну і вперед, пояснюй слово яке бачиш, не використовуючи це саме слово, однокореневі та заборонені!

У мене, до речі, оптоволокно завжди асоціювалось з цією лампою:

А у вас?)

Тринадцять днів і в реліз

4 липня, 20:51 — сів за проєкт. Flutter уперше в житті: раніше я цього ніколи не робив.

Мій попередній застосунок на мобілки — Memessage — це дві окремі нативні бази, на iOS та Android, і ця складність була виправдана тим, що мені треба було змальовувати анімацію з екрана, а на Flutter це неможливо (за «неможливо» в ІТ прийнято кидати помідори — можете це робити). На Memessage для обох платформ з набиванням шишок пішло десь пів року, але найцінніше, що я звідти виніс, — розуміння мультиагентності і особистий скіл architect.

Скіл architect

Скіл architect я написав давно, і він постійно модернізується синхронно з моїм розвитком і розумінням того, як створювати продукти і робити це швидко. Адже моя нетерплячість нікуди не ділась: проєкт будь-якої складності я хочу закінчити вже сьогодні ввечері — попри те, що вже вечір і вільного часу після служби в мене не нескінченна кількість.

Тому architect вміє брейнштормити і збирати докупи те, що я хочу реалізувати. Потім ми створюємо бриф проєкту, де обираємо стек технологій та архітектуру, а також те, яким чином перевірятимемо якість коду. Далі я запускаю скіл architect з посиланням на бриф, і він створює такий собі роадмап специфікацій.

На початку це ще не специфікації, а просто папки, в кожній з яких — промпт-завдання на розробку специфікації, розбитої на фази. Це робиться для того, щоб специфікації кожної фази писав окремий агент, а не одинак, який потоне в контексті і зробить спеки нечіткими. Також у скіла є застереження — жодного реального коду в спеках. Без цього агенти починають реалізовувати проєкт прямо в md-файлах. Це як мінімум подвійна робота.

Батіг

Далі, перед початком виконання, я роблю найважливіше — батіг.

Агент, який упирається в перешкоду, шукає, як її обійти. Ну бо це агент — йому загалом треба «задачу виконано», а не «задачу виконано правильно». Заблокував лінтер — він спробує // ignore. Впав тест — додасть skip. Не пускає хук — намагатиметься прошмигнути з --no-verify.

Робимо git commit:

  1. Формат. dart format на застейджених файлах. Не відформатовано — до побачення.
  2. Аналізатор. dart analyze --fatal-infos --fatal-warnings — будь-яка підказка рівня info, і ми позбавляємо агента кишенькових токенів.
  3. Секрети. gitleaks проходить по діфу. Ключ у коді — розстріл.
  4. Заглушки. Скрипт шукає в нових рядках // ignore:, @Skip, skip:, exclude-tags, dependency_overrides: і послаблення конфігу лінтера. Знайшов — погрожую, що поставлю його під керівництво агента Gemini.
  5. Захищені файли. Якщо в коміті є Makefile, lefthook.yml, конфіг лінтера, скрипти якості чи воркфлоу — падаємо, якщо немає свіжого дозволу.
  6. Цілісність тестів. Застейджений *_test.dart без жодного expect( — стоп. Нова тавтологія expect(x, x) — давай по новій, Міша.
  7. Дзеркало. Додав файл у lib/features/room/ — має існувати test/features/room/. Немає — роби.

Робимо git push:

  1. Тести і покриття. Ганяються всі тести і рахується покриття. Менше 90% — донт пуш зе хорсес.
  2. Покриття діфа. Окремо перевіряється покриття тих рядків, які змінила саме ця гілка: там теж має бути не менше 90%. Це важливіше за перше — покриття по всьому проєкту це повільна середня, вона не помітить, як фіча додала сотню непокритих рядків.
  3. Вразливі залежності. Сканер проходить по lock-файлу і звіряє кожну версію з базою відомих вразливостей.
  4. Дублювання. Копіпасту ловить детектор — не більш як 5%.

На сервері, а він у нас є, — те саме, але послідовно, зі стопом на першій помилці: зібрати адмінку (лінт + типи + тести + білд) → підняти Postgres і прогнати тести з тим самим порогом 90% → покриття діфа → аудит залежностей. Ті самі гейти проганяє CI на кожному пуші в main.

Guard

Як ми вже всі знаємо — агенти ліниві. Вони обов’язково будуть намагатися зробити все аби-як, головне щоб працювало. Вони будуть робити усе, аби задача, яку вони виконують, не потягнула за собою ще якусь. Знаєте оце їх «ой, тут купа помилок, але це не я зробив»? Тому всі можливі варіанти обходу вони знайдуть і використають — і тому батіг має бути якісним.

У Claude Code є хуки на рівні самого інструмента. Один із них — PreToolUse. У мене є скрипт scripts/quality/claude-guard.sh, підключений у .claude/settings.json.

Що ріже: --no-verify, git commit -n, LEFTHOOK=0, LEFTHOOK_EXCLUDE=, префікс SKIP=, зміну core.hooksPath, rm .git/hooks, lefthook uninstall.

Вночі — мутанти

Про важливість тестів я знав ще до використання агентів, але лінь агентів завжди проходить червоною ниткою по всіх етапах розробки. Саме тому 90-відсоткове покриття для агента — така сама вимога, як і покриття голови перед походом у церкву: треба? — буде.

Бо покриття показує тільки те, які рядки коду виконались під час тестів. Воно не показує, чи тест хоч щось перевіряє. Імовірно, 90% з тих 90% тестів, які написав агент, позеленіють, навіть якщо видалити 100% коду.

Мутаційне тестування б’є саме туди: береш робочий код і ламаєш у ньому одну дрібницю — міняєш > на >=, + на -, викидаєш рядок. Зіпсована копія — мутант. Далі ганяєш тести. Хоч один упав — мутанта вбито, тести справді щось стережуть. Усі зелені — мутант вижив: код зламано, а ніхто не помітив.

Виконання

Все, запускаємо виконання спек і 13 днів чекаємо посилання на застосунок в App Store.

Жарт, але ця дорога у мене накатана. Я запускаю агента зі скілом architect і посиланням на специфікації, який знає, як ці спеки виконувати. Fable 5 у мене збирав команди агентів, розкидав зони відповідальності і на початку розрулював точки їх перетину. Opus — як виконавці.

Дехто з вас може подумати, що Fable 5 тут оверкіл і я забиваю цвяхи мікроскопом. Частково матимете рацію — особливо тепер, коли вийшов Opus 5 і в деяких задачах перевершив свого старшого брата, якщо вірити бенчмаркам. Однак де Fable 5 дійсно сильний, так це в мультиагентності. Він неперевершено керує агентами.

Так, мені довелось пересісти на підписку за $250, тому що половина лімітів згорала просто від того, що я ввів команду /model Fable. Але воно було того варте.

Паралельно я розробляв і сервер: він і джерело «паків» зі словами та тегами, і генератор цих слів, і стор-скрін-генератор, і навіть диригент публікацій в обидва стори. Я і так затягую обсяг, тому скріни покажу трохи далі.

Все встало на потік: ніч — для генерації кодової бази фіч і мутацій, день і вечір, коли є час, — фікс багів і корективи.

17 липня — реліз в App Store. 13 днів від першого коміту.

27 липня — Google Play. Плюс 10 днів через closed testing: 12 тестувальників × 14 днів. Цього разу страждань при публікації було менше, адже у мене вже була база ЦА з проєкту zgidnotranslate.com — розсилка туди і пост у Threads залучили 115 тестерів.

Адмінка

Тут коротко. Я швидко прийшов до ідеї, що ніякого рев’ю для наповнення моїх застосунків контентом я чекати не хочу. Керувати публікацією і наповненням сторів в їхніх безкінечних інтерфейсах теж не хочу. Тому — адмінка.

Тут я додаю слова:

Так віддаю паки зі словами та мета-інформацією:

Тут роблю скріни для сторів:

Гроші

Ось такий прайс:

PRO купується один раз і дає доступ до словника, можна лишити чайові, також будуть платні теми — наразі вона одна. Реклама закладалась на початку, але поки я вирішив відмовитись від неї. Це не глобальний продукт, і він, можна сказати, нішевий, тож з реклами багато не заробиш. Та й не люблю я рекламу як користувач.

Якщо говорити про Аліас+, то ось уся його економіка станом на 8 серпня — це три тижні в App Store:

  • 8 880 разів картку застосунку показали в сторі
  • 1 610 разів із них відкрили сторінку застосунку
  • 717 людей встановили
  • 7 покупок
  • $11 дійшло до мене після комісії Apple

Конверсія з показу в завантаження — 12,4%. Це, як не дивно, добра цифра: медіана по стору десь 3–6%. Тобто іконка, назва і скріншоти працюють, і стор-скрін-генератор в адмінці себе відбив. А от конверсія з завантаження в покупку — рівно 1%. Причому платять одразу: на перший день 0,7%, за тиждень 0,9%. Хто не купив у перші дні — не купить уже ніколи: навряд чи такі люди зайдуть повторно, адже показник Average Retention дуже низький. Але це рівно настільки ж драматично, наскільки й очікувано. Коли ви востаннє грали в Аліас?

Це гра для вечірок, а вечіркам моєї ЦА часто заважають КАБи. Але водночас я радий, що у них тепер є згідно-відповідний Аліас+ для того нечастого збігу обставин, коли про нього згадають у компанії. Я і сам з нетерпінням чекаю тих часів, коли усі ці слова стануть неактуальними і ми всі будемо грати в «Нормальний Аліас» (це реальна назва крутого українського аліасу з цивільними словами, якщо ви не моя ЦА).

Навіщо це все і чи були сумніви щодо 347-го Аліаса в сторах

Я сумніваюсь завжди — саме тому цвинтар моїх проєктів може потягатись з гуглівським. Але щодо Аліас+ сумнівів було мало.

Мені неважливо, скільки грошей я на цьому зароблю. Це моє хобі, а хобі рідко приносить гроші, ба більше, зазвичай їх забирає. Я готовий за це платити. За всі мої проєкти разом в App Store у мене нещасних $50,48 — і тих ще не виплатили. Але я обов’язково заплачу (наголос на «у») за акаунт розробника в жовтні, оплачу Claude ще на місяць, закину на VPS і продовжу домени зі свого грошового забезпечення — та й далі буду весь вільний час лупати в монітор, пірнаючи все глибше в прірву технологій, які б я нізащо не вивчив за життя.

А тепер про витрати. Claude за весь час — $1 203. VPS, хостинг і домени — 20 тисяч гривень. Акаунт розробника Apple — $99 на рік, Google Play — $25 разово. Виходить під дві тисячі доларів, і це за всі проєкти, не тільки за Аліас+. Проти $50,48, з яких $11 за Аліас+.

Усі застосунки, які я пишу, потрібні насамперед мені. Ну, один — моїй колишній дівчині. Якщо комусь ще це цікаво — я радий. Якщо проєкт відправився на цвинтар — що ж, зате я помацав Kubernetes.

P.S. Я свідомо залишив прірву між «зміг написати перший скрипт на 20 рядків коду» і «купою проєктів з Claude Code», аби мати змогу розповідати про них окремо, розширюючи цю статтю і посилаючись на неї. Зокрема, хочу в майбутньому розповісти і про Memessage, який створює анімацію процесу листування, що справді звучить складно, і про zgidnotranslate.com — проєкт, який був написаний за вечір як прикол, а зараз має 5 тисяч зареєстрованих користувачів. Якщо вам буде цікаво.

👍ПодобаєтьсяСподобалось16
До обраногоВ обраному2
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Напевно, одна з найкращих статей, які я читав в цьому році. Успіхів!

Денисе, дуже дякую за таку високу і неочікувану оцінку!)

«Догана, б***ь» — ті найпопулярніші два слова які залишаться з тобою в пам’яті назавжди (зірочки я не ставлю давно вже, то доу займається самоцензурою)

Розсилка доу:
Олексій ніколи не працював розробником, але зібрав на Flutter військовий «Аліас+» за 13 днів та випустив його в App Store.

Пост:
Мій попередній застосунок на мобілки — Memessage — це дві окремі нативні бази, на iOS та Android, і ця складність була виправдана тим, що мені треба було змальовувати анімацію з екрана.

Олексій ніколи не працював розробником, але зібрав на Flutter військовий «Аліас+» за 13 днів та випустив його в App Store.

Так а в чому питання? Якщо ви прочитаєте трошки ще, то зможете побачити на початку статті такий текст:

Програмування ніколи не було моєю роботою, але завжди було моїм хобі

Можливо я якийсь не такий, але для мене це грубий клікбейт, судячи з опису я гадав що тут буде історія с нуля до апстору за 13 днів, у чувака тут знать я б їбав.

Так, але я не працював розробником)

Memessage, доречі, був першою апкою. На ньому я десь пів року гулі і набивав, зокрема на IOS, бо на Android був більше формат портування.

сама стаття доволі цікава доречі, агентний флоу зокрема

Клас, гарна історія, подякував!

Дуже дякую за відгук, Денисе!

Рекомендую книгу «The mom test»

Дякую за рекомендацію, Денисе!)

Підписатись на коментарі