Где проверить аргументы метода?
Мне интересно, где и как часто - в аргументах метода проверки кода.
В приведенном ниже классе примеров (библиотека .dll), как вы думаете, лучший способ? Предположим, что я хочу проверить, что некоторый объект не может быть null
(но это может быть любая другая проверка, необходимая для правильного запуска метода). Лучше ли проверять его только один раз в пункте 1., в общедоступном методе, доступном для пользователя, а позже "доверяй себе", что в других частных методах он не будет нулевым или, лучше быть немного параноидальным и проверять его каждый (в пунктах 2. 3. и 4.)
Проверка его перед использованием объекта (в пунктах 2, 3, 4) защитит меня в будущем, если я решит что-то изменить в классе, используя эти частные методы и "забудьте" передать действительный объект. Также мне не нужно помнить о проверке, если я добавлю новый публичный метод в будущем. С другой стороны, он снова и снова проверяет одно и то же условие. Или, может быть, у вас есть другие предложения?
public class MyClass()
{
public MyClass()
{
}
public void ProcessObject(SomeObject obj)
{
//1. if (obj == null) throw new ArgumentException("You must provide valid object.");
DoSomething(obj);
DoMore(obj);
DoSomethingElse(obj);
}
private void DoSomething(SomeObject obj)
{
//2. if (obj == null) throw new ArgumenException("You must provide valid object.");
//do something with obj...
}
private void DoMore(SomeObject obj)
{
//3. if (obj == null) throw new ArgumentException("You must provide valid object.");
//do something with obj...
}
private void DoSomethingElse(SomeObject obj)
{
//4. if (obj == null) throw new ArgumentException("You must provide valid object.");
//do something with obj..
}
}
Ответы
Ответ 1
Если это API, который вы рекламируете для других разработчиков, то на каждом из ваших методов вы действительно должны бросать либо ArgumentException
, либо ArgumentNullException
.
Если внутренние классы или методы, с которыми другие разработчики не будут взаимодействовать напрямую, я бы использовал Debug.Assert
, поэтому в режиме отладки вы получаете дополнительную информацию об отладке, а в режиме освобождения ее отбрасывают, и вы получаете преимущество в производительности не выполнять все эти проверки аргументов всюду.
Ответ 2
В хорошем программном обеспечении методы должны быть независимыми друг от друга.
Вы должны быть в состоянии использовать их в любом порядке и отделены друг от друга. Итак, да, вы должны проверять одно и то же условие во всех методах снова и снова.
Edit:
Я бы использовал CodeContract с предварительным условием, которое проверяет, что obj не является нулевым. Поскольку это, похоже, является предварительным условием правильной работы методов.
Ответ 3
Каждый публичный метод должен проверять его ввод.
Частные методы могут полагаться на IMHO на проверку других общедоступных методов в классе, если вы просто передаете ранее проверенный объект. Поскольку частные методы инкапсулируются в класс, ответственность за валидацию остается в классе.
Однако, если у вас есть частный метод, который принимает некоторые расчетные параметры (а не те, которые передаются общедоступному методу), то необходимо выполнить дополнительную проверку.
В ваших модульных тестах будет проверяться открытый интерфейс класса, и они будут терпеть неудачу, если ваш SomeObject
равен null
, если ваша проверка выполняется только в ProcessObject
. В этом случае я бы не дублировал проверку в частных методах.