DDD Использование шаблона спецификации для проверки
Я думаю использовать шаблон спецификации для целей проверки. Трудно сказать, как указать пользователю, почему некоторая спецификация не была удовлетворена. Что делать, если Specification.IsSatisfiedBy()
не только вернет значение bool
, но и причину сбоя. Он будет выглядеть примерно так:
interface ISpecification<T>
{
CheckResult IsSatisfiedBy(T candidate);
}
где CheckResult
:
class CheckResult
{
public bool IsSatisfied { get; }
public string FailureReason { get; }
}
В Fowler and Evans существует концепция частично удовлетворительной спецификации, целью которой является дать объяснение, что именно не было выполнено. Однако в этом документе он реализован как дополнительный метод restundUnsatisfiedBy, который возвращает спецификацию, которая не была выполнена Кандидатом.
Итак, вопрос: при использовании Спецификации для целей валидации, как обеспечить обратную связь с пользователем о том, что данная Спецификация не была удовлетворена? Является ли решение, которое я представил выше, хорошо?
Ответы
Ответ 1
Хотя вы можете использовать классы спецификаций для проверки, я бы предложил вам сохранить их как отдельные концепции в вашем домене. Вы можете обнаружить, что вам нужно повторно использовать одни и те же базовые спецификации, но вам нужно вернуть разные "причины отказа" в зависимости от цели и контекста. Подробнее см. в этой статье.
Автор сообщения, упомянутого выше, также любезно передал код github и разместил код как NCommon. Просмотрите эти области, в частности:
Технические характеристики: https://github.com/riteshrao/ncommon/tree/v1.2/NCommon/src/Specifications
Валидации: https://github.com/riteshrao/ncommon/tree/v1.2/NCommon/src/Rules (особенно классы для ValidationResult и ValidationError)
Ответ 2
У меня была та же проблема. Я создаю декоратор проверки для спецификации (код JAVA).
interface Validator<T>{
Respond validate(T t)
}
class abstract ValidationSpecificationDecorator<T> implements Validator<T> {
Specification<T> spec;
ValidationSpecificationDecorator(Specification<T> spec){
this.spec = spec;
}
public Respond validate(T t) {
Respond respond = new Respond();
if(!spec.IsSatisfiedBy(t){
respond.add(error(t));
}
return respond;
)
public abstract Error error(T t);
}