Как быть, когда все советуют растащить проект на микросервисы. А ты не готов

    Монолит часто обсуждают в негативном ключе. Но сразу перейти на микросервисы получится не у всех — и вот уже не первая команда и компания делятся опытом построения «переходного звена»: модульной архитектуры. Давайте в деталях посмотрим, как делаются такие проекты.



    Недавно я смотрел два доклада на эту тему: от Юлии Николаевой из iSpring и Антона Губарева из Skyeng. Так как с Антоном мы работаем в одной компании, для своего подкаста я решил поговорить с Юлей.



    Ниже — текстовая расшифровка основных идей из разговора.

    «Мы взвесили причины, по которым хотели перейти в микросервисы, и настоящие проблемы, которые мешали нам жить в монолитной архитектуре»


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

    Это произошло с нашим проектом: он стартовал в 2009-м, но долго не было людей и времени, чтобы бороться с неконтролируемым разрастанием кодовой базы. А к 2018-му стало понятно: пора уже как-то реструктуризировать монолит.

    Когда встал вопрос, что делать с нашим монолитом, мы, естественно, тоже рассматривали микросервисы. Но… У распределенной архитектуры свои накладные расходы. И мы не были к ней готовы. Например, у нас не было команды девопсов от слова «совсем».

    Не было как такового нормального CI/CD, не было ни докера, ни кубернетеса — вообще ничего такого.


    Плюс, у нас не стояла остро проблема масштабирования: нет таких нагрузок. Что реально мешало — очень тесная связанность кода. Изменение в одной части зачастую приводило к ошибкам в куче других мест, плюс мы не могли нормально разрабатывать несколько фич. Вернее, разрабатывать параллельно мы могли, но вот смержиться… на этом этапе могли возникать неожиданные логические конфликты.

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

    У нас все усугублялось тем, что кусок легаси написан на Symfony 1.4 с использованием Propel 2, который не так просто использовать в парадигме DDD (Domain Driven Design). А нам очень хотелось DDD. Для этого хорошо подходит ORM Doctrine, которую к легаси так просто не прикрутишь.

    Мы решили скрестить ужа с ежом и теперь живем с двумя фреймворками.


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


    «Буквально каждый день, на каждом шагу мы встречали множество вопросов, которые не знали, как решить»


    Мы, тимлиды, сначала вдвоем, потом втроем разрабатывали функционал в этой новой архитектуре. Было много вопросов. Начиная с того, как организовать папки в проекте: правда, когда сделали и поняли, как и зачем, находили в интернете просто массу источников, в которых все это написано. Наверное, не так искали)

    Параллельно часть команды разработчиков ушла в девопсы.


    Они занялись переездом в кубернетес, докер и все такое.

    Чтобы погрузить остальную команду в тему, мы подготовили специальный курс по DDD, который пару выходных все проходили. Нашим разработчикам надо было реализовать два контекста — прямо закодить их. Мы, конечно же, все идеи рассказали, но получили фидбэк, что очень сложно и «мозг прямо ломает».

    Да, поначалу тяжело. Но зато когда разработчик распробует и примет новую архитектуру, а ему прилетает фича, которую нужно сделать в легаси, у него сразу возникнет мысль: «Как бы мне сделать так, чтобы было похоже на новую архитектуру».

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

    На все у нас ушло, наверное, три с половиной месяца.


    Мы не просто переделали архитектуру, но и реализовали новый функционал с вынесением частей из легаси. Плюс, все эти три месяца нам команда девопсов настраивала инфраструктуру, чтобы мы смогли взлететь в Kubernetes. Сейчас в новом коде у нас 14-15 контекстов плюс большой легаси, где можно было бы выделить несколько контекстов. Пока в легаси остается большинство контроллеров — непонятно было, куда положить их код, потому что контроллеры могут получать и манипулировать данными разных контекстов.

    И ура! Мы можем писать фичи в 3-4 потока командой из 12 бэкендеров.


    Сергей: В PHP мы не можем дать программисту по рукам и запретить использовать какой-то внутренний класс другого модуля. Это же все держится на устных договоренностях внутри команды. Как это все организовать?


    Юлия: Контролировать такую архитектуру сложно. Все разработчики должны быть погружены в эту идею, разделять ее. Мы по этим граблям прошлись поначалу, когда вовлекали команду. Многим казалось, что это оверинжиниринг дикий: «Зачем так сложно, давайте так не будем».

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

    Мы нашли такую утилиту — deptrac — статический анализатор кода, который помогает контролировать зависимости.


    Утилита встроена в наш CI/CD и запускается автоматически: фактически, большая часть договоренностей контролируется с ее помощью. Логические ошибки стараемся отлавливать еще на архитектурном ревью: это встреча, на которой разработчик, которому предстоит пилить фичу, представляет схемы, где все по слоям уже разделено. Там сразу понятно, что в каком контексте, какие взаимосвязи и т.д.

    Сергей: А как такую архитектуру мэйнтэйнить?

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

    Сергей: БД у нас одна, проект у нас один. Что мне делать, если в моем модуле нужны данные из нескольких других контекстов?

    Юлия: Это один из самых сложных вопросов — наверное, как в модульной, так и в микросервисной архитектуре. Мы пытались в одном из случаев реализовать объединение данных из разных API: сделали запросы, объединение в памяти, сортировку, фильтрацию. Работало жутко медленно.

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

    Сергей: И здесь мы подходим к проблеме с дублированием кода...

    Юлия: Дублирование возникает, например, если у нас есть слой, который авторизует операции во всех контекстах — и мы его дублируем в каждом контексте. То есть, у нас есть практически одинаковый код, который запрашивает: «А есть ли права у пользователей». Но мы считаем, что это достаточно приемлемое дублирование.

    Сергей: А что делать, когда одному модулю нужно выполнить действие в другом модуле? Например, при оплате изменить баланс, создать уведомление — это все разные контексты. Как в монолите быть с этим?

    Юлия: Ты перечислил кейсы, которые хорошо укладываются в событийную модель. У нас много через асинхронные ивенты сделано. Если контекст не должен знать ничего про то, что произойдет в других контекстах, — будет событие, которое обработает все заинтересованные в нем лица. Если действие тесно связано с выполняемой операцией и про ее контекст нужно знать, напрямую вызывает метод API.

    Все как в микросервисной архитектуре, грубо говоря.


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

    Сергей: Но если приложение постоянно усложняется фичами и контекстами, модульный монолит все равно лишь промежуточный шаг к микросервисам?

    Юлия: Да, конечно. Если подразумевается, что приложение будет непрерывно расти, если команды будут расти, это естественно. Например, у нас возникла проблема, что автотесты нереально долго выполняются перед релизом, а если что-то отвалится — приходится повторно это все запускать.

    Новые фичи, если они независимые, мы будем, наверное, в микросервисах сразу делать. Тем более у нас уже есть инфраструктура, есть шаблон, из которого можно создать новый микросервис. Но, допустим, если нужно использовать какие-то данные или классы из легаси, у которого нет своего API. У нас такой принцип, что легаси может дергать API, но новые контексты от легаси, фактически, ничего не могут получать и с ними не общаются, только через ивенты. Если мы вынесем что-то в микросервис, а этому микросервису нужен будет доступ к легаси коду, какому-то функционалу, то это будет достаточно сложно сделать.

    P.S. Больше выпусков подкаста «Между скобок» с интересными людьми из мира PHP можно найти здесь.
    Skyeng
    Крупнейшая онлайн-школа Европы. Удаленная работа

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

      0
      Мы, тимлиды, сначала вдвоем, потом втроем разрабатывали функционал в этой новой архитектуре.


      Что-то тимлиды не своим делом у вас занимаются.
        +5

        А почему надо переходить на _микро_сервисы? Неужели, обычные сервисы уже не популярны? Почему?


        А если к любому другому слову добавить приставку SI, оно станет круче?… фемто-модули (hello, leftpad).… пико-скрипты. гига-sql. кило-клиент. мили-конфиг.

          0
          А если к любому другому слову добавить приставку SI, оно станет круче?… фемто-модули (hello, leftpad).… пико-скрипты. гига-sql. кило-клиент. мили-конфиг.

          Нано- забыли )
            0

            Дописывайте. Приставок много, список открыт к дополнению.

            –1
            Чтоб масштабировать отдельные кусочки системы, а не все разом
              +4

              А разве приложение, порезанное на несколько сервисов, нельзя масштабировать раздельно для каждого сервиса? Например, если толстый и основательный интернет-магазин состоит из 30 сервисов, то мы можем каждый из них масштабировать согласно его значимости и нагрузке, которую он создаёт.


              … Просто люди привыкли использовать слово "микросервис" как синоним слова "сервис" ("давайте порежем монолит на сервис" — думают они, "давайте порежем монолит на микросервисы" — говорят они).


              При этом "микросервисная архитектура" по сравнению с обычными сервисами приносит с собой такой комплект ответственности, что редкий человек её выдержит. Взять-то возьмёт, да не сдюжит.

              +1

              У некоторых есть практика, что разрезая монолит на сервисы, мы получаем несколько монолитов в итоге. Сочетая все недостатки монолитов и распределеных систем.


              Некоторым именно круче надо ;)


              Некоторые при слове сервис сразу вспоминают SOAP и их в дрожь бросает :(


              Некоторые из практических соображений выбирают именно микро — меньше длина "линии разреза", меньше внутренних вызовов рвать на внешние


              Много причин, у каждого свои, даже в рамках одной команды

                +1

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

                  0

                  Редко обычно прямо берут на 100 микросервисов или 10 сервисов распиливают монолит. Обычно по одному выпиливают. И каждое отдельное выпиливание менее рискованным становится в случае микросервисов.

                0
                Микро- от обычного сервиса отличается тем, что сделан конкретно для данного проекта. Обычно это обрезанный, никак или плохо документированный куцый проектик с несколькими REST-урлами и прибитой гвоздями архитектурой. Чтобы он дорос до полноценного сервиса — должно пройти прилично времени, не каждый проект доживет.
                  0

                  Если он плохо документированный, то это уже не микросервисная архитектура. Принцип микросервисной архитектуры — фиксация проекта на уровне API компонент. Если API едет, то уже не микросервисная архитектура.

                    +1
                    Ну в мире розовых пони все сервисы, архитектура и код прекрасно документированы, но мы, к сожалению, живем в реальном мире.
                      +2

                      При чём тут розовые пони? Микросервисная архитектура придумывалась для того, чтобы защитить проект от говонокода. На верху сидит толковый лид, который думает архитектуру, масштабирование и т.д., он ваяяет соглашения в API, а дальше уровень говнокода за конкретным API определяется степенью важности этого API. Если это поддержка стикеров в чате, то команда набирается сильная и толковая, которая пишет хороший сервер. Если это какая-то ерунда, типа управления стержней атомного реактора, то туда можно набрать джунов и индусов. Соблюдён контракт на API? Всё хорошо, проект живёт. Какой-то микросервис стал невыносим? Его можно переписать не ломая остальные куски.


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


                      Но… Это работает до тех пор, пока есть толковый техлид. Если джун или просто скучающий программист for fun спроектировал микросервисы, то всё, можно закапывать. Будет кратно хуже, чем в монолите, потому что теперь все ошибки проектирования будут вылазить в сетевое взаимодействие в райнтайме со всеми вытекающими.

                        0
                        Микросервисная архитектура придумывалась для того, чтобы защитить проект от говонокода.

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

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


                        Отчасти это верно, но микросервисы все же придуманы не для этого.

                        Основная задача разбивки монолита на микросервисы — уменьшение зависимостей одного компонента от других и приведение этих зависимостей в некоторый порядок. Бонусом часто идет возможность использования микросервиса в других проектах, пример — сервис авторизаций или приема платежей.
                        Минусом — надо управлять зависимостями, версиями микросервисов, развертыванием. Есть существенная потеря производительности.
                          +1

                          А мужики говорят, что микросервисы придуманы для независимого деплоя и масштабирования ) Остальное бонусы

                            0
                            Я знаю массу случаев, когда микросервисы вводились вообще без обоснований, просто потому что это нынче модно. Если хочет человек потрахаться с микросервисами и у него есть время — кто ж ему запретит? Это пока еще не уголовно преследуемое занятие ).
                              0

                              Я говорю о том, зачем придуманы (вернее как миру презентованы), а не о том, зачем внедряются :)

                                0
                                Микросервисы существуют уже десятки лет и их даже специально никто не придумавал — это логичное развитие любого проекта.
                              +1

                              А чем это отличается от сервисов? Сервисы так же независимо деплоятся и масштабируются. "Микро"-то тут при чём?

                                0

                                Ещё больше независимости. Единица деплоя/масштабирования делает только одну вещь в пределе и делает её хорошо и её отказ мало влияет на остальную систему.

                                  0

                                  И чем это отличается от сервисов? Почему обязательно "микро"?

                              0

                              Я ничего не путаю. Крупные проекты невозможно защитить от появления говнокода. Задачей проекта является защита от влияния говнокода на проект (почувствуйте разницу — появление и влияние). Микросервисы — один из методов защиты. Каждый страдает в своей песочнице сам в соответствии со своей компетенцией, а архитектура проекта определена на уровне сетевого API между компонентами. Пока архитектура хороша, говнокод не может влиять на проект. (Не на "как хорошо проект работает", а на проект — на то, насколько там внутри много спагетти из зависимостей и паталогических связей).

                                0
                                Крупные проекты невозможно защитить от появления говнокода.

                                Это не так, достаточно поставленного процесса Code Review. Полно достаточно крупных Open Source-проектов, грамотно сделанных.

                                Микросервисы — один из методов защиты.

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

                                  Больше они вонять будут — площадь выше при том же объёме. :)

                                    +2
                                    Опытные говнокодеры могут уменьшая площадь просто накладывать наверх слоями. Так заказчику кажется, что говна меньше, если смотреть сверху.
                                    +3

                                    … И все эти проекты всегда предусматривают плагины, сторонние модули, или ещё какой-то метод подгрузить код не коммитя его в основной репозиторий. Это как раз и делается для "защиты от говнокода". Если какой-то плагин плохой, то это проблема плагина, а не проекта.


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

                                      0

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

                                        0
                                        Не бывает такого, чтобы вот много баночек меда и из одной попахивает говном. Если поставлен процесс Code Review — то будет более-менее удобоваримо везде, ну кроме тех мест, что затруднительно переписать, но тогда оно будет обложено warning'ами, что сюда без болотных сапог, противогаза и перчаток лучше не соваться.

                                        А вот если процесс Code Review не поставлен — тогда обычно разброд и шатание, что, впрочем, не исключает какие-то грамотные места, если отдельные личности — профессионалы своего дела.
                        0
                        Дело не в монолите или микросервисах — адекватный программист всегда напишет адекваную программу на любой архитектуре. Переписывание монолита на микросервисах напоминает известную басню Крылова…
                          0
                          > Монолит часто обсуждают в негативном ключе.
                          > Но сразу перейти на микросервисы получится не у всех

                          А монолит в каком смысле? В том, что весь код вообще в кашу или в том, что все модули в одном сервисе и в одной базе?

                          А нужно прямо именно на микросервисы?
                            0

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

                            –1
                            Может это немного оффтопик, но как это все(микросервисы, архитектура...) вяжется с тем, что команда Skysmart(я так понял, те же люди, что и Skyeng) присылает пароли плейн текстом по почте?
                              0

                              Да никак, оно ортогонально.

                                0
                                Ортогонально, да не совсем. Технический блог на хабре повышает уровень доверия к команде. Пароли, хранящиеся в базе плейнтекстом этот самый уровень доверия обнуляют.
                                  0

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

                                    0
                                    Факты говорят сами за себя. При регистрации приходят данные доступа, затем при создании интерактивной рабочей тетради приходит инструкция о том как ее переслать ученикам. Внизу данной инструкции опять плашка с данными доступа плейн текстом.
                              +2
                              Собственно, переход на микросервисы как решение проблемы высокой связности кода кажется мне абсурдным решением. Как гильотина против перхоти. SOLID в обычном коде никто не отменял. Если архитектура отвратная в монолите, она останется такой и в микросервисах.

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

                              Недостатки: многократно возросшая цена поддержки, упавшая надёжность, сложность отладки. В каком-то описании про микросервисы читал, что де отладка становится легче. Ха-ха три раза. Где же легче, когда полную инфраструктуру приложения нельзя впихнуть на один комп девелопера? В одном из проектов писались здоровые методы, которые сериализовали отклики сетевых сервисов в xml и потом локально создавали моки, которые имитировали микросервисы соседей. Дофига кода обвязки, чтобы только отладиться и найти ошибку.
                              В общем, do it when you need it. Don't do because it is trendy, don't do just because you can.
                                0
                                полную инфраструктуру приложения нельзя впихнуть на один комп девелопера?

                                Не для всех приложений это справедливо

                                  +1
                                  Не знаю, как насчет «микро»-сервисов, но переход на отдельные bounded contexts, обменивающиеся через асинхронные сообщения прекрасно позволяет разделить работу, чтобы люди не мешали друг другу, в том числе по деплою. Каждая команда работает в своём темпе и со своей степенью надежности, нужной бизнесу. Плюс этот же подход позволяет достаточно легко и однотипно интегрировать любой сторонний функционал, мы вот Битрикс24 так подключаем — дали доступ команде разработчиков под Битрикс к нашей кафке и вперед.

                                  Кроме прочего этот подход позволяет потрогать в продуктовой среде новые технологии не перенося на них критичные для бизнеса bounded contexts и в случае успеха плавно на них мигрировать, не переписывая на них вообще всю систему за один заход.
                                    0
                                    И да, если криво поделить систему на микросервисы можно вместо монолита получить распределенный монолит, который обладает всеми недостатками как монолита, так и микросервисов, по этим граблям люди ходят с удивительной частотой.
                                    0
                                    ИМХО, если разработчики не смогли хороший монолит и поехали на микросервисы без понимания зачем их реально используют, то с большой вероятностью у них выйдет «распределенный монолит», который обладает практически всеми недостатками как монолита, так и микросервисов.
                                      –1
                                      А нам очень хотелось DDD.

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

                                      Просто интерфейсами покрыть, чтобы было похоже на «чистую архитектуру»? По-моему опыту так делать не надо, все закончится созданием кучи никому не нужных интерфейсов и только добавит акцидентальной сложности. По-моему в прикладном проекте (не в библиотеке) интерфейсы нужно делать только тогда, когда на 100% знаешь, что будет больше одной реализации. YAGNI. А так ощущение создается, что в описываемом проекте люди только открыли для себя интерфейсы и DDD и пустились применять просто потому что это «круто». Ничего, время все расставит на свои места, набьются шишки. Лучше конечно их набивать используя прототипные проекты а не основной.

                                      Мы решили скрестить ужа с ежом и теперь живем с двумя фреймворками.

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

                                      Сейчас в новом коде у нас 14-15 контекстов плюс большой легаси

                                      По-моему в проекте проблем стало еще больше. О каком разделении на контексты можно говорить, если база одна?

                                      Интересно, решили ли они делать persistence ignorance?
                                        0
                                        интерфейсы нужно делать только тогда, когда на 100% знаешь, что будет больше одной реализации.

                                        Моки для тестов считаются реализацией?


                                        О каком разделении на контексты можно говорить, если база одна?

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

                                          0
                                          Моки для тестов считаются реализацией?

                                          Нет

                                          В целом одна база никак не противоречит разделению на контексты.

                                          По мне так база это часть релизации контекста, сугубо внутренняя вещь. Чтение напрямую из базы минуя интерфейсы контекста приводит к нарушению принципа сокрытия информации на уровне контекстов.
                                            0
                                            Нет

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


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

                                            С одной стороны, да. С другой, обычно всё-таки таблицы часть реализации, а то, что таблицы нескольких контекстов лежат в одной физической базе "чисто случайно" особо на логическую изоляцию не влияет. С третьей, сама база, схемы конкретных таблиц могут быть частью интерфейса. Никого же вроде особо не смущает, чтение событий одного контекста в другом. Принципиальных различий с базой не вижу, пока только чтение идёт

                                              0
                                              Почему?

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

                                              Чисто теоретически. Я думаю, что в описываемом проекте такого нет. Да и вообще, я глубоко сомневаюсь, что кто-то реально будет делать БД частью интерфейса ограниченного контекста.
                                                0

                                                Какими моками? В PHP моков на уровне языка нет, есть четыре, вроде, основных способа создания моков, работающих с тайпхинтами объектов:


                                                • имплементация интерфейса (нужен интерфейс)
                                                • расширение класса (класс должен быть не final, мокуемый метод не должен быть final, класс не должен быть статически "прилинкован" к внешнему миру, в общем много требований к исходному классу)
                                                • манипуляция механизмом автозагрузки, подставляя вместо оригинальной свою реализцию, совместимую с оригинальной
                                                • вмешательство в работу zend engine

                                                Я что-то упустил? Самый простой — первый как по мне.


                                                Да и вообще, я глубоко сомневаюсь, что кто-то реально будет делать БД частью интерфейса ограниченного контекста.

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

                                                  0
                                                  вмешательство в работу zend engine

                                                  У вас чувство юмора такое? Вы же с первого раза поняли, какие моки имеются ввиду. Все что вы написали я прекрасно знаю, зачем вы всё это перечислили?
                                                    0

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


                                                    И я нахожу, что имплементация интерфейса самый простой в общем случае, особенно если приложение соблюдает ISP из SOLID — просто чтобы не реализовывать 100500 методов, в тесте не используемых.

                                                0
                                                Принципиальных различий с базой не вижу, пока только чтение идёт

                                                События можно версионировать. Со схемой базы это не получится.
                                                  0

                                                  Никогда не видели, когда приложение пишет одновременно в две таблицы типа users и users_v2, пока даже не то что условно внешние клиенты на новую схему не перейдут, а просто миграция по преобразованию данных в новую схему отрабатывает? Чем отличается от эмитирования событий двух версий?

                                          0
                                          Конечно проект хороший, развивается, растет и специалисты растут вместе с проектом. Приятно знать, что есть такие PHP проекты.
                                            0
                                            Вообще я бы различал монорепозиторий и монолитный код. Последний — это впервую очередь сильно связанный код и кучей проблем из-за этого. Модульный код, представленный в докладе или код разбитый по контекстам с жесткими границами — это фактичеси те же (микро)сервисы, но только имеющие общую бд (может еще некоторые инфраструктурные штуки). Разбить и вынести на микросервисы такое приложение можно легко. Зато нам не нужны распределенные транзакции, у нас есть легкий дебаг приложения, легко резворачивать и доставлять код. Монорепозиторий с модульным подходом, как по мне, это идеальный старт любого приложения, а микросервизная архитектура это логическая эволюция, но главное чтоб возникла потребность в этом и не было микро-сервисы ради микросервисов, так как накладные расходы будут намного выше.
                                            Кстати кому интересно недавно опубликовал пример приложения на DDD/SQRS на симфони
                                              0

                                              К какому варианту хранения микросервисов пришли в итоге? Каждый микросервис в своем репо? Или общий?

                                                0

                                                Каждый микро сервис в микро репо на микро компьютере. Микро компьютеры объединяются в микро сеть. Каждая клавиша клавиатуры имеет собственный микро сервис для обработки. Движение мыши контролируется 4 микро сервисами: влево, вправо, вперёд, назад.

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

                                                Самое читаемое