2012-08-06 3 views
4

я работаю над приложением, где этот процесс продолжается, как этотИсключения стратегии обработки - повторное использование коды исключений

UI --> backend process --> result to UI. 

В моей Java коде, я регулировал свои исключения, используя примерочные поймать, но в коде У меня так много повторных исключений, которые могут вызывать одни и те же исключения в разных классах, что уменьшает читаемость и повторное использование кода.

Итак, я планирую сделать стратегию обработки исключений, чтобы вместо того, чтобы бросать одно и то же исключение в разные классы, мне нужно организовать исключение и повторно использовать коды исключений.

Может ли кто-нибудь предложить мне лучшую технику обработки исключений для этого?

ответ

2

Поскольку у вас есть GUI, который будет использоваться клиентом, клиент должен знать, произошло ли исключение, поэтому лучшим местом для обработки исключений будет ваш верхний слой (тот, который связывается с графический интерфейс).

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

Это означает, что все остальные, более низкие уровни просто выбросят исключение.

Вы можете создать несколько пользовательских исключений и использовать их вместо обычных, (т.е. поймать SqlException и бросить MyDBException с большим количеством деталей, как код исключения, строка запроса и т.д.)

EDIT

Я бы также рассмотреть возможность исключения исключений из 2-х категорий: логических и функциональных.

  1. Logical - проблема с логикой приложения, например, когда пользователь пытается войти в систему с недопустимой имя пользователя/пароль, эти ошибки обычно будут выброшены вами по назначению и будет пользовательских ошибок, которые вы создаете.
  2. Функциональные - все обычные исключения, которые бросаются из-за проблем в самом приложении (например, DB соединения и т.д.)

Тогда вы можете принять решение о стратегии обработки каждого типа. Логические исключения возвращают определенные данные пользователю (неверное имя пользователя/pwd), а исключения Functinal возвращают более общее сообщение типа: возникла проблема, обратитесь в службу поддержки.

3

Всегда ручка Непроверенные Исключения как можно ближе к их источнику, но не создавайте их, это inherently unsafe программирование идиома последней инстанции; когда нет возможности восстановить программу.

При реализации приложения код защитно покупается всегда с использованием проверенных исключений при кодировании для управления исключительными рабочими потоками; например, когда ваш код не выполняет свой интерфейс «Contract».

Приложение не должно вылетать с неконтролируемым исключением, поскольку оно не может попасть в систему оценки кредитоспособности третьей стороны. Отключите эту опцию и продолжите создание клиентских клиентов.

Обобщите обработку исключений, но специализируйте их создание. например

CustomerNotFound extends CustomerException 
CreditCustomerNotFound extends CustomerException 
CashCustomerNotFound extends CutomerException 

{ 
    aCustomer = customerList.find(...) 
} catch CustomerNotFound() { 
    logger.warn(...) 
    throw CustomerException(CustomerNotFound) 
} 

InvoiceAddressException extends InvoiceException 

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

Выполняйте общую обработку и отчетность как можно ближе к пользовательскому интерфейсу.

+0

-1, для многих проверенных исключений была плохая идея, прочитал Джошуа Блоха, Брюса Эккела и многих других ... И посмотрите на любые современные Java-рамки. Spring, Hibernate, JPA, CXF ... все они используют исключенные исключения, и это прекрасно, чтобы поймать DataAccessException для создания определенного рабочего процесса. –

+0

Обратите внимание, что создатели C# вдохнули вдохновение из Java и решили не помещать проверенный механизм исключения в C#, потому что это считается некорректной функцией. Даже Scala не выполняла проверенные исключения. –

+0

Вместо того, чтобы подавлять нисходящие голоса от гнева, не стесняйтесь объяснять, почему вы не согласны с тем, что я ответил. –

1

Я хотел бы показать подход, ориентированный дизайн для этого,

  1. во-первых, «Мартин Spamer» правильно, как нам нужно, чтобы поймать только проверяемое исключение .... но в очень детальном уровне ... например InvalidCredentialException и AuthorizationException не следует бросать/улавливать как LoginException, потому что, предположите, вы бросаете его как исключение одного типа, а затем вас просят обрабатывать эти типы по-разному в будущем, тогда?

  2. во-вторых, там ярусы UI ----> передний ярус ----> сервис уровня -----> DAO ярус

Логика должна быть,

(i) фронт-ярус получит запрос от пользовательского интерфейса и обработает проверки/исключения на основе front-end (например, MissingUserNameException при входе в систему). Если все в порядке, то переадресация запроса на уровень обслуживания

(ii) служба будет проверять логику бизнеса и, если она действительна, то она обработает запрос. Если это не произойдет, это приведет к исключению из правильного сообщения для внешнего уровня

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

Этот подход будет иметь еще одно дополнительное преимущество. Предположим, что возникает требование, когда вам нужно выставить некоторые бизнес-методы в качестве веб-сервиса ... так что ваши службы будут выставлены в любом случае. Теперь, если вы поместите всю обработку исключений (т.е. преобразование исключения в правильное сообщение), логика в интерфейсном уровне и уровне обслуживания полностью не осознает их ... тогда это будет беспорядок, когда вам нужно снова реорганизовать свой код уровня обслуживания (а также передний уровень). Даже несколько раз позже может возникнуть другая ситуация, когда ваша технология переднего уровня становится устаревшей, и вам придется перекодировать всю логику обработки исключений в новых технологиях.

Таким образом, нижняя строка, уровень обслуживания должен знать + обрабатывать все исключения для проверки бизнеса с надлежащим сообщением. После оформления исключения правильным сообщением он передаст его на клиентский уровень, из которого вызывается служба. Теперь это ответственность клиентского уровня, чтобы показать сообщение и украсить его снова каким-либо другим сообщением, если это необходимо. Таким образом, вы можете сохранить все уровни независимыми.

-2

Edit: Оригинальный ответ переехал сюда в ваш другой вопрос: https://stackoverflow.com/a/16172074/82609

Чтобы сохранить свой ответ в рамках вопроса, вот интересные детали:

Избегайте исключений коды

Тип исключения должен быть достаточным для принятия решений по управлению потоком.Разбор исключений или управление потоком создадут бесполезный код. Добавьте больше типов исключений, сколько у вас есть коды исключений.

Пункт 39: Используйте исключение только для исключительных условий (Effective Java главы Jochua Блохи):

Пункт 39: Используйте исключение только для исключительных условий. То есть, не используйте исключения для потока управления, такие как catching NoSuchElementException при вызове Iterator.next() вместо первой проверки Iterator.hasNext().

В функциональных языках мы используем исключения только для действительно исключительных условий. Исключительное условие - это нечто вроде «невозможно подключиться к базе данных», а не что-то вроде «пользователь не предоставил требуемое количество статьи во входном тексте». Это не является исключительным, это бизнес-ошибка.

Язык Java не очень помогает, но в идеале вы можете вернуть эту бизнес-ошибку в качестве вывода функции (например, экземпляр EnumAddBasketError) вместо создания AddProductToBasketWithoutQuantityException. На практике люди склонны поднимать исключение, нарушая нормальный поток управления и замедляя приложение (исключения имеют стоимость).

Избегайте проверяемые исключения

Читайте мой другой ответ здесь: https://stackoverflow.com/a/16172074/82609 проверяемых исключений для восстанавливаемых отказов (рекомендации Sun). Неиспользуемые исключения легче справляться с неисправимыми отказами.


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

+0

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

+0

Хорошо, извините, тогда. Это не мое изобретение, но по моим ссылкам и Брюс Эккель, и Джошуа Блох, как правило, говорят, что было бы лучше без проверенных исключений. Обратите внимание, что есть глава «Мышление в Java», называемая «Избегайте ненужного использования проверенных исключений», и что, как я помню, сказано что-то вроде «если вы не знаете, что использовать, используйте непроверенные исключения». –

+0

Btw @MartinSpamer это правда, мой ответ имеет больший объем, чем вопрос, но поскольку у первоначального автора был поставлен еще один вопрос, я подумал, что это может ему помочь: http://stackoverflow.com/questions/11819052/java-exception-handling- Стратегия –

0

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

http://docs.oracle.com/javaee/6/tutorial/doc/bnbpj.html

Это ставит этот вопрос в простом контексте. Когда люди не привыкли к исключениям (например, скрипты/функциональные программисты), они говорят о том, что используют только RuntimeExceptions ..., которые заставляют вас загрязнять внешний интерфейс с неуправляемыми ошибками, возникающими в пользовательском интерфейсе. (Я не считаю, что очень удобно, если вы считаете, программный код в долгосрочной перспективе ... ремонтопригодности)

http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

Если клиент может занять некоторое альтернативное действие, чтобы оправиться от исключения, сделать это проверенное исключение. Если клиент не может сделать ничего полезного, сделайте исключение непроверенным. К полезным, я имею в виду принятие мер для восстановления из исключения, а не только для регистрации исключения.

(Есть сообщения о лесозаготовительных модели с исключениями, но я не буду там в этом, как она замолкает)

трудно обнаружить непроверенные исключения, и они легко получить передать свой «близко к источнику «ловить. (Если они не отмечены, они будут невидимы для кода клиента и проскользнут).

Мне поставили под сомнение эту проблему с некоторым устаревшим кодом, бросающим много неконтролируемых исключений, которые теперь приводят к крушению пользовательского интерфейса. (из-за ненадежных услуг)

Возможно, «у каждого» есть свое мнение, как правильно поступать, но я пытаюсь создать общий шаблон для обнаружения ошибок (исключенных исключений), близких к пользовательскому интерфейсу, и представления их с хорошей ошибкой popups (JSF кстати) вместо того, чтобы направлять пользователя на страницу «error.xhtml» (введено в web.xml).

// Для вышеуказанного сценария я придумал это решение.
Это даже, кажется, работает очень хорошо.

  1. Создайте аннотацию привязки перехватчика и перехватчика.
  2. Аннотировать классы или методы, по которым вы хотите, чтобы их пузырящиеся EJBExceptions были дезинфицированы.
    • Не перехватывайте все или не получаете ненужную обработку/накладные расходы. Просто используйте его там, где он вам действительно нужен, на уровне BackingBean/ManagedBean.

Перехватчик связывания аннотаций

@Inherited 
@InterceptorBinding 
@Target({ ElementType.TYPE, ElementType.METHOD }) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface InterceptEJBExceptions {} 

Перехватчик

@Interceptor 
@InterceptEJBExceptions 
public class EjbExceptionInterceptor { 
    @AroundInvoke 
    public Object interceptBubblingExceptions(final InvocationContext context) throws Exception { 
     try { 
      return context.proceed(); 
     } catch (MySpecificEJBException msejbe) { 
      Object[] args = { msejbe.getErrorCode(), msejbe.getMethodSignature(), msejbe.getParameters()}; 
      // This would create a FacesMessage in JSF 
      addErrorMessageToFacesContext(null, summary_template, details_template, args); 
     } catch (EJBException ejbe) { 
      super.addErrorMessageToFacesContext(null, "Unspecified EJBException", ejbe.getMessage()); 
     } 
     // "Pure" RuntimeExceptions will fall through and will be shown on 'error-page' specified in web.xml 
     return null; 
    } 
} 

beans.xml

<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> 

    <interceptors> 
     <class>xxx.xxx.xxx.exception.interceptor.EjbExceptionInterceptor</class> 
    </interceptors> 
</beans> 

Использование в Java-Классе s

@RequestScoped // Class must be in EE context 
// @InterceptEJBExceptions // Have the annotation at class level to intercept all method calls in this class 
public class MyBB { 
    @InterceptEJBExceptions // Only intercept when this method gets called 
    public String myEjbExceptionThrowingActionListener(Object obj) { 
     // Some code that may throw an EJBException 
    } 
} 

MySpecificEJBException бы класс Exception расширения EJBException. Постройте класс так, как вам нравится переносить полезную информацию для последующего ведения журнала и для отображения чистых сообщений об ошибках на экране вместо того, чтобы вызывать исключение на экране с или без error-страница, определенная в web.xml (что также должно имеют в качестве резерва).
Не забудьте указать оригинальное исключение в классе!

Создайте больше своих собственных Исключений, расширяющих EJBException по мере необходимости и бросайте их по своему усмотрению (в качестве RuntimeExceptions они не отмечены). Затем просто добавьте блок catch в перехватчик и сделайте сообщение о регистрации и/или ошибке, отображаемое для этого случая.

В общем:

  • Используйте проверенные исключения, где вы можете реагировать на ошибки.

    • В Java 7 вы можете использовать следующий синтаксис для группировки Исключения, которые можно обрабатывать аналогичным образом.

      попробовать {...} задвижка (SomeException | OtherException е) {...}

  • Если у вас есть много проверяемых исключений, вы можете/должны, возможно, сгруппировать их по категориям (расширить некоторые более общее исключение). Затем вы можете поймать на основе этого исключения группировки (в дополнение к/вместо группировки catch-clauses).

  • Включите эти исключения в EJB/RuntimeExceptions, которые загрязняют вас кодом (если вы действительно ничего не можете сделать близко). Затем они должны быть захвачены и обработаны общим кодом EjbExceptionInterceptor. Перехватчик поймает исключение => покажет чистое сообщение об ошибке/всплывающее окно, но пользователь останется на одной странице без потери данных, над которыми он/она работал.
  • Избегать бросать равнину RuntimeException. Они сигнализируют ошибку в коде (мое мнение) и вышеперечисленный перехватчик позволят им провалиться на странице ошибок . Это также отключит пользователя от страницы, на которой он сейчас находится.
    • Эти ошибки должны быть всегда исправлены с высоким приоритетом (например, NullPointerException сделает это).
    • Также: Не бросайте Исключения практически обо всем, это будет плохое программирование. Если ваш код может что-то сделать с ошибкой перед рукой (например, использовать перегруженные методы или значения по умолчанию, чтобы предотвратить использование нулевых параметров), тогда сделайте это, не пропустите проблему клиенту (метод вызова). Это просто ленивое программирование + использование RuntimeExceptions, чтобы скрыть эти ошибки, просто безответственно! Пробные испытания!


Я не смог найти какое-либо фактическое решения для обработки (как образец) ошибки, но через много дискуссий, что правильно и что неправильно. У нас есть 2 типа Throwables, так почему бы им не использовать их конструктивно?
Вместо продолжения этой дискуссии я надеюсь, что это будет реальное решение и сделает трюк.

Буду признателен всем конструктивным комментариям и предложениям по улучшению.

Смежные вопросы