2015-06-25 4 views
3

Мне интересно, будет ли то, что я собираюсь сделать, это хорошо или плохо. У меня есть этот класс:Обработка исключений - это хорошая практика?

public class Element : IElement 
{ 
    public float? Max { get; private set; } 

    public float? Min { get; private set; } 

    public float? Average { get; private set; } 

    public bool HasValue { get; private set; } 


    public void SetRange(float? min, float? max) 
    { 
     if (min >= max) 
     { 
      throw new WrongElementValueException("Min must be greater than max!"); 
     } 
     else if (min < 0f || max < 0f) 
     { 
      throw new WrongElementValueException("Min/max must be greater than 0!"); 
     } 
     else if (min > 100f || max > 100f) 
     { 
      throw new WrongElementValueException("Min/max must be lesser than 0!"); 
     } 
     else 
     { 
      Min = min; 
      Max = max; 
      Average = (min + max)/2f; 
      HasValue = true; 
     } 
    } 
} 

Пользователь установит значения, используя метод SetRange(). Но у него есть некоторые ограничения, такие как Min, должен быть больше Max, и ни один из них не должен быть больше 100 или меньше 0.

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

+6

Это кажется мне разумным. Хотя я не уверен, что тип исключения более подходит, чем стандартное 'ArgumentException', но это незначительная точка. В любом случае, если вход недействителен, и объект не может действовать иначе, то бросание исключения является подходящим ответом. – David

+1

@David Согласен с тем, что исключение ArgumentException более уместно, поскольку это ожидаемое исключение в случае плохих аргументов. –

+0

«Пользователь установит значения» пользователя приложения или пользователя (т.е. разработчика) кода, который вызовет этот метод? – Richard

ответ

2
else if (min < 0f || max < 0f) 
    throw new WrongElementValueException("Min/max must be greater than 0!"); 
else if (min > 100f || max > 100f) 
    throw new WrongElementValueException("Min/max must be lesser than 0!"); 

Я бы отметить, что уже ArgumentOutOfRangeException, который определен именно для такого рода случай

..
if (min >= max) 
    throw new WrongElementValueException("Min must be greater than max!"); 

Это, безусловно, должно быть ArgumentException, но если WrongElementValueException унаследован от ArgumentException, то это нормально.

Ваш роды л. Я бы хотел пойти дальше:

HasValue = true; 

Зачем позволять классу никогда не иметь значения. Рассмотрим, если добавить:

public Element(float min, float max) 
{ 
    SetRange(min, max); 
} 

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

Обратите внимание, что я изменил это с float? на float. Вам вполне может быть рекомендовано сделать это на протяжении всего класса. В противном случае, если у вас есть потребность в тех случаях, когда Min и Max равны нулю, (и, следовательно, не хотят, чтобы избавиться от HasValue) вы должны поймать тот случай в SetRange:

public void SetRange(float? min, float? max) 
{ 
    if (min < 0f || max < 0f || min > 100f || max > 100f) 
     throw new ArgumentOutOfRangeException(); 
    if (min >= max) 
     throw new WrongElementValueException("Min must be greater than max!"); 
    Min = min; 
    Max = max; 
    if(min.HasValue && max.HasValue) 
    { 
     Average = (min + max)/2f; 
     HasValue = true; 
    } 
    else 
    { 
     Average = null; 
     HasValue = false; 
    } 
} 

(я бы также в целом пользуйтесь double и double? над float и float?, если у вас нет веской причины).

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

+0

Спасибо @ Jon Hanns :) Я думаю, вы исчерпали тему полностью. Я буду следовать вашему предложению об использовании double вместо float. Мне нужно, чтобы они были обнуляемы, потому что есть приемлемая возможность, что просто не будет данных о min и max. Еще раз спасибо! –

2

Исключение полезно, когда действительный программный поток невозможен (например, соединение с базой данных потеряно). Проверять исключение пользователя и исключение бросания, если значения недействительны, абсолютно нормально, тогда как вы можете также использовать предложенный allready ArgumentException.

9

Это подходящая практика, да.

Хотя я предполагаю, что потребительский код будет ожидать ArgumentException, а не этот тип исключения, но это может быть относительно небольшая точка.

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

Альтернатива этому объекту - «попытаться выяснить, что делать», что часто приводит к довольно плохому кодированию практики. Например ...

  • Предположим, что вместо этого вы хотите вернуть сообщение об ошибке вместо того, чтобы выбрасывать исключение. Что, если потребительский код не проверяет это сообщение об ошибке? Объект будет оставлен в неизвестном и недопустимом состоянии и может спокойно вводить ошибки. Принимая во внимание, что если код потребления не проверял исключение, то программа явно и явно потерпит неудачу и должна быть исправлена ​​соответствующим образом. Явные и очевидные ошибки много легче поддерживать, чем тонкие и незаметные.
  • Предположим, что вы хотите «показать сообщение пользователю». Это потребовало бы жесткого связывания этого объекта с уровнем представления, который побеждает объектно-ориентированные принципы и делает код очень жестким и трудным для поддержания.

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

+0

Спасибо за ваш ответ! В самом деле, я собираюсь показать сообщение пользователю, что он установил неправильные значения, чтобы он мог их улучшить :) –

+0

@bartosz.baczek: Который я очень рекомендую делать :) Просто помните, где лежит ответственность за такие вещи (которые вы, кажется, делаете довольно хорошо до сих пор). Классы бизнес-логики просто выполняют бизнес-логику и бросают исключения при возникновении сбоев, уровень представления управляет пользовательским вводом и направляет пользователя на внесение исправлений в случае сбоев. Удачи! – David

-3

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

Оба будут работать одинаково в этом сценарии.

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

И, между прочим, вы не думаете, что это неправильно.

if (min> = max) throw new WrongElementValueException («Мин должен быть больше max!«); // Ваш печатаете мин должно быть больше, чем максимум, и вы проверяете то же

+2

"ограничить его простой консольной печатью"? Что это вообще значит? – David

+0

вы можете просто показать сообщение об ошибке msg out out вместо создания объекта исключения с использованием той же строки и отобразить его на выходе. Я не думаю, что здесь нужна такая работа. –

+0

@sulemanravla, вы можете ... но вы действительно не должны этого делать. –