Как зайти в Даркнет?!
25th January, 01:11
4
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
893
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
912
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4380
0
Помогите пожалуйста решить задачи
24th November, 23:53
6084
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4395
0
Метода Крамера С++
23rd October, 11:55
4308
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2598
0
Как вы передаете сообщения/ошибки уровня обслуживания на более высокие уровни с помощью MVP?
В настоящее время я пишу приложение ASP.Net от UI вниз. Я внедряю архитектуру MVP, потому что я устал от Winforms и хотел чего-то, что имело лучшее разделение проблем.
Таким образом, с MVP презентатор обрабатывает события, вызванные представлением. Вот некоторый код, который у меня есть, чтобы иметь дело с созданием пользователей:
public class CreateMemberPresenter
{
private ICreateMemberView view;
private IMemberTasks tasks;
public CreateMemberPresenter(ICreateMemberView view)
: this(view, new StubMemberTasks())
{
}
public CreateMemberPresenter(ICreateMemberView view, IMemberTasks tasks)
{
this.view = view;
this.tasks = tasks;
HookupEventHandlersTo(view);
}
private void HookupEventHandlersTo(ICreateMemberView view)
{
view.CreateMember += delegate { CreateMember(); };
}
private void CreateMember()
{
if (!view.IsValid)
return;
try
{
int newUserId;
tasks.CreateMember(view.NewMember, out newUserId);
view.NewUserCode = newUserId;
view.Notify(new NotificationDTO() { Type = NotificationType.Success });
}
catch(Exception e)
{
this.LogA().Message(string.Format("Error Creating User: {0}", e.Message));
view.Notify(new NotificationDTO() { Type = NotificationType.Failure, Message = "There was an error creating a new member" });
}
}
}
У меня есть моя основная проверка формы, выполненная с использованием встроенных элементов управления проверкой .Net, но теперь мне нужно проверить, что данные достаточно удовлетворяют критериям для уровня сервиса.
Допустим, могут отображаться следующие сообщения уровня сервиса:
- Учетная запись электронной почты уже существует (сбой)
- Ссылка на введенного пользователя не существует (сбой)
- Длина пароля превышает допустимую длину хранилища данных (сбой)
- Участник создан успешно (success)
Предположим также, что на уровне сервиса будет больше правил, которые UI не может предвидеть.
В настоящее время у меня есть уровень сервиса, который бросает исключение, если все пошло не так, как планировалось. Это достаточная стратегия? Этот код пахнет для вас, ребята? Если бы я написал такой уровень сервиса, вы были бы раздражены необходимостью писать докладчиков, которые используют его таким образом? Коды возврата кажутся слишком старой школой, и bool просто недостаточно информативен.
Редактировать не по OP: слияние в последующих комментариях, которые были опубликованы в качестве ответов OP
Cheekysoft, мне нравится концепция a ServiceLayerException. У меня уже есть глобальный модуль исключений для исключений, которые я не ожидаю. Считаете ли вы, что все эти пользовательские исключения утомительны? Я думал, что ловить базовый класс исключений было немного вонючим, но не был точно уверен, как продвигаться оттуда.
tgmdbm, мне нравится умное использование выражения lambda там!
Спасибо Cheekysoft за последующие действия. Поэтому я предполагаю, что это будет стратегия, если вы не возражаете, чтобы пользователь отображал отдельную страницу (Я в первую очередь веб-разработчик), если исключение не обрабатывается.
Однако, если я хочу вернуть сообщение об ошибке в том же представлении, где пользователь представил данные, вызвавшие ошибку, мне придется поймать исключение в Презентаторе?
Вот как выглядит CreateUserView, когда ведущий обработал ServiceLayerException:
Для такого рода ошибок, это хорошо, чтобы сообщить об этом в том же представлении.
В любом случае, я думаю, что сейчас мы выходим за рамки моего первоначального вопроса. Я поиграю с тем, что вы опубликовали, и если мне понадобится дополнительная информация, я отправлю новый вопрос.
Что звучит правильно для меня. Исключения предпочтительнее, так как они могут быть выброшены в верхнюю часть слоя сервиса из любого места внутри слоя сервиса, независимо от того, насколько глубоко они вложены в реализацию метода сервиса. Это позволяет сохранить код службы чистым, поскольку вы знаете, что вызывающий ведущий всегда будет получать уведомление о проблеме.
Не ловите исключения
Тем не менее, не ловите исключения в presenter, я знаю, что это заманчиво, потому что он держит код короче, но вам нужно ловить конкретные исключения, чтобы избежать ловли исключений системного уровня.
Планирование простой иерархии исключений
Если вы собираетесь использовать исключения таким образом, вы должны создать иерархию исключений для своих собственных классов исключений. В минимуме создайте класс ServiceLayerException и бросьте один из них в свой метод обслуживания, когда возникает проблема. Затем, если вам нужно создать исключение, которое должно/могло бы быть обработано презентатором по-другому, вы можете создать определенный подкласс ServiceLayerException: скажем, AccountAlreadyExistsException.
Затем ваш ведущий может сделать следующее
try {
// call service etc.
// handle success to view
}
catch (AccountAlreadyExistsException) {
// set the message and some other unique data in the view
}
catch (ServiceLayerException) {
// set the message in the view
}
// system exceptions, and unrecoverable exceptions are allowed to bubble
// up the call stack so a general error can be shown to the user, rather
// than showing the form again.
Использование наследования в ваших собственных классах исключений означает, что вам не нужно перехватывать многопильные исключения в вашем презентаторе-вы можете, если есть необходимость, - и вы не можете случайно перехватить исключения, которые не можете обработать. Если ваш ведущий уже находится в верхней части стека вызовов, добавьте блок catch( Exception ) для обработки системных ошибок с другим представлением.
Я всегда стараюсь думать о своем сервисном слое как о отдельной распространяемой библиотеке и выбрасываю такое конкретное исключение, какое имеет смысл. Затем реализация presenter/controller/remote-service решает, нужно ли ей беспокоиться о конкретных деталях или просто рассматривать проблемы как общую ошибку.
Как предлагает Cheekysoft, я бы хотел переместить все основные исключения в ExceptionHandler и позволить этим исключениям всплывать. ExceptionHandler будет отображать соответствующее представление для типа исключения.
Однако любые исключения проверки должны обрабатываться в представлении, но обычно эта логика является общей для многих частей приложения. Поэтому мне нравится иметь такого помощника, как этот
public static class Try {
public static List<string> This( Action action ) {
var errors = new List<string>();
try {
action();
}
catch ( SpecificException e ) {
errors.Add( "Something went 'orribly wrong" );
}
catch ( ... )
// ...
return errors;
}
}
Затем при вызове вашей службы просто сделайте следующее
var errors = Try.This( () => {
// call your service here
tasks.CreateMember( ... );
} );
Тогда в ошибках пусто, вы хорошо идете.
Вы можете пойти дальше и расширить его с помощью обработчиков исключений custome, которые обрабатывают необычные исключения.
В ответ на последующий вопрос:
Что касается создания исключений, которые становятся утомительными, вы как бы привыкаете к этому. Использование хорошего генератора кода или шаблона может создать класс исключений с минимальным ручным редактированием в течение примерно 5 или 10 секунд.
Однако во многих реальных приложениях обработка ошибок может быть 70% из работы, так что это все просто часть игры на самом деле.
Как предполагает tgmdbm, в приложениях MVC/MVP я позволяю всем моим необработанным исключениям всплывать наверх и попадать в диспетчер, который делегирует ExceptionHandler. Я настроил его так, что он использует ExceptionResolver, который смотрит в файле конфигурации, чтобы выбрать подходящее представление для отображения пользователя. Библиотека Java Spring MVC делает это очень хорошо. Вот фрагмент из конфигурационного файла для Spring MVC's Exception resolver - его для Java/Spring, но вы получите идею.
Это занимает огромное количество обработки исключений из ваших докладчиков / контроллеров в целом.
<bean id="exceptionResolver"
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="UserNotFoundException">
rescues/UserNotFound
</prop>
<prop key="HibernateJdbcException">
rescues/databaseProblem
</prop>
<prop key="java.net.ConnectException">
rescues/networkTimeout
</prop>
<prop key="ValidationException">
rescues/validationError
</prop>
<prop key="EnvironmentNotConfiguredException">
rescues/environmentNotConfigured
</prop>
<prop key="MessageRejectedPleaseRetryException">
rescues/messageRejected
</prop>
</props>
</property>
<property name="defaultErrorView" value="rescues/general" />
</bean>