Комментарии 19
Тоже недавно открыл для себя VSA и пока что вполне ей доволен.
Посмотрим как она поведёт себя при усложнении проекта
Видимо мне наглядности не хватает, но пока выглядит как "я не смог пилить архитектуру, поэтому буду по старинке складывать всё в кучу". Для тупней типа меня - отличненько
=)
Все мы иногда тупни. Найти себе сплошных senior-ninja-10+yoe-developer в команду, чтобы поддерживать сложную архитектуру, и не испортить все в первый кранч/отпуск тимлида (и это еще если тимлид сам понимает, что делает) - это, конечно, здорово, но сложно и дорого.
Можно найти довольно много книг/статей, и вот прям шаг за шагом построить себе красивую архитектуру следуя всем заветам, и для этого не потребуется быть каким-то одаренным разработчиком. Однако, точно ли оно стоило потраченного времени? Точно ли бизнес выиграет от этого оверхэда? Точно ли коллега прочел ту же книгу и на одной волне с тобой, или просто делает вид?
На разных проектах свои правильные ответы на эти вопросы, но у меня есть ощущение, что к сожалению их обычно не задают себе.
Все становится сложным когда сущностей в бд 100+. Вы предлагаете делить одномерно по VSA или HSA. Я уже давно применяю подход двумерного деления: VSA+HSA. Если интересно могу описать.
Я там местами описал, в параграфах про DDD и границы подхода: далеко не весь код проекта получится (и стоит) поделить прям по слайсам: горизонтальные слои все равно останутся, и для меня суть VSA скорее в том, чтобы избавиться от горизонтальных слоев (и не размазывать код по всему проекту) там, где это возможно.
Так что, возможно, корректнее это было бы назвать VSA+HSA. Но если ваше понимание этого отличается, то интересно было бы услышать.
Интересно
Если не применять двумерный подход то всегда случается что одна ответственность с одной точки залезает в другую так как по второй мерности они слиты воедино.
Вообще, я тут на эту тему размышлял в таком стиле: если у нас в моде теперь микросервисы, а монолиты типа плохо - почему мы внутри одного монолита даже не пытались все эти годы делить код на части?
Можно же придумать и как ограничить куски БД, которым управляет каждый слайс. И сделать взаимодействие «слайсов» так, чтобы это были асинхронные вызовы с сериализуемыми параметрами. Чтобы чуть что - деплоить этот слайс отдельно, или выделить в отдельную репу.
Но там куча вопросов, начиная с того, как разложить это по проектам. Я пока ничего лучше эдакой 2х мерной архитектуры не придумал: у меня разбито на проекты как обычно - common (dto, интерфейсы), services (реализация), web (контроллеры и прочее про веб). Но в каждом проекте - все лежит по одинаково названным папочкам, типа Users, Products, и т д. И этим слайсам разрешено общаться только через их публичные интерфейсы в common. Так себе, конечно, но хоть какой-то порядочек.
Особенно этот вопрос заиграл с LLM-ками: им надо четкие правила как что класть, и где что искать, ограничить им контекст нужно.
Да, VSA в текущем виде - не универсальное решение, хотя у меня есть подозрение что универсального решения и не будет: слишком уж размыты могут быть границы фичи от проекта к проекту. Да и сегодня твой эндпоинт рекомендаций для юзера учитывает только его купленные товары, а завтра пол базы корми нейронке, чтобы угадывать что захочет купить юзер.
В общем, правила может и можно сформулировать, только увы, головой все равно думать придется.
Но с LLM-ками да. По моему опыту, они могут подсказывать куда чаще и качественнее с VSA структурой (да и просто если писать код не забывая о KISS), чем с огородом из слоев и абстракций, даже при одинаковом функционале проекта.
Я в своих проектах заменил MediatR на аналог с кодогенерацией https://www.nuget.org/packages/Mediator.SourceGenerator
А в чем принципиальная разница с Areas?
Можно же еще проще. Полностью плоская структура папок. В одной папке код инициализации микросервиса в виде массива функций. В остальных папках код конечных точек API так же в виде массива методов обрабатывающих контейнер состояния.
Достаточное уже время такой подход использую. Новые сотрудники программируют с первого дня, потому что при взгляде на структуру папок сразу понятно что делать.
Проекты есть на Node.js, C# и Java.
Тоже уже несколько лет стал применять такой вариант, или гибридный, потому с ростом проекта количество моделей становится большим, папки огромные или папок много, но они раскиданы на слои.
Потому удобнее, когда большая часть фичи и всего его моделей можно уложить в отдельный скоп, в отдельную папку.
Потом деление на namespace так же будет ограничено папкой, и не видеть эти тучи других объектов.
Кто-нибудь пользуется https://fast-endpoints.com?
Мне лично зашло, использую в паре проектов.
А можно задать Вам вопрос новичка? Мне трудно играть Вашими аббревиатурами... (Везде какое-то пристрастие к аббревиатурам! Ну, да, ладно. Ближе к делу!)
А почему у Вас (или у всех нас?) прямо в коде должен фигурировать пользователь и, там, всякие модули обработки заказов?
Я ничего не понимаю в Ваших слоях и расслоениях, но когда говорят о слоях, я всё время думаю о том, что на нижнем уровне (слое) находятся объекты БД. Там есть и пользователи, и заказы, и платёжки. На верхнем уровне (уровне пользовательского интерфейса) есть элементы управления и формы, составляемые из элементов управления. Задача промежуточных слоёв — осуществить отображение нижнего слоя на верхний. Отображение не означает, что на верхнем слое воспроизводится логика нижнего слоя. Она реализуется, а не воспроизводится. Как это кажется, вроде бы, очевидным...
Понимаете? Кажется, что верхний слой должен знать только про то, что вот есть какие-то объекты какого-то одного класса, имеется список объектов данного класса, но с каждым объектом одного класса обязательно связаны объекты других классов, и в каждой конкретной ситуации (предметной задаче) класс этих связанных объектов свой. Вот мы на верхнем уроне и должны решать вопросы управления списками объектов.
Возьмите Вашу четырёхуровневую архитектуру. На самом нижнем уровне находятся таблицы. Выше — отношения и домены (например, описание того, что вот эта сущность — это телефонный номер). Ещё выше логика работы (само приложение), где приводятся алгоритмы работы (безотносительно какого-либо пользовательского интерфейса). А пользовательский интерфейс (причём, конкретный) — это просто обёртка над приложением. У одного приложения может быть много разных интерфейсов. Один — для десктопа. Другой — для смартфона. Ещё один — для банкомата или кассового аппарата. Но! Приложение всегда одно. А обычно разрабатывают различные приложения. При этом, все слои смешиваются. Логика работы везде дублируется. (У любого специалиста от такого дублирования мозги подудонятся могут!) А мне всегда казалось, что смысл слоёв — в чётком разделении задач. Разве не так? Разве не было бы удобнее на уровне концептуальной модели/схемы базы данных описать приложение (один раз и в одном месте!) и автоматически генерировать весь необходимый пользовательский интерфейс?
По слою UI на картинке проведен слайс, да. Но это не значит, что за один слайс будет отвечать сверху до низу один человек. Кто-то может писать БД часть, кто-то UI. На практике фронт часто отделен от бэка совсем, и там может быть вообще своя архитектура и бэкендеру об этом думать не нужно - все варьируется от проекта к проекту.
Но на бэке, вряд ли у вас будет что-то типа "я пишу DTO для этого эндпоинта, ты - преобразование моделей БД в DTO, а вот он - валидацию", условно говоря. Этим, как правило занимается один человек, в рамках одной задачи. Отсюда и логика архитектуры.
Но вот в целом, (прошу прощения если ошибаюсь), вы уже пытаетесь рассуждать нетривиальными абстракциями, имея довольно небольшие представления о том, как это все работает на практике. И проблема тут не в вас: я тонкой нитью по статье провожу, что, по моему мнению, мы слишком усложняем проекты и строим лишние абстракции там, где это не нужно. Что приводит к тому, что нам повально нужны сеньоры, которые смогут во всем этом добре разобраться. А VSA - пример того, как упростить это дело.
Я как-то видел проект, где ребята пытались строить CQRS, DDD и чистую архитектуру, пока в самом проекте было полно веселья типа эндпоинтов, возвращающих статус 200 с ошибкой внутри.
В руби фреймворке hanami, начиная с версии 2, внедрили данный архитектурный подход.
Тоже пробую такой поход (VSA, FSD). Пока нравится. И надеюсь, что это лучше ляжет на работу с LLM. LLM лёгким движением проходится по горизонтальным слоям внося изменения в разных местах и после 5 - 10 таких изменений мозг начинает кипеть (высокая нагрузка на понимание изменений).
Ещё интересн подход от Users stories, но пока попробовать только в планах.
Vertical Slice Architecture на примере C# — простая и удобная архитектура для небольших (и не только) пректов