Связь между слоями в приложении - PullRequest
3 голосов
/ 27 марта 2010

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

public String updateSomething()
{
   try
   {
      //Begin transaction here
      dataLayer.do1();
      dataLayer.do2();
      dataLayer.doN();
      //Commit transaction code here
   }
   catch(Exception exc)
   {
      //Rollback transaction code here
      return exc.message;
   }

   return "";
 }

Является ли это хорошей практикой или я должен выбросить другое исключение в улове (тогда метод будет аннулирован)?

Ответы [ 4 ]

5 голосов
/ 27 марта 2010

Мне нравится возвращать стандартный контракт на уровень пользовательского интерфейса из бизнес-уровня.

Это выглядит так:

public class ServiceOperationResult<T>
{

    public bool Successful
    {
        get; 
        set;
    }

    public ServiceErrorType ErrorType
    {
        get;
        set;
    }

    public string ErrorMessage
    {
        get;
        set;
    }

    public T ReturnData
    {
        get;
        set;
    }
}

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

Например, бизнес-ошибки отображаются в красной метке ошибки, а внутренние ошибки перенаправляются на страницу ошибок (в веб-приложении) или закрывают форму (в приложении Windows)

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

2 голосов
/ 27 марта 2010

Лучший способ - обернуть исключение в более общий тип и перебросить его. Поэтому updateSomething () должен объявить, что он может генерировать какое-то исключение (например, UpdateFailedException), а в блоке catch вы должны заключить исключение.

public String updateSomething() {
  try {
    [...]
  } catch ( SQLException e ) {
    // rollback;
    throw new UpdateFailedException(e);
  }
}

Но ловить абстрактный тип исключения не очень хорошая идея. Вы должны обернуть только те вещи, которые семантические вы знаете. Например: SQLException, DataAccessException (Spring DAO) и т. Д.

Если вы оберните Exception, вы легко можете обернуть InterruptedException в NullPointerException. И это может сломать ваше приложение.

1 голос
/ 27 марта 2010

Немного необычно возвращать строку типа этой (но нет никакой реальной причины не слишком). Более обычные методы были бы:

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

  • имеет метод void, который выдает исключение при сбое, и обрабатывает его в вызывающем коде (как вы предлагаете)

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

0 голосов
/ 28 июля 2013

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

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

например, вы ловите исключение на бизнес-уровне и хотите сообщить на уровне представления

public string DummyFunction
{
   try
   {

   }
   catch(Exception ex)
   {
      throw new businessException();
   }
}
...