2012-03-22 2 views
0

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

У меня есть такой код:

public class SomeClass 
{ 
    private readonly object m_internallyUsedObject; 
    private ThirdPartyObject m_user; // Third party object. 

    public SomeClass(object internallyUsedObject) 
    { 
     m_internallyUsedObject = internallyUsedObject; // We just want to ensure that the object will remain the same throught the life time of SomeClass object. 
     m_user = new ThirdPartyObject(); // This object is not yet needed here. 
    } 

    public void DoSomething() 
    { 
     m_user.DoSomethingElse(m_internallyUsedObject); // Now we're using it and we are not sure whether null value is tolerated. 
    } 
} 

Поскольку мы взять internallyUsedObject в конструкторе, мы, вероятно, знаете, семантика этого объекта и как она должна быть использована. С другой стороны, мы просто передаем этот объект третьему лицу во время вызовов. Наш объект SomeClass будет работать нормально, независимо от того, является ли значение null или нет.

Теперь проблема в том, что мы не знаем, будет ли null всегда работать на ThirdPartyObject - он может работать в одном варианте (в этом случае это нормально опустить null чек) и не работают в другом.

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

Как я уже говорил выше, это простая проверка не может быть полезной или даже недействительной в версиях конкретного объекта третьей группы с:

if (internallyUsedObject == null) 
{ 
    throw new ArgumentNullException("internallyUsedObject"); 
} 

Правомерны в соответствии с ООП взять internallyUsedObject из приведенной выше коды внутри конструктор, когда мы не будем использовать его напрямую? Разве это не нарушает принцип "fail fast", так как может показаться, что мы просто откладываем проблему на более поздний этап жизни объекта?

+0

Я бы выбросил 'ArgumentNullException' только тогда, когда вы знаете, что это не должно быть' null', например, в 'DoSomethingElse'. –

+0

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

+0

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

ответ

0

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

public void MyMethod(MyObject input) { 

    // 1. perhaps security checks, if an in method security is required 
    if(security.AccessLevel < requiredLevel) 
     throw new CustomSecurityException("Insufficent Access"); 

    // 2. data checks 
    if(input.Property == null) 
     throw new ArgumentNullException("Input didn't contain the value I wanted"); 

    if(input.Property2 < someImportantLevel) 
     throw new CustomBLException("Input didn't meet required level for something"); 

    // 3. perform BL 
    // ...do whatever 

} 

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

if(input != null) { 
    //do logic 
} else { 
    throw new Exception(); 
} 

Если проверки могут быть скрыты или вложенными и труднее найти.

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