2016-07-05 2 views
2

В нашей конструкции системы мы следующие слои:Исключения - Пользовательские исключения на каждый слое

Web API -> BusinessLayer -> HelperLayer -> DataLayer - Call hierarchy 

Web API является уровнем услуг отдыха, бизнес делает бизнес-операции на субъекте предпринимательской деятельности, помощник делает преобразование данных организация для хозяйствующего субъекта и выборки данных РоКо из базы данных

Как мы обсуждаем стратегию управления исключение из системы, являются следующие два вида:

я предпочитаю, что все ошибки будут распространяться до Web API, порога е мы используем фильтр ошибок для перехвата, журнала ошибок и изменений Context.Response обеспечить дружественное сообщение для конечного пользователя, преимущества то же:

  1. Источника ошибки остается неповрежденным

  2. Мы обрабатываем исключение, когда его требуется

  3. Простой и понятный механизм для обработки

ошибки Что другой набор товарищи по команде предпочитают, мы создаем настраиваемое исключение для каждого уровня, такое как DALException, HelperException, BusinessException, где данный слой генерирует исключение, вызывающий слой обрабатывает его, заполняет внутреннее исключение и, таким образом, продолжает, по своему преимуществу:

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

Для меня проблема с этой конструкции:

  1. Изменение источника of exceptio п что Nopt хорошая практика
  2. Ловля исключение без обработки
  3. Лот дополнительного кода путем добавления попробовать поймать везде, что может повлиять на производительность в моем понимании

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

Пожалуйста, разделяю Ваше мнение и дайте мне знать, если уточнение требуется

+0

Почему ярлык java? – GhostCat

+1

В моем понимании это очень общий вопрос дизайна, действительный как для C#, так и для Java, даже когда мой код находится в C# –

ответ

1

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

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

Существует множество способов реализации перехвата. Это может зависеть от того, какие инструменты уже включены в ваши приложения. Я использую Windsor для инъекции зависимостей, поэтому удобно использовать их перехватчики.Если бы я не использовал Windsor, я бы посмотрел на PostSharp.

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

99% времени это позволяет мне не иметь try/catch блоков в моем коде вообще. Регистрация и реинтронирование отводится на перехватчики. Единственный раз, когда у меня есть обработка исключений, нужно обработать что-то изящно, поэтому мне нужно поймать исключение, зарегистрировать его и вернуть результат без исключения.


Unrelated перехвату:

На практике, я обнаружил, что большую часть времени, имеющий один тип исключения против другого или исключений оборачивания на других типах бесполезно. 99% битвы просто имеют детали исключения, не имея ничего. Пока никто не делает throw ex (уничтожая трассировку стека), вы получите то, что вам нужно в деталях исключения. Если мы получим умные исключения для обертывания в более исключительных случаях, тогда мы просто создадим больше информации, которую мы будем игнорировать. У нас будет больше деталей для просеивания, поскольку мы ищем одно, на что мы действительно заботимся - что было исключением и где оно было брошено?

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

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

+0

Спасибо за детали, многое из этого имеет смысл в моем случае –

1

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

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

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

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

+0

Большое спасибо, имеет смысл смысла –

0

А как насчет перебора исключений с исключением цепочки и разбора этой цепочки в фильтре (выберите только первое исключение в цепочке (причина) или проанализируйте все контексты для всех слоев)?

class App { 
    public static void main(String[] args) { 
     View view = new View(); 
     try { 
      System.out.println(view.doRender()); 
     } catch (ViewException e) { 
      System.out.println("ERROR: " + unrollChain(e)); 
     } 
    } 

    static String unrollChain(Exception e) { 
     Throwable current = e; 
     while (current.getCause() != null) { 
      current = current.getCause(); 
     } 
     return current.getMessage(); 
    } 
} 

class View { 
    private Business business = new Business(); 

    String doRender() throws ViewException { 
     try { 
      return "<html>" + business.doBusiness() + "</html>"; 
     } catch (BusinessException e) { 
      if (System.nanoTime() % 2 == 0) 
       throw new ViewException("Some context if have one", e); 
      else 
       throw new ViewException(e); // no local context, pure rethrow 
     } 
    } 
} 

class Business { 
    private Dao dao = new Dao(); 

    int doBusiness() throws BusinessException { 
     try { 
      return dao.select() + 42; 
     } catch (DaoException e) { 
      if (System.nanoTime() % 2 == 0) 
       throw new BusinessException("Some context if have one", e); 
      else 
       throw new BusinessException(e); // no local context, pure rethrow 
     } 
    } 
} 

class Dao { 
    int select() throws DaoException { 
     if (System.nanoTime() % 2 == 0) 
      return 42; 
     else 
      throw new DaoException(); 
    } 
} 

class DaoException extends Exception { 
} 

class BusinessException extends Exception { 
    public BusinessException(String message, Throwable cause) { 
     super(message, cause); 
    } 

    public BusinessException(Throwable cause) { 
     super(cause); 
    } 
} 

class ViewException extends Exception { 
    public ViewException(String message, Throwable cause) { 
     super(message, cause); 
    }  
    public ViewException(Throwable cause) { 
     super(cause); 
    } 
} 
+0

В моем понимание этого проекта будет только усложнять ситуацию, и, как упоминалось в @Scott Hannen, это только увеличило бы объем информации, который мы предпочли бы игнорировать вместе с потерей исходного источника исключения –

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