All streams
Search
Write a publication
Pull to refresh
0
0
Касболат Кумахов @uhfath

Разработчик

Send message

Ну на мой взгляд это не корректно сравнивать — событие и вызов сервиса. Как вы одно другим заменяете?

Команду. Через Send().

Какой то у Вас надуманный пример)
Как часто Вы на асинхронные операции переделываете? Ну, максимум один раз.
Т.е. по факту плюс только в том, что заставляет везде task в качестве результата использовать. Сейчас, думаю, это практически везде по дефолту так. Есть реальные примеры?)

Достаточно взять любую ситуацию с необходимостью изменения контракта.


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

Эмм. Вот прямо сейчас в текущем проекте проверил. Убрал хендлер.


[18:43:49 ERR] An unhandled exception has occurred while executing the request.
System.InvalidOperationException: Handler was not found for request of type MediatR.IRequestHandler`2[MedService.API.Logic.Features.Auth.Commands.SignInCommand,MedService.API.Contracts.Auth.SignInResponse]. Register your handlers with the container. See the samples in GitHub for examples.

Ну простой пример, первый пришедший в голову.
Имеем данные и сервис-валидатор, описанный контрактом:


Пример сервиса
public class SomeData
{
    public int SomeValue { get; set; }
}

public interface IValidatorService
{
    public IEnumerable<string> Validate(SomeData someData);
}

internal class ValidatorService : IValidatorService
{
    public IEnumerable<string> Validate(SomeData someData)
    {
        if (someData.SomeValue != 10)
        {
            return new[]
            {
                "Something must have gone very wrong!", 
            };
        }

        return Enumerable.Empty<String>();
    }
}

Ничего необычного. Используем тоже по простому:


Пример использования
void Test(IValidatorService validator)
{
    var badData = new SomeData
    {
        SomeValue = 20,
    };

    validator.Validate(badData).Dump("Bad");

    var goodData = new SomeData
    {
        SomeValue = 10,
    };

    validator.Validate(goodData).Dump("Good");
}

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

Что бы меньше связей отслеживать при изменениях.
Можно провести аналогию с микросервисами, которые общаются через брокер (RabbitMq, Kafka и т.п.).
Один микросервис постит сообщение (запрос или команду) в брокер, не зная кто его будет обрабатывать. А обрабатывать его будет "кто-то". И вот этого "кто-то" можно в любой момент поменять. Даже никаких контрактов соблюдать не надо. Главное уметь обрабатывать запрос.

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


Да, можно сделать интерфейс сервиса и отдать контроллеру.
Один интерфейс, ещё один, потом ещё парочку.
Или сказать всем контроллерам "работай только через этот сервис" и "используя вот эти DTO (request)".
А вот реализации уже могут лежать где угодно.
С одной стороны свобода действий. Но с другой — вероятность хаоса (хендлеры разбросаны повсюду). Поэтому важно правильно организовать процесс. У нас примерно так:


Features
|-- Queries
    |-- AppQuery
        |-- AppQuery.Handler <-- вложенный приватный класс
|-- Commands
    |-- AppCommand
        |-- AppCommand.Handler <-- вложенный приватный класс

В таком варианте CTRL+CLICK по запросу и сразу виден его хендлер.
Но подходит только для схемы "один запрос, один хендлер".
Ну и плюс ивенты. Бывает удобно.


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


В общем штука интересная для проектов с кучей контроллеров.
Для проектов попроще добавляет больше boilerplate кода.

А если сделать так?
Для этого нужно отключить оплату для всех проектов.

Этого достаточно для дальнейшего использования без создания ИП?
Такое ощущение, что письмо коснулось тех кто не ИП, но включил оплату в настройках.
Я вот не ИП и оплаты у меня нет. Хотя она была где-то очень-очень давно включена в недрах AppEngine для тестов, когда Firebase еще не был куплен гуглом.
Письмо не приходило.
2

Information

Rating
Does not participate
Location
Нальчик, Кабардино-Балкария, Россия
Date of birth
Registered
Activity

Specialization

Backend Developer, Application Developer
Senior
From 200,000 ₽
C#
.NET
OOP
PostgreSQL
Entity Framework
.NET Core
Microsoft SQL Server