• MediatR за межами Vertical Slice Architecture. Чому ви можете використовувати його неправильно

    Нажаль на гітхаб проекти таких посилань немаю. Проекти, з якими мені видавалось працювати в приватних репозиторіях.

    Приклад з CQRS був і у Богарда в поясненні переваг Vertical Slice Architecture, але чисто технічно я не бачу великої проблеми зробити це і без MediatR в «класичній» архітектурі.
    Просто в кожен контролер (якщо це треба в межах одного контролеру) буде інжектатися два сервіси — для Query і для Command.

    Я пробував такий підхід на одному з сервісів в якості експерименту — як результат такі сервіси (їх інтерфейси) дуже швидко виросли, і потрібна дисципліна і постійний нагляд за цим. Та й з неймінгом починаються цікаві штуки типу QuerySuperService, etc.

    Словом, це все можна, але для чого придумувати те, що вже реалізовано і працює доволі добре? З мого досвіду дизайн системи завжди і без того складний, і простіше використати існуючий інструмент, а не витрачати ресурси на побудову свого, який в кінці буде вирішувати ті ж задачі, і вимагати ефорти для її підтримки.Звичайно, якщо одним з constrains є вимога не використовувати вендорні бібліотеки то мій коментар не є доцільним.

    Цікаво, а що саме у випадку з AOP виглядало або працювало гірше?

    Проблеми з відсутністю типізації, це те що найбільш вистрілювало в ногу. Все працює, до поки хтось не вирішить змінити ієрархію базових типів, або щось на кшталт того. Останній раз я з цим стикався в 2019-2020, можливо щось змінилось, і я помиляюсь.

  • MediatR за межами Vertical Slice Architecture. Чому ви можете використовувати його неправильно

    На мою думку одним з важливих нюансів використання MediatR успішно є передумова побудови так званого Task-based interface, коли команди доволі гранулярні а квері зазвичай вертають багато інформації. З описаного прикладу в мене склаласу думка що за основу взято простий CRUD (Get Order, Create Order, Get Product, Create Product), і тут я погоджусь що змісту в використанні бібліотеки немає. Проте коли мова іде про task-based зазвичай дії більш гранулярні, і часто компонують кінцевий об’єкт (продукт, чи ордер) в декіка кроків.

    Архітектурно за допомогою бібліотеки простіше реалізовувати Clean Architecture, так як більшість оркестрації буде в командах, навіть якщо вони залежні на інші інтерфейси бізнес рівня, і таким чином команда є бізнес агрегатором, в той час як залежності на application layer interfaces в контролері і агрегацію юз кейсів там є швидше порушенням Clean Architecture, бо контролери належать до інфраструктури, яка є несуттєвою і часто міняється.

    Декілька слів по секціях:
    — Допомагає дотримуватися принципу одного обов’язку (Single Responsibility Principle)? Знову ж таки архітектурно бібліотека допомагає реалізувати підхід CQS, або CQRS (залежить від вимог проекту і потреби). Останній передбачає використання Materialized Views — коли читання вертає велику кількість інформації. На моїй практиці це так і працює, тому за декілька років використання не зустрічався з описаною проблемою коли є десяток кверів які детально вертають дані. Швидше за все тут щось не так архітектурно, і вибір бібліотеки для цього кейсу був хибний.

    — Вирішує проблему надмірної кількості залежностей в конструкторі? Допомагає, і задає тон на вищому рівні, привчаючи розробників до того що кількість залежностей можна і треба обмежувати.

    — Спрощує навігацію в коді? На перших проектах де використовував бібліотеку справді було трохи незручно мати квері і хендлер в різних файлах. Проте в C# 9 додали records, і так як command гранулярна (читай вище чому) то зазвичай record має 2-3 проперті і пишеться в одну лінійку коду не перевищуючи 120-150 символів. Таким чином і команді і хендлер в одному файлі. Проблема навігації вирішена

    — Дає можливість реалізовувати наскрізний код? Часково погоджусь, проте автор згадує контректні бібліотеки для AOP, і насправді на ринку для .NET їх доволі обмежена кількість. До того ж перформанс вимагає кращого. Проте не погоджусь з «Будь-який із них забезпечить більшу гнучкість в реалізації наскрізного коду, ніж MediatR, і не вплине на структуру вашого сервісу та його внутрішні класи.» — я пробував різні варіанти для AOP, проте з MediatR вдалось створити найкращий варіант який працює як для REST комунік так і для messaging, коли перед командою виконуються пайплайни. Думаю тут справа смаку, проте памятати потрібно, що AOP це як мін окремий концепт, і який на рівні компіляції може пропускати низку потенційних проблем, у випадку використання runtime AOP.

    На основі висновку — застосування в багаторівневій архітектурі, це дуже абстрактне потяння, так як зазвичай є декілька варіантів імплементації цієї архітектури, і так як бібліотека це деталь імплементації, то тут порівняння нетотожне. Я б виходив з аналізу типу реалізації, і розглядав MediatR з точки зору того, які проблеми в цій реалізації вона допоможе вирішити.

    Підтримав: Sergey Boryssenko