2010-10-08 3 views
1

Если функция выполняет все надлежащие проверки внутри, я должен проверить все, прежде чем звонить, или лучше не? Является ли избыточность безопасности хорошей практикой?Хорошо это или плохо, чтобы перестраховать?

Пример (в какой-то C# -like псевдокода с помощью ссылки аргументов мимоходом):

 

doSomething(vector v) { 
    ...; 
    v.clear; 
    useCleanVector(v) 
} 

useCleanVector(vector v) { 
    if(!v.isClean) v.clear; 
    ... 
} 
 
+3

Действительно зависит от того, какое программное обеспечение вы пишете. –

+4

Этот вопрос слишком общий для хорошего ответа ... возможно, вы могли бы привести примеры кода? –

+0

Что это связано с функциональным программированием? –

ответ

0

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

v.clear(); // clear the vector to be safe. 
v = v2; 

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

Лучше всего понять, что функция проверяет, а что нет, и использовать ее соответствующим образом.

+0

Я не думаю, что это то, что он имеет в виду. То, что он имеет в виду, это вещи, такие как проверка аргументов функции для достоверности один раз при вызове функции, и один раз внутри нее –

+0

@Pekka, точно. Но с точки зрения математической логики это то же самое, что и @JoshD. – Ivan

+0

@ Ивана да, но ваша функция может использоваться позже в контексте, который * не делает первую проверку. В этом случае вторая проверка * может * иметь смысл (это также может быть ненужным. Действительно зависит от вашего проекта) –

4

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

/** 
* precondition : id must be the id of a flarg. 
* 
* myfunc will return -1 if value is outside the valid 0-10 range. 
*/ 
int myfunc(int id, int value); 

Это позволяет мне код что-то вроде этого

int flarg_id = ... 
if (! is_flarg(flarg_id)) { printf("Bad flarg"); exit(1); } 
int value = ... 
int rv = myfunc(flarg_id, value); 
if(rv == -1) { printf("Bad value"); exit(1); } 
+0

+1. Пока документы четко указывают, что будет делать функция при каких обстоятельствах, огромная часть неопределенности отпадает. –

0

Да, вы всегда должны выполнить необходимые проверки на этом уровне охвата.

Причина? Когда кто-то приходит через вас через n месяцев, они не будут следовать вызовам функций до последнего элемента. Удостовериться, что каждая функция защищена сама по себе, поможет облегчить глупые ошибки или, что еще хуже, ошибки, которые трудно отследить.

+0

Это действительно зависит от того, насколько дорогой чехол. Если код хорошо документирован, то это строгое может быть более чем необходимо –

+0

Я думаю, что в основном, но я боюсь, что в некоторых случаях это может даже ввести трудно различимые ошибки. – Ivan

+0

@Ivan нет, если ваша функция хорошо документирована, и каждый экземпляр, вызывающий функцию, был написан с учетом этой документации. Документация - это действительно ключ - если это хорошо, можно написать код против него и надеяться, что он будет подавать ожидаемый ввод –

1

Существует избыточность (часто хорошая), и вы повторяетесь.

Чтобы заимствовать у примера Джоша, если функция Foo гарантирует, что он очищает вектор, нет причин для его очистки заранее. Доверяйте и проверяйте гарантии, предоставляемые вашим API.

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