Повторные проверки параметров в функциях - PullRequest
5 голосов
/ 14 июля 2010

У меня часто есть иерархии вызовов, в которых все методы нуждаются в одинаковых параметрах Если я не хочу помещать их на уровень экземпляра (член класса), я всегда спрашиваю, имеет ли смысл проверять их правильность в каждом методе.

Например:

public void MethodA(object o){
   if(null == o){
      throw new ArgumentNullException("o");
   }
   // Do some thing unrelated to o

   MethodB(o);

   // Do some thing unrelated to o

}

public void MethodB(object o){
   if(null == o){
      throw new ArgumentNullException("o");
   }
   // Do something with o
}

Если Method A использует параметр, то его очистить, я должен проверить действительность там, а также в MethdoB. Но до тех пор, пока MethodA ничего не делает с o больше, чем дает MethodB, рекомендуется проверять правильность также в MethodA.

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

Я взял нулевую проверку в качестве примера, но проверки индекса или проверки диапазона попадают в самооценку, однако я думаю, что существуют ограничения из-за опасности избыточного кода. Что ты думаешь?

UPDATE

Благодаря ответу AakashM я понял, что был немного точен. MethodA не только звонит MethodB, но и делает другие вещи, но не относится к o. Я добавил пример, чтобы прояснить это. Спасибо AakashM.

Ответы [ 3 ]

9 голосов
/ 14 июля 2010

Код Пола Стива Макконнелла говорит о понятии ' баррикада ' - стене защиты, за пределами которой данные не заслуживают доверия, а внутри которых данные являются доверенными.Данные, которые хотят войти в баррикаду, должны пройти процесс валидации, но внутри баррикады данные могут свободно перемещаться без ограничений по коду валидации.

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

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

Что касается MethodA, если он на самом деле ничего не больше, чем вызов MethodBне должно существоватьЕсли это заглушка для будущего расширения, и в какой-то момент он собирается что-то сделать с o, тогда его код проверки также должен остаться.

1 голос
/ 14 июля 2010

Я не считаю проверку параметров "избыточным кодом".Вам необходимо защитить все внешние точки входа.Если у вас есть метод private, такой, что вы знаете, что к тому времени, когда поток достигнет его, все его параметры будут действительны, то у вас, возможно, есть случай, но для public (и даже protected) методовдействительно нет.

1 голос
/ 14 июля 2010

Я думаю, вы должны убедиться, что это произойдет один раз, когда создается входное значение (ответственность вызывающего).Это работает, если класс используется только внутренними клиентами.Если он является частью общедоступного API, то вы не можете исключать проверки, но вы можете их разложить, как это предлагается в других ответах.

В целях тестирования вы также можете использовать Debug.Assert(o != null) в обоих методахи проверки будут удалены из кода выпуска, , если производительность является проблемой .

...