Должен ли я использовать assert в моем PHP-коде?

Сотрудник несколько раз добавил команду assert в наших библиотеках в тех местах, где я использовал бы оператор if и выбрал исключение. (Я никогда не слышал об этом раньше). Вот пример того, как он его использовал:

assert('isset($this->records); /* Records must be set before this is called. */');

Я бы сделал:

if (!isset($this->records)) {
    throw new Exception('Records must be set before this is called');
}

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

Итак, мой вопрос заключается в том, что использовать утвердительную идею, указанную выше, и следует ли использовать ее чаще, а не if и exceptions?

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

Ответ 1

Эмпирическое правило, применимое на большинстве языков (все, что я смутно знаю), заключается в том, что assert используется для утверждения, что условие всегда истинно, тогда как if если возможно, что он иногда терпит неудачу.

В этом случае я бы сказал, что assert является подходящим (основанным на моем слабом понимании ситуации), потому что records должен всегда устанавливаться до вызова данного метода. Таким образом, неспособность установить запись будет ошибкой в ​​программе, а не условием выполнения. Здесь assert помогает (при адекватном тестировании), чтобы не было возможного пути выполнения программы, который мог бы вызвать защищенный код с assert, который будет вызываться без records, который был установлен.

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

Ответ 2

Подумайте о том, что утверждает, что "комментарии мощности". Вместо комментария вроде:

// Note to developers: the parameter "a" should always be a number!!!

использование:

assert('is_numeric(a) /* The parameter "a" should always be a number. */');

Значения абсолютно одинаковы и предназначены для одной и той же аудитории, но первый комментарий легко забыт или проигнорирован (независимо от количества восклицательных знаков), в то время как "комментарий силы" доступен не только для людей, чтобы читать и понять, он также постоянно подвергается машинной проверке во время разработки и не будет игнорироваться, если вы настроите правильную обработку утверждений в коде и в привычках работы.

Таким образом, утверждения являются совершенно иной концепцией, чем if (error)... и исключениями, и они могут сосуществовать.

Да, вы должны комментировать свой код, и да, вы должны использовать "комментарии по мощности" (утверждает), когда это возможно.

Ответ 3

Это полностью зависит от вашей стратегии развития. Большинство разработчиков не знают о assert() и используют последующее модульное тестирование. Но инициативные и встроенные схемы тестирования иногда могут быть полезными.

assert полезен, поскольку он может быть включен и отключен. Это не снижает производительность, если такой обработчик не определен. У вашего колледжа нет его, и вы должны разработать код, который временно включает его в среду разработки (если E_NOTICE/E_WARNING включены, то должен быть обработчик утверждения). Я иногда использую его, когда мой код не может смешивать смешанные переменные типы - я обычно не занимаюсь строгой типизацией в слабо типизированном PHP, но там случайные варианты использования:

 function xyz($a, $b) {
     assert(is_string($a));
     assert(is_array($b));

Что, например, компенсирует отсутствие спецификаторов типа string $a, array $b. PHP5.4 будет поддерживать их, но не проверять.

Ответ 4

Ассемблер не является заменой нормальному управлению потоком, например if или исключениям, поскольку он предназначен только для отладки во время разработки.

Ответ 5

Важное замечание относительно утверждения в PHP раньше, чем 7. В отличие от других языков с конструкцией assert, PHP не полностью выводит утверждения assert - он рассматривает его как функцию (выполняйте debug_backtrace() в функции, вызываемой утверждением). Поворот утверждений, кажется, просто hotwire функция в ничего не делает в двигателе. Обратите внимание, что PHP 7 можно заставить эмулировать это поведение, установив zend.assertions на 0 вместо более нормальных значений 1 (вкл.) Или -1 (выкл.).

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

<?php
  function foo($a) { 
    echo $a . "\n"; 
    return TRUE;
  }
  assert_options(ASSERT_ACTIVE, FALSE);

  assert( foo('You will see me.'));
  assert('foo(\'You will not see me.\')');

  assert_options(ASSERT_ACTIVE, TRUE);

  assert( foo('Now you will see'));
  assert('foo(\'both of us.\')');

Учитывая намерение утверждать, что это ошибка, и давняя, поскольку она была на языке, поскольку утверждение было введено еще в PHP 4.

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

EDIT: изменено выше, чтобы отметить изменения в PHP 7 и 7.2

Ответ 6

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

Ответ 7

Вы, коллега, действительно пытаетесь применить проектирование по контракту (DbC) на языке Eiffel, основываясь на книге "Создание объектно-ориентированного программного обеспечения", 2-е издание.

Утверждение, как он его использовал, будет {P} -part логики Хоара или Тройного Хора: {P} C {Q}, где {P} является предварительным условием утверждения (иона) s и {Q} являются утверждениями (ионами) после условия.

Я бы критически принял к сведению советы о том, что функция assert в PHP имеет ошибки. Вы не хотите использовать глючный код. Что вам действительно нужно, так это создателям PHP исправить ошибку в assert. Пока они этого не сделают, вы можете использовать assert, но используйте его, помня о его текущем состоянии ошибки.

Более того, если функция assert содержит ошибки, я предлагаю вам не использовать ее в рабочем коде. Тем не менее, я рекомендую использовать его при разработке и тестировании кода, где это уместно.

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

Более того - я очень рекомендую, чтобы создатели PHP всесторонне изучили дизайн по контракту и попытались включить его в PHP как можно скорее! Тогда всем нам может быть полезен компилятор/интерпретатор с поддержкой DbC, который бы решал проблемы, отмеченные в ответах (выше):

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

ПРИМЕЧАНИЕ. Даже использование вами if -statement в качестве замены утверждения (предусловия) будет иметь тяжелые последствия, если его использовать для усиления предусловия или ослабления постусловия. Чтобы понять, что это значит, вам нужно изучить проект по контракту, чтобы знать! :-)

Приятного изучения и обучения.

Ответ 8

Нет, ваш сотрудник не должен использовать его как обработчик ошибок общего назначения. Согласно руководству:

Утверждения должны использоваться только как функция отладки. Вы можете использовать их для проверки работоспособности, которые проверяют условия, которые всегда должны быть ИСТИНЫ, и которые указывают на некоторые ошибки программирования, если нет, или для проверки наличия определенных функций, таких как функции расширения или определенные системные ограничения и функции.

Утверждения не должны использоваться для обычных операций выполнения, таких как проверка входных параметров. Как правило, ваш код всегда должен работать правильно, если проверка подтверждения не активирована.

Если вы знакомы с автоматизированными наборами тестов, глагол "assert" обычно используется для проверки вывода какого-либо метода или функции. Например:

function add($a, $b) {
    return $a + $b;
}

assert(add(2,2) == 5, 'Two and two is four, dummy!');
assert(is_numeric(add(2,2)), 'Output of this function to only return numeric values.');

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