Pull to refresh

Comments 4

Простите, но это капец какой короткий пересказ официальной справки!


На том же fluentvalidation непросто сделать вот что. Как-то понадобилось мне в базе держать данные нескольких пользователей (допустим, заметки) и запрещать показывать чужие. Поэтому даже в самом простом запросе


public class Query : IRequest<NoteDto>
{
    public Query(int currentUserId, int noteId)
    {
        this.CurrentUserId = currentUserId;
        this.NoteId = noteId;
    }

    public int CurrentUserId { get; set; }

    public int NoteId { get; }
}

Я либо дважды лезу в базу (на валидаторе в первый раз, на IRequestHandler<Query, NoteDto> — второй), либо отказываюсь от использования валидатора в handler'е и пишу по-старинке, либо пишу громоздкий некрасивый код (потому что надо проверять связку query+полученный из БД результат).


И в общем, это как-то не особо вдохновляет.

Конкретно для вашего случая (если у вас EF например), проще было бы просто условие в фильтре поставить:


var note = _db.Notes.FirstOrDefault(x => x.UserId == currentUserId && x.Id == noteId)

Но вообще это можно решить с помощью RuleSet'ов

Как-то понадобилось мне в базе держать данные нескольких пользователей (допустим, заметки) и запрещать показывать чужие.

А это не задача FluentValidation. Это — задача слоя бизнес логики, в вашем примере — QueryHandler'а, который должен либо самостоятельно определить текущего юзера, либо получить эти данные из Query, а затем либо делегировать выборку репозиторию (читай — sql запросу), либо самостоятельно отфильтровать данные.

FluentValidation — это библиотека исключительно для Presentation Layer и предназначена только для первичной валидации данных, пришедших от пользователя. Например, что email — это email, а не случайная строка, или что возраст — больше нуля, но меньше 120 и, в случае ошибки — детально сообщить об этом юзеру. С чем и справляется блестяще.
Бизнес слою же вообще желательно работать только с ValueObject, которые должны быть реализованы так, чтобы их в принципе было невозможно создать невалидными, но это уже оффтопик.

И, к вашему примеру, добавлю еще, что RequestHandler не должен возвращать DTO. Опять же, потому что RequestHandler — это слой бизнес логики (модели), а DTO — это Presentation Layer. По этому меняем NoteDto на Note (Entity), в контроллер добавляем AutoMapper (или собственный маппер Note -> NoteDto) и радуемся тому что слои не залезают друг в дружку, а код — чистый, красивый и лаконичный.

Спасибо за комментарий. Да, в итоге на похожем и остановился: что для проверок бизнес-правил эта библиотека не подходит.


Единственное, совет насчёт Dto — спорный. Вот тут или вот в этом приложении (оно не совсем чистый DDD, согласен) декларируется другой подход и вполне успешно применяется.

Sign up to leave a comment.