Проект: Reinforced.Tecture  Публичный пост
3 сентября 2020     335   
Reinforced.Tecture

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

Сейчас меня попустило, я каюсь и наконец могу адекватно рассказать что это такое. Итак.

Reinforced.Tecture - это экспериментальный архитектурный фреймворк для C#. Моё личное видение того, как надо писать кровавый ынтерпрайз в мире .NET в 2к20 с минимальным количество боли и максимальным количеством профита.

Все знают что такое кровавый ынтерпрайз: опердни, автоматизации документооборота, складов, отчётности, делопроизводства и прочая нудятина с префиксом "бизнес-" и привкусом офисной затхлости. Обычно такой код пишется двумя способами:

  • непристойно обмазывается классическими ОО-паттернами родом из Java (да, даже на C#) и лихих 80х-90х. Как пример - MS-овский eShopOnContainers, где авторы попытались применить вообще всё, что когда-либо слышали про ОО-дизайн;
  • или говнокодится на коленке не самыми квалифицированными сотрудниками в тщетной попытке уложиться в дедлайны и удовлетворить бизнес на предмет требований. Как следствие - генерит больше мемов, чем полезной работы.

Первое вроде как считается "правильно", второе вроде как считается "быстро". Тут я и подумал: а почему никто не сделает чтобы было быстро и правильно? C# - язык с крутыми языковыми плюшками, довольно мощной системой типов и в то же время вполне себе интерпрайзный, что позволяет щедро использовать его в кровавом продакшене в отличие от oCaml и прочих хаскеллей. К тому же я очень люблю и хорошо знаю C#, поэтому взялся за проектирование.

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

Потом контракт с эстонцами закончился и с разрешения начальства, я забрал свои архитектурные наработки с целью их систематизировать и допилить до чего-либо вменяемого. И вот спустя полгода работы в spare time, у меня наконец имеется продуманный и законченный авторский архитектурный шаблон со всем необходимым glue code для шарповых приложений. Хоть прям сейчас запиливать автоматизацию похоронного бизнеса.

Получилось довольно своеобразно, в духе киберпанка и не без доли кринжа. Чем-то напоминает MediatR, EF.Core и Autofac в одном лице. Некоторые функционально-осведомлённые товарищи углядели в этом ZIO (а я даже не понял о чём это они лол).

Если рассказывать крупными мазками, то набор плюшек такой:

  • Решение выполнено в общей идейной стилистике Microsoft: с оглядкой на функциональное программирование, но без фанатизма, монад функторов и повальной иммутабильности;

  • За основу взята концептуальная идея разделения запросов и команд (модное нынче слово CQRS);

  • Команды складываются в очередь и диспатчатся опосля. Я использовал тонны синтаксического сахара - только бы не заставлять пользователя писать дурацкое слово "Enqueue" и создавать инстансы команд руками;

  • Запросы пишутся в виде статических расширений. Я очень хотел убить Repository pattern - я его убил;

  • Сервисно-ориентированная архитектура обыгрывается на свой слегка кринжовый лад: для сервисов не надо писать свои интерфейсы, а надо сразу классы. Кринжовость заключается в том, что у этих классов должен быть приватный конструктор. Патамушта!

  • В решение вмонтирован свой мини-DI-контейнер, обслуживающий инстансы сервисов. Только он убер-простой: нет лайфтайм менеджмента (потому что лайфтам сервисов логики всё равно известен), не требуются портянки регистраций (все метаданные берутся из типов). Пишешь Do<OrdersService>() и готово;

  • Из коробки поддерживается работа с бесконечным количеством баз данных одновременно. И от всех вы абстрагированы;

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

  • Система трейсинга. Трейс в Tecture - это не просто лог. Это - запись всех отправленных запросов и всех созданных команд. По вызову магического метода трейс рассказывает вам человеческим языком что конкретно делает приложение в том или ином случае.

В огромных проектах, когда все уже забывают какие были реквайрменты эта фича должна по задумке стать божественным спасением утопающих. Когда тикеты потёрты, емейлы потерялись, документы истлели, Confluence лежит а комментарии в коде встречаются нечасто - то система, готовая сама объяснить что в конечном счёте улетает в базу данных по нажатию той или иной кнопки - буквально восьмое чудо света. А если ей ещё и немного помочь, оставляя короткие аннотации к командам и человеческие описания запросов - то текст трейса приобретает характер серьёзного документа. На случай важных переговоров, как говорится.

В нашей эстонской команде этой фичи очень не хватало, потому что в управление требованиями мы в конечном счёте и упёрлись.

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

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

  • Комбинируя две вышеописанных фичи и ловким движением укладывая их в unit-тест получаем доселе невиданную плюшку архитектуры: автоматизация автоматизации тестирования. Т.е. если у вас есть система, про которую бизнес говорит "на данный момент всё работает как надо" - ленивым движением пальца вы можете сгенерить регрессионные тесты, реально валидирующие логику и не требующие поднимать вообще никакой инфраструктуры для прогона. DevOps-инженер уже ждёт куда бы впаять вызов dotnet test.

  • В виду специфической природы тестирования - отпадает необходимость в моках, абстрактных прокладках, промежуточных интерфейсах. Можно просто брать. И. Пилить. Фичи.

  • Стоит ли говорить что логика и запросы полностью композабельны. Сервисы можно использовать друг из друга, одни запросы из других;

  • В одной из фич легализован прямой SQL в базу данных. Ура товарищи! Теперь пуляться SQL-строками можно безопасно и подконтрольно;

  • Есть точки расширения для поддержки новых и новых фич.

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

5 комментариев 👇
Semyon Kotlyarov, Программист 5 сентября 2020

Очень круто звучит, нашел в статье проблемы с которым сам часто сталкиваюсь. Но совершенно непонятно как вкатится, если научен "обмазывается классическими ОО-паттернами" и тем более начать использовать в проекте старше 5 лет. Придется отложить до светлого будущего, когда нужно\можно будет начать что-то с нуля.

Энивей респект.

  Развернуть 1 комментарий

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

По моему опыту на Tecture-архитектуру проект переводится сравнительно просто. В основном приходится удалять существующий код :)

  Развернуть 1 комментарий
Ihor Filimonchuk, Привлекаю клиентов с интернетов 5 сентября 2020

Сорь за коммент не по теме.
Мб у меня клюк, но когда эмблема маленькая (https://prnt.sc/ubz8hs), она будто создана для обозначения диктаторского режима.

Мб это из-за контекста, рядом белое а тут выделается)

  Развернуть 1 комментарий

@IhorFilimonchuk, может быть... :)

  Развернуть 1 комментарий
Vladimir Zimin, Твой куратор из 11 октября 2020

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

Парочка вопросов:

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

И ещё вопрос по аспектам. Я правильно понимаю, что на всякие сильнораспространённые штуки можно написать свои аспекты и куда-то выложить, в тот же NuGet, так что со временем (в идеале) появится коллекция аспектов под всё самое необходимое?

Удачи тебе с проектом, выглядит круто!

  Развернуть 1 комментарий

😎

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

Что вообще здесь происходит?


Войти  или  Вступить в Клуб