Передача ошибки бизнес-валидации из сервисного уровня в уровень презентации - PullRequest
4 голосов
/ 18 декабря 2009

Мы используем шаблон MVP в нашем уровне представления (PL) и уровне обслуживания на основе WCF (SL). PL вызывает операционные контракты на SL и внутренне выполняет некоторые бизнес-проверки. Если проверка прошла успешно, мы возвращаем объект (представленный как контракт с данными) в PL.

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

Entity2 Operation1(Entity1 e)
{
 //Do some business validation and if passes pass on the updated object back to PL
}

Одним из способов является создание общего класса ответа, который является общим для всех контрактов на операции. Это будет выглядеть примерно так.

public class Response
{
    public ExceptionType exceptionType;
    public ExceptionInfo exceptionInfo;

    Collection<Entity> entityCollection;
}

ExceptionType: это перечисление, в котором указывается, произошла ли ошибка BusinessValidation, SecurityValidation или произошло какое-то неизвестное исключение.

ExceptionInfo: это перечисление, которое сообщает конкретные детали проверки / исключения, произошедшего, например, errorCode и т. Д.

Коллекция: сервисный уровень может возвращать один объект или набор объектов. Мы используем это свойство для возврата объекта или объектов согласно требованию. Он также может быть нулевым также в случае, если произошла ошибка проверки или метод не ожидает какой-либо возвращаемой сущности от уровня обслуживания.

Это хороший подход для передачи ошибок валидации в PL.

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

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

Есть еще идеи по поводу этого сценария?

1 Ответ

2 голосов
/ 30 декабря 2009

Рассмотрим:

Как вы сообщаете сообщения / ошибки сервисного уровня верхним уровням, используя MVP?

Я не уверен, как конкретно помочь здесь. Во-первых, я не очень разбираюсь в ваших настройках и не знаю ничего о деталях WCF. Во-вторых, я не получаю комментарий о неприязни к исключениям для бизнес-логики ... но я предполагаю, что вы имеете в виду «проверку бизнеса», как вы заявили в другом месте (в этом случае, это имеет смысл для меня).

В моем невежестве, похоже, у вас есть начало вашей собственной схемы, так что, возможно, у вас много свободы. И, конечно, многие вещи могут работать. Итак, вот несколько альтернатив:

Способ связи

Вы можете просто попробовать свой подход и посмотреть, как вам это нравится. IMO, это смешивание проблем для проверки и совместной работы (иногда это не помогает, особенно если вы начинаете спрашивать, как обрабатывать сбои). Command-Query, кроме всего прочего, это классическая проблема return-vs-throw, и на этой границе у вас есть право выбрать любой из них, пока он работает.

Если у вас есть фреймворк для вашего MVP, вы можете посмотреть, есть ли в нем что-то встроенное.

За исключением этого, вы можете изменить отношения PL / SL, чтобы явно отделить проверку от операции. Вот так:

IList<Error> Validate_Operation1(Entity1 a){}
Entity2 Operation1(Entity1 a){}

Или, чтобы быть сумасшедшим:

public interface ICommand
{
    IList<Param> Params { set; }
    IList<Error> Validate();
    void Execute();
}

Если бы я строго отличал «Ошибки валидации» от «Ошибки пост-валидации» и «Неожиданные ошибки», я мог бы сделать выше. Возвращение проблем проверки в результате запроса проверки, конечно, не является «исключительным».

Помимо всего этого, вы можете подумать о том, чтобы немного более абстрактно понять, что вы собираетесь делать с ошибками после проверки. Некоторые из них могут быть действиями пользователя, независимо от того, связаны ли они с бизнесом. «Datatraveler кажется поврежденным. Пожалуйста, переформатируйте флэш-накопитель». Или даже предупреждения типа «Настройки не найдены, дополнены настройками по умолчанию». Если ваше приложение обладает высокой интерактивностью, ваша болтливая SL может использовать более общий механизм для отправки вопросов проверки.

Содержание сообщения

Я не считаю ваши сущности Response-class-with-error-enums-and-null-юридических лиц миль отличающимися от определения вашего собственного класса ошибок или исключения, если честно. Я не особо разбираюсь в «многоцелевом» возврате, подобном этому, но есть подход для такого подхода: многие EventArgs или асинхронные аргументы обратного вызова реализованы так, чтобы иметь информацию об ошибке, отмене и результатах.

Что касается перечисленных вами недостатков, я не уверен, насколько широка иерархия ошибок, когда вы говорите, что «PL должен обрабатывать все случаи, определенные в exceptionInfo», поэтому простите, что я предположил наихудшее здесь. Выбранное вами транспортное средство (исключения, простые строки или перечисление исключения) не меняет того факта, что если вы распознаете 762 различных ошибки, вы узнаете 762 различных ошибки.

Но это не значит, что ваши докладчики должны четко учитывать каждого из них. Вы получаете выгоду от контекста - вы знаете, что вы не получите «Имя пользователя было пустым» после того, как пользователь уже вошел в систему и проверил баланс ипотеки. (И если вы это сделаете, вам, вероятно, следует рассматривать это как «непредвиденную ошибку при проверке баланса. Пожалуйста, повторите попытку позже» и зарегистрируйте стек вызовов, верно?)

Так что вашему докладчику нужно знать только короткий список, который относится к его контексту, а не все. Все остальное "Неожиданно ...".

И, так как вы определяете свой собственный класс Error, вы можете рассмотреть возможность помещения своих ошибок в строковые ресурсы и привязывания идентификатора ресурса к конкретной ошибке при создании объекта. Затем, вместо индивидуальной обработки случаев, многие из них могут быть решены одним и тем же действием: Получить идентификатор, загрузить строку, показать строку, выполнено. Выписка переключателя не требуется.

...