2010-03-27 3 views
3

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

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 ""; 
} 

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

ответ

1

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

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

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

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

+0

+1, я люблю первый путь. Я лично ненавижу беспорядок попытки. Разве не здорово писать «if (updateSomething()) {}« вместо «try {updateSomething();} catch (Exception) {}"? –

+0

У меня есть любовь к прямолинейности техники «если». Но есть преимущества для метода исключений, например, когда вам приходится много раз называть множество методов, вы можете написать: 'try {something(); что-то другое(); еще одна вещь(); л(); } catch (...) {} finally {alwaysRunThis(); } 'вместо проверки каждого оператора if на этом пути. Лошади для курсов ... –

2

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

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

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

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

+1

Вы абсолютно правы. Я просто сомневаюсь, что в итоге я завершу попытку, поймаю все в пользовательском интерфейсе, который вызывает бизнес-уровень. Это проблема? –

+0

думаю. Есть ситуации, когда вы не можете продолжить и должны прекратить применение. Нет никакого смысла в поиске OutOfMemoryError или что-то в этом роде. Итак, главное - отделить ошибки, которые можно восстановить из ошибок, которые нет. –

+0

Я все еще думаю, что trycatch уродлив и должен быть помещен только в бизнес-слоях и выше. – Rushino

5

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

Это выглядит следующим образом:

public class ServiceOperationResult<T> 
{ 

    public bool Successful 
    { 
     get; 
     set; 
    } 

    public ServiceErrorType ErrorType 
    { 
     get; 
     set; 
    } 

    public string ErrorMessage 
    { 
     get; 
     set; 
    } 

    public T ReturnData 
    { 
     get; 
     set; 
    } 
} 

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

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

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

+1

+1, очень интересная идея. –

+0

+1, у меня тоже была эта идея, полезная, если вы хотите избежать использования try catch везде ... – Rushino

0

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

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

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

public string DummyFunction 
{ 
    try 
    { 

    } 
    catch(Exception ex) 
    { 
     throw new businessException(); 
    } 
} 
Смежные вопросы