2015-06-11 33 views
1

Мне очень сложно, когда дело доходит до good design.
Я не уверен, должен ли я позволить более позднему методу выбросить исключение или я должен сам его выбросить.
Вещь:

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

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

Рассмотрим это:

private bool _canWaste = false; 



/// <summary> 
/// Runs around and wastes something. 
/// </summary> 
/// <exception cref="InvalidOperationException"> 
///  Thrown when <paramref name="CanPower"/> is false. 
/// </exception> 
public void Run(bool CanWaste) { 
    _canWaste = CanWaste; 
    // <- Should I check if we can waste and throw an ArgumentException here or 
    // throw the 'wrong' type later in Waste? 
    Waste(); 
} 



/// <summary> 
/// Wastes something. 
/// </summary> 
/// <exception cref="InvalidOperationException"> 
///  Thrown when we cannot waste. 
/// </exception> 
private void Waste() { 
    if(!_canWaste) throw new InvalidOperationException("We cannot waste."); 
    /* ... */ 
} 

Это простой пример (который не имеет смысла), где было бы сделано Исли.
Но, конечно, есть методы, где оценка намного сложнее.

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

ответ

3

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

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

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

+0

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

+0

@NoelWidmer, рассмотрим более простой пример, предположим, что вы получаете строковый параметр для 'DateTime', который должен быть в определенном формате. Когда вы пытаетесь проанализировать свою * строку * DateTime на объект DateTime, используя' DateTime.ParseExact 'и вы получите исключение из строкового формата недопустимого значения. В этом случае вы можете уловить исключение, возникшее во время разбора, и вернуть клиенту' InvalidArugmentException'. Если ваш сценарий подобен этому, то обязательно, поймайте 'InvalidOperationException', а затем выбросите' InvalidArgumentException' – Habib

+1

В дополнение к выше ^^, если единственной целью вашего метода является проверка аргумента, его следует назвать вероятным и может возвращать bool, указывающий, является ли аргумент действительным или нет, вместо исключения исключения, просто делая намерение более явным, а код более читаемым - IMO. – Habib

2

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

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

public void Run(bool CanWaste) 
{ 
    if(!CanWaste) 
     throw new ArgumentException("CanWaste must be true", "CanWaste"); 
    Waste(); 
    // ... 
} 

Однако, если вы не знаете, если аргумент является недействительным и определение является дорогостоящим (f.e. Вы должны выполнить его), то пусть глубинный метод броска. Вы можете обрабатывать InvalidOperationException в вызывающем методе:

public void Run(bool CanWaste) 
{ 
    _canWaste = CanWaste; 

    try 
    { 
     Waste(); 
    }catch(InvalidOperationException ioe) 
    { 
     throw new ArgumentException("CanWaste must be true", "CanWaste", ioe); 
    } 
} 

Конечно, в этом случае можно легко определить, если аргумент является действительным. Это также не лучший пример, поскольку параметр bool, который может быть только true, не имеет большого смысла.

+0

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

+0

@NoelWidmer: но вы называете 'Waste' первым, что не нравится, если' _canWaste == false', так что на самом деле это _is_ уже недействительно в этом методе или неверно бросать 'InvalidOperatonException' в' Waste'. –

+0

Я думаю, вы правы. Thx для того, чтобы расчистить это для меня. –

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