За семь лет в IT я повидал многое: и большие задачи, и экстренные багфиксы ночью, и не совсем понятные требования от бизнеса, но всегда это были готовые проекты с уже выстроенной архитектурой, где знаешь, что и как работает. Год назад, в конце августа, ко мне пришел знакомый и сказал примерно следующее: у меня есть команда, мы занимаемся P2P платежами, сейчас работаем с одной известной площадкой, но хотим сделать свой продукт, можешь с этим помочь?
Экспертизы в сфере P2P платежек у меня не было, поэтому первоначально пошел гуглить, что это вообще такое, где и как работает. После изучил схему, которую он мне прислал. В голове обрисовалась картинка как это можнно реализовать на практике, я ему рассказал свои мысли, сильные и слабые (на мой взгляд) стороны его идеи. После чего он выдал: а сделать сможешь? Деньги на реализацию есть, ТЗ — напишу, всё как полагается.
Опыт создания проектов с нуля у меня практически нулевой. Конечно на работе я занимался и настройкой деплоя, и созданием новых сервисов, но чтобы и разработать, и задеплоить, и потом еще работоспособность поддерживать - такого еще не было. Внутри мелькнула мысль: это же новый уровень, вполне рабочий вызов. Чтож, пора попробовать. Что из этого вышло - под кат
Начало работы
Через 2 недели после нашего первого разговора мне было предоставлено ТЗ. Мы созвонились со всей командой, чтобы удостовериться, что мы понимаем друг друга, обсудили детали и выделали основные элементы:
ЛК для трейдеров и мерчантов
Админка для управления и первыми и вторыми
Работа с криптовалютой для автоматического пополнения и вывода средств на платформе
Алгоритм подбора реквизитов для оплаты
Мобильное приложение для оперативного реагирования на заявки, а так же парсинга СМС для автоматического их подтверждения
Также было отмечено, что конкуренты могут досить нашу систему, поэтому нужно от этого уметь защищаться.
После того, как обговорили требования я прикинул архитектуру проекта, стэк, на котором буду разрабатывать. Я сразу спросил какой планируется объем трафика на этапе запуска, а так же через 3-6 месяцев, ребята сказали, что хайлоада не будет. Исходя из требований я оценил, что мой типичный стэк Ruby on Rails + Sidekiq + Postgresql отлично справятся с задачей.
Следующий вопрос - это на чем писать фронт. Мне показалось, что проект достаточно интерактивный, курсы валют должны обновляться достаточно часто, а вместе с ними идет пересчет стоимости заявок, чтобы трейдер видел актуальную сумму в криптовалюте и мог решать брать ему заявку или нет. Выбор был между привычным мне Vue.js и новым фреймворком в мире Rails - Hotwire. Если с vue я был знаком и он не казался мне чем-то страшным (даже учитывая, что я вообще не фронтенд разраб), то hotwire одновременно подкупал своей идеологией того, что все можно рендерить на бэке и любые изменения отправлять по вебсокетам, забыв о сложном JS на фронте, но, с другой стороны, я понимал, что могут возникнуть какие-нибудь неочевидные для меня проблемы и на их решение я буду тратить слишком много времени, поэтому выбор пал в пользу Vue.js.
Следующий вопрос, на котором я заострил внимание - это мобильное приложение. Я сразу озвучил, что я не мобильный разработчик и что для этого придется найти другого человека, на что ребята согласились. Но затем взглянув на требования к нему, я понял, что 99% функционала мобильного приложения можно уместить в обычный телеграм бот. В него я буду отправлять уведомления о новых заявках, о том, что заявка оплачена и т.д. и если в бот добавить пару кнопок - получится полноценное приложение. Только стоить это будет дешевле, и разработка будет быстрее. Единственный нюанс, который нужно было продумать: парсинг СМС. Но и тут нашлось решение - Macrodroid. Он может реагировать на различные тригеры в системе, один из которых СМС, и выполнять различные действия. Для проверки гипотезы мы настроили макродроид на прием СМС и отправку текста на сервер через колбэк - и все получилось. Решили сделать разбор сообщения на сервере, к тому же шаблоны можно будет настраивать прямо в админке, что так же прибавляет в оперативности внесения правок.
Я озвучил срок реализации в 4-5 месяцев, назвал стоимость. Все были довольны и разработка началась.
Старт разработки
Разработку я начал с простых вещей: регистрация, авторизация, CRUD для основных сущностей в системе. Особый интерес для меня представляли работа с блокчейном, криптовалютами, и телеграм ботом. Самой сложной задачей для меня была работа с заявками - ее я оставил на потом. С некоторыми вещами провозился гораздо дольше, чем планировал.
Основная сложность конкретно для меня - это фронтенд. Напомню, у меня уже есть небольшой опыт работы с vue.js поэтому я решил использовать его в качестве фронта. Сначала я пытался с нуля поднять фронт, подклчить нужный UI-кит, настроить линты, сборку и прочие прелести. Но, т.к. опыта мало, получалось у меня это крайне плохо, поэтому по итогу я решил взять готовый шаблон админки Vuestic Admin. Там уже все было настроено - бери и делай. Это сэкономило мне время и дальше разработка пошла как по маслу.
После появления первых нескольких страниц я приступил к настройке деплоя приложение на тестовый сервер. Всю инфраструктуру описывал через Ansible. В целом первый выкат на тестовый стейдж у меня случился примерно через месяц-полтора, показывать там было особо нечего, но то, что оно работает - уже хорошо.
Сразу же прикрутил к серверу средства мониторинга, чтобы потом, на проде, с этим было проще. У меня большой опыт с InfluxDB + Grafana, поэтому первым делом я взялся поднимать именно эту связку. Завез telegraf, influxdb, начал настраивать дашборды в графане. Поскольку раньше я все запросы писал на InfluxQL, а сейчас в ходу новый Flux, мне было крайне сложно в нем разобраться, все казалось таким нелогичным. Несколько раз начинал все с нуля, но по итогу удалось настроить все нужные мне графики.
Первые трудности
По началу, разработка шла довольно-таки неплохо, я делал задачи одну за другой, иногда что-то вызывало проблемы, но они решались. Весь прогресс я старался заливать на тестовый сервер и показывать заказчику результат. В основном демонстрировал UI, т.к. некоторые вещи по ходу работы я переделал в более удобном, как мне кажется, виде. Процесс тестирования мы решили отложить на потом, когда все уже будет готово.
На изучение блокчейна Ethereum + разобраться как генерировать кошельки, отправлять/принимать USDT именно в автоматическом режиме у меня ушло довольно-таки много времени, потому что информации в сети хоть и много, но она мало относилась к ruby. Сначала пытался адаптировать код с других языков на ruby, а потом просто плюнул на это дело и завез в проект пару скриптов на питоне, это было кратно проще, чем пытаться подключить библиотеки, которые были написаны 10 лет назад и давно никем не поддерживались.
Также были нюансы с выплатами. Для того, чтобы отправить средства с одного USDT кошелька на другой, нужно хранить приватный ключ где-то в базе данных. Это создавало риски в случае взлома системы остаться без денег и возмещать убытки из своего кармана. Прикинув, как часто будет производится выплата, мы решили, что можем проводить ее в ручном режиме, нигде не сохраняя приватные ключи от сгенерированных кошельков.
Самое сложное началось когда начал объединять разные блоки приложения между собой. По началу предоставленное ТЗ мне казалось очень логичным и удобным. Оно было в формате страниц с расписанными элементами на них, что за что отвечает и какая кнопка что делает. Выглядело это примерно так
По такому ТЗ удобно делать UI, однако оно совсем не отражает взаимодействия между разными модулями приложения. У меня было 3 разных ЛК (трейдер, мерчант и админ) и описаны они были в разных частях ТЗ. К примеру, вот есть страница в ЛК трейдера с реквизитами. Он их может создавать, удалять, редактировать и т.д. Есть описание алгоритма подбора реквизитов, в котором описано по каким критериям подбираются реквизиты. Это понятно, окей. Но еще есть нюанс, что, если не удалось произвести оплату по этому реквизиту N раз его нужно блокировать. Где мы это напишем? Верно - в админке, на странице настроек, между полями "Телеграм для уведомлений" и "Backend host", что вообще не очевидно. Таким образом, чтобы сделать какой-то законченный блок приходилось просматривать все ТЗ и искать любое упоминание нужного мне функционала. Если все равно было что-то непонятно нужно было состыковать время, чтобы созвониться и выяснить все детали. А пока деталей нету - беремся за другой функционал. Эти переключения контекста все чаще увеличивали время работы. Я думал, что за один вечер сделаю какой-нибудь законченный блок, но оказывалось, что из-за недостатка информации его сделать не получится и нужно делать другой. И хорошо если в другом все понятно.
Еще немаловажный фактор это то, что помимо этого проекта у меня есть основная работа. Долгое время работы по вечерам очень сказывается на самочувствии, я уже начал чувствовать усталость, и мой энтузиазм потихоньку начал угасать. Я старался делать один выходной в неделю, чтобы вообще не писать код, но иногда, когда появлялось вдохновение, я писал код 7 дней в неделю. Чем дольше живешь в таком режиме - тем менее продуктивным становишься.
Тестирование и обратная связь
Через 4 месяца, когда ядро проекта было готово, настало время тестирования. Изначально мы хотели привлечь тестировщика, но по опыту разработки решили, что будет быстрее, если заказчик сам будет тестировать всю систему.
Конечно, я не надеялся, что весь функционал будет работать идеально с первого раза, поэтому приготовился фиксить баги. Помимо ошибок в коде были косяки из-за того, что я неправильно понял задачу. Мне казалось, что оно должно работать одним образом, а работать оно должно совсем не так. Где-то были мои недочеты с невнимательным прочтением ТЗ, а где-то откровенно двусмысленные формулировки (хотя на этапе работы мне казалось что там все предельно очевидно). Было даже такое, что сегодня мы добавляли на форму кнопку, через 2 дня думали, что все-таки она не нужна, а через неделю добавляли снова.
Изначально я покрывал весь функционал юнит тестами, но на этом этапе я уже думал зачем дописывать тест на этот узкий кейс сегодня, если завтра может оказаться, что работать он должен по-другому. Конечно, я продолжал покрывать тестами критические моменты, но со временем я делал это все реже.
Тестирование у нас было примерно в таком темпе: в выходные ребята на весь день погружались в протыкивание системы, находили баги, записывали это в гугл документ, а на неделе я эти баги правил. И так раз за разом. Иногда подбешивало, что разные баги находятся в одних и тех же местах, и почему нельзя было увидеть его в прошлый раз, я бы все разом поправил, а не переписывал один кусок кода дважды. Внезапно мы вдруг поняли, что будет гораздо продуктивнее, если заказчик составит чек-листы, по которым я буду сверяться и, в случае чего, вносить правки. Мы постарались составить чек-листы не только на баги, но и на всю платформу.
Также во время тестирования появлялось понимание, что чего-то не хватает, где-то нужно дополнительное поле вывести, где-то убрать. В качестве примера: в ТЗ были предусмотрены базовые отчеты о результатах работы платформы, но после теста стало понятно, что эта информация совсем не дает понимания о том, сколько платформа реально заработала за месяц. Пришлось доделывать. Не то чтобы это сложно, но в режиме постоянных правок любые доработки вызывали только негативные эмоции и отторжение.
Выгорание
К этому моменту разработка уже велась на протяжении полугода, я уже почувствовал, что начал выгорать. Все чаще я уделял проекту меньше времени, вместо вечера плодотворной работы я мог написать пару строчек и уйти заниматься своими делами. Было время, когда я не притрагивался к проекту неделю. Также на меня давили и некоторые личные факторы, все вкупе опускало мое настроение на дно, казалось, что я так долго разрабатываю этот проект, но конца все еще не видно.
Помимо админки и ЛК нужно было еще сделать 2 страницы для оплаты. А это чистый фронт, с ним у меня были большие проблемы, потому что ни дизайна, ни верстки не было, были лишь макеты как это должно выглядеть.
Шли дни, недели, а проект так и оставался в том же состоянии, что и был. И я подумал: нужно либо доделывать проект до конца, либо не делать вовсе, потому что тянуть уже невозможно. В марте я озвучил ребятам свое желание бросить разработку, вернуть аванс и разойтись. Признал, что подвел их и проект до конца не доведу. Ожидал кучу хейта в свой адрес, об упущенном времени, о неоправданном доверии и т.д. НО! в ответ на это я получил огромную поддержку в свой адрес. Для меня это было очень неожиданно, парни были довольны проделанной работой, сказали, что сами не ожидали сколько нюансов и деталей вылезет по ходу разработки, согласились ждать дальше, сами предложили мне взять перерыв длинною в месяц и съездить в отпуск. С одной стороны, я был очень рад, что они меня поддержали, но с другой - думал, что все таки придется закончить проект, а так не хотелось ?
Восстановление
Я съездил в Таиланд, занимался тайским боксом, плавал в море, загорал на пляже, в общем, удалось перезагрузиться. По возвращении я был готов продолжать.
Мы наняли фронтенд-разработчика на фрилансе, за неделю он склепал нам весь необходимый UI для оплаты, с меня было только API.
Спустя 3 недели мы были готовы к релизу. Я развернул сервер для продакшена, настроил домен, Cloudflare, SSL сертификат, подключил сбор метрик о состоянии сервера и приложения, настроил бэкапы и остался финальный штрих - нагрузочное тестирование. Для нагрузочного теста я использовал Locust. Результаты теста оказались удовлетворительными, каких-то затыков не обнаружено, все работает стабильно. Было, правда, пару мелких багов, но они были быстро исправлены. Это, кстати, тоже хорошо, потому что обнаружить их при ручном тестировании было крайне проблематично, а на проде они бы вылезли 100%. Поэтому, я считаю, нагрузочное тестирование это must have перед запуском любого проекта.
Финал
Мы запустились в мае. Пришли первые пользователи. Снова начался процесс фикса багов и доработок. Но к этому я уже относился по-другому. Проект работает, мы получали фидбэк от реальных пользователей системы, и это давало мотивацию. Через 3 месяца после запуска проект принес первую ощутимую прибыль. Серьезных багов не нашли, из необычного: мы сталкивались с непонятной блокировкой домена, проблемами с сервером и сетью по вине провайдера, с непонятными багами на мобильной версии сайта, а также странными затупами при загрузке проекта через мобильный интернет. Но решать эти проблемы было даже интересно.
Итоги
Этот проект дал мне колоссальный опыт не только в разработке, но и в проектировании систем, планировании времени и общении с заказчиком. Было очень круто запускать проект с нуля, настраивать сервер, деплой, смотреть на метрики и видеть, что все работает как надо. Основные выводы, которые я для себя сделал следующие:
Не приступать к разработке, пока досконально не разобрался, что нужно получить в итоге. Обычно на работе я сталкиваюсь с небольшими задачами, до нескольких дней разработки. И в большинстве случаев я сразу вижу и объем работы, и на что они влияют, и что потребуется сделать. Однако, когда начинаешь разрабатывать проект с нуля это не так. Подход "по ходу разберемся" работает не всегда.
Начинать разработку нужно с кор-функционала. Думаю, каждому разработчику хочется пробовать новые штуки, с которыми раньше не работал. Это абсолютно нормальное и понятное желание, однако нужно уметь с ним бороться, потому, что разрабатываемый проект - это не игрушка (если, конечно, это не ваш пет-проект) где можно применить 100500 новомодных инструментов, а в первую очередь это решение конкретной проблемы заказчика.
Как можно раньше отдавать проект на тестирование, а не ждать когда все будет готово. Этот пункт вытекает из предыдущего. Чем раньше будут выявлены непонятные моменты - тем дешевле будет это все исправить
Казалось бы, всем известные правила, написанные в любой книжке по управлению проектами, однако, пока сам не попробуешь - не прислушаешься :)
Комментарии (6)
Daddy_Cool
09.11.2024 20:15Нехило! Если можно несколько вопросов.
1. Интересно, насколько этот проект оказался успешен как бизнес-проект для заказчика?
2. По опыту написания таких... развесистых приложений, начиная с какого-то момента трудно удержать всё голове. И мерзкие обратные связи... Т.е. когда обнаруживаешь, что для изменения чего-то в мелкой дальней функции надо создать что-то новое в основной части.
Вот здесь описаны страдания товарища в связи с этим. Было ли что-то такое?
https://qna.habr.com/q/1747153. "Я съездил в Таиланд, занимался тайским боксом, плавал в море, загорал на пляже, в общем, удалось перезагрузиться. По возвращении я был готов продолжать".
А не было такого, что "Ой блин, опять это... а в Тае так было хорошо?" )))motoroller95 Автор
09.11.2024 20:15за время разработки бизнес сильно поменялся. конечно, обороты не те, что планировались на старте, но число с тремя нулями на комиссии проект приносит ежемесячно.
Это интересный вопрос, думал только у меня появлялись такие мысли) В целом, могу сказать, что даже сейчас считаю этот проект не большим. Основные моменты и бизнес-логику я помню даже спустя 3 месяца как вообще не смотрел в код. НО! после того, как начались массовые переделки я начал замечать что все больше упускаю из виду какие-то нюансы. То в одном месте коэффициент пересчитать забыл, то в другом сумму заявки не приплюсовал и т.д. Поэтому думаю, что этот проект считается мелким и контекст в голове удержать реально. Озвученная проблема начинается со средних проектов, где разных переплетеных доменов >3
ну, кстати, нет. я же еще и на основной работе отпуск взял, поэтому после отдыха мне было прям норм. к тому же большой геморрой для меня в виде фронта отвалился, доделать бэк было не так страшно
Daddy_Cool
09.11.2024 20:15Спасибо! Возможно такая проблема есть у всех, только мало кто говорит.
Хотя... один мой друг написал шахматный движок. Через два года я указал ему на ошибку во внедренных правилах и он её исправил буквально за 15 минут - в процессе моей игры в шахматы.
saratoga8
09.11.2024 20:15Спасибо за интересную статью
Советую использовать для проектирования проектов методологию BDD и Impact Mapping
они облегчают понимание целей проекта
ninJo
Молодец чеполодец!;