5 вещей, которые я бы хотел знать до начала разработки биржи

«Скажи мне — и я забуду, покажи мне — и я запомню, дай мне сделать — и я пойму».

В закладки

Когда я со своим котом начинал разработку движка биржи, именно эта цитата Конфуция звучала в моей голове. Мы были сплоченной и мотивированной на результат командой. Интерес и готовность преодолевать трудности, возникающие на пути к MVP, — вот как можно было описать наше состояние. Вызовы и открытия, возникшие в процессе разработки, определенно внесли свои коррективы и стоили затраченного времени. Об основных из них, а также об итогах эксперимента, я и хочу поведать сегодня.

Для нетерпеливых — вот ссылка на демо версию биржи. Также можно запустить демо на своих машинах.

Самый большой вызов этого проекта состоял в ограниченности ресурсов. Наверняка если бы это ограничение не стояло так остро, список выглядел бы иначе. Возможно, для кого-то этот список будет банальностью, но любой вопрос можно воспринимать по разному: пропасть между “услышал о проблеме”, “понял ее” и “осознал” довольно велика.

Список того, что я осознал при разработке проекта:

  1. Довести проект до MVP сложнее, чем начать его.

    Когда работаешь над проектом один, тем более только в свободное время, очень легко отклониться от намеченных сроков. В разработке пришлось сделать полугодовую паузу из-за возросшей основной рабочей нагрузки и семейных дел.

    Реализация проекта была разделена на 2 временных отрезка: март-апрель 2019 и ноябрь-декабрь 2019. В ноябре я не был уверен, что доведу проект до MVP. Но так как уже были готовы все внутренние интерфейсы, система хранения, процессинг ордеров и оставалось только создать интерфейсы пользователей, я решил продолжить.

    Как итог, я понял, что лучше не приостанавливать проект, так как теряется исходная мотивация и происходит переключение внимания. Чтобы продолжить работу, пришлось приложить некоторые усилия чтобы найти время для завершения проекта.

  2. Маркетинг бывает разным.

    Этот пункт я включил после анализа и выбора стека для фронтенда. Разнообразие библиотек и фреймворков поражает, а скорость изменений их API вообще иногда вводит в ступор.

    Хайп — это не всегда хорошо, так как размер сообщества вокруг проекта часто не коррелирует с качеством решения.

    Если проект/решение/технология позиционирует себя, как лучшее решение, а в описании многое объясняется “магией”, лучше избегать их применения. Это сохранит ваше время в будущем.

  3. Никогда не знаешь, с какой проблемой или недоработкой в стороннем ПО столкнешься.

    Даже проверенные решения иногда подводят. Редко, но все же случается ситуация, когда инструмент, который используешь довольно продолжительное время, начинает вести себя себя не так, как ожидаешь.

    Во время проекта у меня было несколько ситуаций, когда я удивлялся. Это были Timescale и его time_bucket не поддерживающий большие интервалы; Tarantool и вопросы, связанные с репликацией, а также ручным управлением транзакциями; Rustler, который стал копировать больше данных при вызове функций... Этот список можно продолжать, но главное и самое ценное — в мире открытого программного обеспечения всегда можно исправить проблему, либо же, исследовав исходный код приложения, понять, как ее обойти.

    Из-за ограниченности ресурсов приходится тщательно планировать объем работ. Но в случае возникновения незапланированных трудностей, любые и мелкие и крупные проблемы приходится решать самому. Их просто некому делегировать.

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

  4. Когда взгляд замыливается, это влияет на принятие решений.

    В обычных условиях коммерческой разработки мы коммуницируем с другими людьми. Любой проект — люди, создающие и использующие его. В процессе разработки мы постоянно получаем новую информацию от других участников и дополняем свое видение вопроса.

    Принятие любого технически сложного решения — процесс непростой. Когда вы погружены в проблему и проводите часы, а иногда и дни, обдумывая пути решения, ваш взгляд замыливается.

    Я осознал, насколько важно и ценно работать над проектом в команде. Возможность посовещаться с коллегой, который в теме, но не работает над этой же задачей и может критически оценить ваш подход и решение, сохранит время и снизит вероятность ошибок.

  5. Кота сложно научить программировать (для тех кто хочет повторить эксперимент).

    Несмотря на то, что мой четырехлапый друг демонстрировал неподдельный интерес к проекту, это не мешало ему постоянно отвлекаться и всячески лениться. Уже после пары недель, я понял, что программистом ему не стать. Однако нельзя недооценить его навыки командной игры. В итоге в зону его ответственности перешли вопросы поддержания командного духа, с которыми, надо признать, он справился на отлично.

​Кот Максим Молчанов​

Итоги эксперимента

В начале эксперимента я поставил 2 основных задачи:

  • углубление собственных знаний и прокачка экспертизы;
  • исследование применимости функциональных языков и проектов с открытым исходным кодом при разработке торговых систем.

За время эксперимента я определенно систематизировал и углубил свои знания предметной области и даже попытался поделиться ими с сообществом (ссылки на предыдущие скучные теоретические статьи можно найти в моем профиле). Поэтому данный пункт считаю успешно выполненным.

Что касается функционального программирования.... Опять же, я смотрю через призму Erlang/OTP. Erlang как язык и OTP как фреймворк определенно подходят для промышленного программирования и реализации финансовых систем. Экосистема зрелая, а минимальный синтаксический базис языка, иммутабельность и подходы, заложенные в OTP, позволяют быстро реализовывать масштабируемые распределенные и при этом надежные системы. К сожалению я не вел журнал затраченного времени, но вся разработка заняла 4 неполных месяца в свободное время после основной работы. При этом в проекте более 200 интеграционных тестов.

Но и ложка дегтя в бочке меда все же есть. Erlang по производительности очень похож на Python. В отличии от последнего, на нем легко писать высококонкурентные системы с настраиваемым уровнем параллельности. Кроме того, эти системы довольно легко масштабировать и разносить компоненты в рамках кластера. Эти системы в результате получаются хоть и емкими, но не сверхбыстрыми.

Исходя из последнего вывода, я понял, что наиболее эффективным и производительным подходом будет не разнесение обработчиков рынков и аккаунтов клиентов по разным машинам в рамках кластера, а обработка всех рынков и аккаунтов в рамках одной машины с репликацией данных для обеспечения надежности.

Из-за недостаточной производительности Erlang, обработку рынков стоить делать на более низкоуровневых языках без GC и справедливых планировщиков. В текущей реализации я уже вынес часть функционала в NIF на Rust.

Таким образом, благодаря оптимизированной работе с сетью и бинарными структурами, Erlang прекрасно решает вопросы организации надежной и быстрой распределенной платформы. А вот вопрос работы с ордерами и аккаунтами лучше реализовать на Rust/C/C++ (добавлять по вкусу).

Еще одним немаловажным моментом является выбор языка для фронтенда. По старой привычке я отдал предпочтение Vue + Js. Но если бы я выбирал стек сейчас, то выбрал бы Vue + Typescript. Более строгая типизация позволила бы ускорить разработку.

Спасибо всем, кто следил за развитием эксперимента. Надеюсь вам было не очень скучно! Не прощаемся! :)

Возможно будет интересно:

Материал опубликован пользователем.
Нажмите кнопку «Написать», чтобы поделиться мнением или рассказать о своём проекте.

Написать
{ "author_name": "Maxim Molchanov", "author_type": "self", "tags": [], "comments": 9, "likes": 0, "favorites": 6, "is_advertisement": false, "subsite_label": "dev", "id": 106470, "is_wide": true, "is_ugc": true, "date": "Thu, 13 Feb 2020 13:59:45 +0300", "is_special": false }
Создать объявление на vc.ru
Трибуна
Shema — игрушка и сонный ассистент на стыке IoT и AI от стартаперов из Волгограда
Shema — устройство, которое успокаивает ребёнка и помогает ему заснуть. Оно управляется со смартфона, имеет «умный…
0
{ "id": 106470, "author_id": 449645, "diff_limit": 1000, "urls": {"diff":"\/comments\/106470\/get","add":"\/comments\/106470\/add","edit":"\/comments\/edit","remove":"\/admin\/comments\/remove","pin":"\/admin\/comments\/pin","get4edit":"\/comments\/get4edit","complain":"\/comments\/complain","load_more":"\/comments\/loading\/106470"}, "attach_limit": 2, "max_comment_text_length": 5000, "subsite_id": 235819, "last_count_and_date": null }
9 комментариев
Популярные
По порядку
Написать комментарий...
0

Отдельный like за Erlang|OTP.

Основная задача Erlang - обеспечить большое количество стабильных соединений с клиентами минимальной стоимостью (ресурсной). То есть он получает запрос на соедиение от клиента и держит его пока есть необходимость. То есть Erlang не про бизнес-логику. Он про инфраструктуру.

Бизнес-логику можно было бы сделать на Elixir. Это язык высокого уровная. Код Elixir преобразуется в Erlang. Фактически, Elixir - синтаксический сахар для Erlang :)

И, да, классный UI получился! Чистенько и гладенько

Ответить
1

Спасибо!)

Ответить
0

В целом статья вышла не плохая. Подскажите это анг проект? И не совсем понял что за биржа? Ы целом за статью 5. А кот молодец)

Ответить
0

Это мой личный эксперимент по разработке биржи на функциональных языках силами одного человека. Все начиная от архитектуры и заканчивая интерфейсами пользователя пришлось реализовывать самому.
Внизу статьи есть ссылки на статьи, описывающие путь развития проекта.
До перевода на русский руки не дошли пока.   

Ответить
0

Да увлекательно. Нужно ознакомиться с вашим деитещем. Ведь труда вы внесли не мало.

Ответить
0

Если возникнут вопросы, буду рад ответить

Ответить
0

Лайк за отзывчивость). По любому будут вопросы, по любому обращусь)

Ответить
0

Лайк за слог :)

Ответить
0

Благодарю)

Ответить
{ "page_type": "article" }

Прямой эфир

[ { "id": 1, "label": "100%×150_Branding_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox_method": "createAdaptive", "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfl" } } }, { "id": 2, "label": "1200х400", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfn" } } }, { "id": 3, "label": "240х200 _ТГБ_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fizc" } } }, { "id": 4, "label": "Article Branding", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "cfovx", "p2": "glug" } } }, { "id": 5, "label": "300x500_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfk" } } }, { "id": 6, "label": "1180х250_Interpool_баннер над комментариями_Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "ffyh" } } }, { "id": 7, "label": "Article Footer 100%_desktop_mobile", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjxb" } } }, { "id": 8, "label": "Fullscreen Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjoh" } } }, { "id": 9, "label": "Fullscreen Mobile", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjog" } } }, { "id": 10, "disable": true, "label": "Native Partner Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyb" } } }, { "id": 11, "disable": true, "label": "Native Partner Mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyc" } } }, { "id": 12, "label": "Кнопка в шапке", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "bscsh", "p2": "fdhx" } } }, { "id": 13, "label": "DM InPage Video PartnerCode", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox_method": "createAdaptive", "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "flvn" } } }, { "id": 14, "label": "Yandex context video banner", "provider": "yandex", "yandex": { "block_id": "VI-223676-0", "render_to": "inpage_VI-223676-0-1104503429", "adfox_url": "//ads.adfox.ru/228129/getCode?pp=h&ps=bugf&p2=fpjw&puid1=&puid2=&puid3=&puid4=&puid8=&puid9=&puid10=&puid21=&puid22=&puid31=&puid32=&puid33=&fmt=1&dl={REFERER}&pr=" } }, { "id": 15, "label": "Баннер в ленте на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byudx", "p2": "ftjf" } } }, { "id": 16, "label": "Кнопка в шапке мобайл", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byzqf", "p2": "ftwx" } } }, { "id": 17, "label": "Stratum Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvb" } } }, { "id": 18, "label": "Stratum Mobile", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvc" } } }, { "id": 19, "disable": true, "label": "Тизер на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "p1": "cbltd", "p2": "gazs" } } }, { "id": 20, "label": "Кнопка в сайдбаре", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "cgxmr", "p2": "gnwc" } } } ] { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9qZWN0SWQiOiI1ZTRmZjUxODYyOGE2YzcxNDUxNWY0ZGEiLCJpYXQiOjE1ODI1MzY0NDB9.AwBBnUWMy3RR1xtAoaXVr81WvqxdlD4C8CBpwFiONzw", "release": "35e7e021" } { "page_type": "default" }