Mediator Logo.png

Этой весной в чатах и сообществах dotnet (не забываем #DropTheDot) обострились анти-медиаторные настроения. Поначалу меня это забавляло, потом удивляло: люди подхватывают лозунги, не пытаясь разобраться в вопросе. Квинтэссенцией обострения стал доклад Андрея Парамонова "MediatR не нужен”, шокирующий своей категоричностью аргументов. В докладе были зерна истины, но они к концу так и не проросли.

Желание прорастить эти зерна и мой крайне положительный опыт использования медиатора в проектах разного типа и размера смотивировали меня написать данную статью. Статья основана на личном опыте и наполнена эмоциями, за это заранее извиняюсь 🤭 Будет интересна она скорее людям, которые уже знакомы с медиатором, встречались с ним в теории или на практике.

С чего медиатор начался и где он сейчас

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

Медиатор как design pattern

Медиатор - шаблон проектирования, design pattern, про который можно прочитать в разных книжках, или, например, вот здесь.

Выглядит он примерно вот так:

Медиатор как design pattern

Медиатор как design pattern

Согласитесь, мало похоже на то, что мы видим в обсуждениях и страстях вокруг медиатора, но, тем не менее, этот шаблон вдохновил появление известной и обсуждаемой, той самой, библиотеки. Тут нет никаких Behavior-ов, Request-ов, Notification-ов, нет даже команд и запросов. Суть шаблона в разрыве зависимостей между объектами введением медиатора как дополнительного связующего звена. Медиатор занимается построением общения между объектами, которые раньше общались друг с другом напрямую.

The library

Библиотека за авторством Jimmy (автора другой скандальной либы AutoMapper). Библиотека очень простая: написать ее вы сможете буквально за день, а за два дополнить тестами. Это если знать, что писать, и выкинуть новые фичи, типа поддержки AsyncEnumerable. Чем же эта библиотека отличается от шаблона выше? Тем, что это реализация шаблона определенным конкретным образом, с новыми введенными абстракциями, такими как Request, Handler и Behavior. Здесь впервые появляются определенные тенденции организации кода под эту библиотеку. Теперь любой класс-сервис* можно представить в виде комбинации Request-ов и их Handler-ов. Каждый метод становится Handler-ом, а его сигнатура превращается в объект-запрос Request.

*такой класс, который не имеет состояния, а скорее является просто сгруппированным набором функций

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

Архитектурный стиль в контексте чистой архитектуры

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

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

Упрощенная схема организации кода на основе чистой архитектуры

Упрощенная схема организации кода на основе чистой архитектуры

Application + Domain это ядро нашего приложения. UI (слева) это точка доступа в наше приложение, и Infrastructure (справа) это внешние зависимости, к которым мы иногда обращаемся. Мы не хотим засорять ядро приложения, поэтому финтом под названием инверсия зависимостей мы вынесли инфраструктурные зависимости в отдельный слой. Вызывать их можно посредством интерфейсов, которые являются частью ядра приложения, реализации же этих интерфейсов лежат в инфраструктурном слое. На входе сразу после UI у нас идут сервисы с набором методов, часть из которых отдает данные, а часть их меняет.

Так где же место медиатора во всей этой схеме? Опытом наших предков выяснилось, что удачнее всего он встраивается на границе между UI и Application. Давайте посмотрим на вариант с медиатором.