Стандарты проверки аргументов функции/метода

Я просто интересовался стандартными методами синтаксиса проверки аргументов. Я работаю с PHP на данный момент, но все, что считало бы агностическим решением платформы/языка, было бы замечательно.

В настоящее время я знаю два довольно распространенных синтаксиса. Например (мои предпочтения):

function foo($a, $b, $c){
    if(!$a){ throw new Exception(); }
    if($b < 0){ throw new Exception(); }
    if(!check($c)){ throw new Exception(); }

    //do stuff with $a, $b, and $c

}

И, альтернативно:

function foo($a, $b, $c){
    if($a){
        if($b >= 0){
            if(check($c)){

                //do stuff with $a, $b, and $c

            }else{ throw new Exception(); }
        }else{ throw new Exception(); }
    }else{ throw new Exception(); }
}

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

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

Ответ 1

Я предпочитаю первый пример, который вы приводите по нескольким причинам:

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

Дизайн по контракту - это общий подход к обеспечению выполнения определенных условий (обычно посредством утверждений), таких как:

Assert.IsNotNull($a, '$a must not be null');

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

Используя тот же подход, вы можете сделать некоторые утверждения в конце метода (post-conditions), чтобы гарантировать, что метод выполнен как ожидалось.

Ответ 2

В качестве альтернативы, сгруппируйте набор тестов if в одном выражении if if:

function foo($a, $b, $c) {
    if ((!$a) ||
        ($b < 0) ||
        (!check($c))) {
       throw new Exception();
    } 

    //do stuff with $a, $b, and $c
}