Как стать автором
Обновить

Комментарии 9

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

Я тоже как то копал в этом направлении, потом забросил. Может вернусь к своему проекту, доделаю, а пока просто выложу здесь пару мыслей, может кому пригодится.

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

Далее — об ограничениях языка. При программировании мы как правило упираемся в то что программа разбита на какие то части, каждая хранится в отдельном файле. В нашем случае это рудимент, который мешает программить. Почему? Потому что именно стремление рассовать все по файлам и приладить древовидную структуру приводит нас к модулям и прочему. Оно неплохо само по себе но есть другой путь.
Давайте рассмотрим разработку программы с потоков (flow) — именно так, как ее обычно обсуждают с бизнесом. То есть у нас есть определенные диаграммы состояний и потоков, и вот эти диаграммы с точки зрения приложения, работающего на обмене сообщений — и есть исходный код программы.
То есть мы задаем агентов, задаем связи между ними, на каждую связь указываем формат сообщения (или он может браться из описания агента) и указываем тип транспорта (вызов метода, tcp, rabbit-agent, да все что угодно) — и компиляем.
И вот тут самый смак. То, что мы сейчас ковыряем и называем исходниками — должно быть результатом компиляции таких диаграмм. То есть это что то вроде DITA — набор кусков кода (описыващих агентов) и набор правил, которые собирают агентов в модули и прикручивают к ним транспорт.
Знаю что запутанно, попробую пояснить на конкретном примере.
Стандартный сервис — клиент — бекэенд — база
на клиенте пишем на js, на бэке пусть будет php и база скажем postgresql, весь интерфейс на хранимках, две схемы — паблик и бэк.
Рассмотрим стандартный запрос к апи
клиент делает какой ни будь fetch, php делает какой нибудь odbc->query() а sql отрабатывает какую либо хранимку.
В обычном проекте это будет лежать в трех локациях по десятку файлов. Как это могло бы быть?
В одном файле
process some_api_request tags api{
    agent client: javascript{
        fetch бла бла
    }
    agent back: php{
        odbc->query(); бла бла
    }
    agent db: plpgsql tags schema=public{
        create function бла бла
    }
}

и много таких описаний на каждый процесс. Да, и это пример без траспорта, так еще планируется что можно задавать связи между агентами с указанием формата сообщений.
а потом собираем:
build client.js as select all where agent=client; или что то в этом роде
build api.php as select all where process has tag api AND agent=back;
build db_public.sql as select all where agent=db and tag schema=public;

То есть на этапе проектировании мы имеем весь код процесса в одном месте. А после сборки мы растасовываем код по контекстам. DITA в чистом виде но для программирования. Один агент естественно может участвовать в разных процессах (можно описать его в одном месте а в описании процессов просто инклудить)
Из одного набора агентов разными правилами сборки можно собирать разные версии софта (для разных сред)
Поменять обмен сообщениями с tcp на rabbit можно просто указав другой транспортный агент.
подходящие под реализацию архитектуры — тот же веб, значительная часть сетевых прилад, расширения броузера (контент скрипты + бэк скрипт + попап — все обмениваются сообщениями + они могут обмениваться с сервером)
В общем есть куда применять )

Плюс к этому уже можно прикручивать gui и получить довольно серьезную и удобную среду разработки.
Один не потяну, потому и забил. Искал готовое — чет не нашел. Появятся интересующиеся — велкам.
признаться — большая часть в голове. Есть конечно наброски, черновики, даже работающий код, но тут какое дело — это все мааааленькая часть глобального плана по захвату мира и из этой мешанины вычленить именно модель сборки прийдется потратить время. В общем я потихоньку сейчас вычленяю другую идею, собираюсь оформить в виде статьи, возможно после этого займусь и сборкой. где то через месяц, не раньше )
А так, на поинтриговать — то что я тут сумбурно описал — это одно из проявлений семантического git-а. Есть еще одна интересная (на мой взгляд) абстракция — это оформление декораторов в виде стилей. То есть применив к коду различные наборы стилей (декораторов) получаем код для разных окружений. Тоже в канве метапрограммирования и тоже имеет свои области применения. (да, абстракцию противного веба с html+css можно использовать в няшном «код+декораторы» стиле)
А готовлю сейчас другую тему — сквозную сборку проекта (клиент, бэк и db api) на основе деклараций (swagger и sql описания функций) то есть один раз указав спеку получаем автоматически сгенеренный client.api модуль на клиенте, каркас бэка (там остается только модулями хандлеры запросов описать) и сгенеренный для бэка клиент к базе (на основе sql дефиниций) Все на тайпскрипте, с контролем типов и все такое, но вообще можно брать любой язык — это mustache шаблоны, можно любой язык метапрограммить.
Но, как и все порядочные программисты я жутко ленив. Хорошо зажигаюсь сам, хорошо зажигаю других, но долго и качественно гореть отказываюсь. Поэтому решил понемногу оформлять идеи в статьи и делать вбросы. Если даже не стрельнет — можно хоть пообсуждать с интересными людьми.
Я бы сказал, что увязывать клиента+бэк+бд не так просто… И про декораторно-стилевой паттерн я бы тоже почитал, так что подкиньте в топку полешек ))
>Я бы сказал, что увязывать клиента+бэк+бд не так просто…
ну это как раз самая готовая часть. В том смысле что оно работает, хоть и не весь функционал реализован) Там из интересного в принципе сама идея и генерация клиента для базы — на основании sql описания базы генерятся typescript интерфейсы и клиент к базе в виде sql.user.login(), sql.user.logout() (у меня бэк на ноде). Да, используется родной парсер postgresql https://github.com/lfittl/libpg_query, там есть бандл для ноды.
Так как каркас бэка сгенерен (причем вместе с санитизацией входных параметров на основе swagger спеки) — то остается только прописать хандлеры, а для них уже есть готовый клиент для работы с базой. И для этого клиента есть описанные интерфейсы, то есть работает контроль типов, что в этом случае правильнее (на мой взгляд) назвать контрактами.
В общем не переключайтесь, в течении месяца рассчитываю добить статью )
Ок, если что, напишите мне, почитаю. Похоже, вам дополнительное удобство добавляет JS, который и тут и там (известное удобство ноды — один язык с фронтэндом). Не забудьте про схемы, лучше 1 раз увидеть, чем 100 раз услышать.
>Не забудьте про схемы, лучше 1 раз увидеть, чем 100 раз услышать.

Вы про sql schema или json?
Нет, я про графические схемы, иллюстрации к Вашей работе
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации