Должен ли я использовать 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, который бы решал проблемы, отмеченные в ответах (выше):
- Правильно реализованный компилятор, учитывающий конструкцию по контракту, (надеюсь) не будет содержать ошибок (в отличие от текущего утверждения PHP).
- Надлежащим образом реализованный компилятор, учитывающий дизайн и контракт, будет обрабатывать нюансы управления логикой полиморфных утверждений вместо того, чтобы ломать голову над этим вопросом!
ПРИМЕЧАНИЕ. Даже использование вами 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.');
Ваш коллега не должен использовать его как обработчик ошибок общего назначения и в этом случае в качестве проверки ввода. Похоже, что поле записей не может быть установлено каким-либо пользователем вашей библиотеки.