Статьи

Почему подавление уведомлений неправильно

Когда я впервые пришел на работу к своему нынешнему работодателю и открыл Zend Studio (не волнуйтесь, они в основном отказались от этого зверства IDE), около 2000 из 10 000 PHP-файлов, которые составляли наше приложение, загорелись ошибками. Разработчики до меня никогда не поддерживали его должным образом, и ужасы унаследованного кода были непостижимы. Я сразу понял, что это не будет легким путешествием.

Потратив несколько недель, пытаясь (и не сумев) исправить ситуацию, я сдался и сосредоточился на более современных задачах, реализующих новые запрошенные функции поверх хаоса — плохая идея, поскольку большинство с этим согласится. Хотя работа — это работа, и какое-то время все работало хорошо. Со временем мы начали замечать, что операции записи приложения достигают максимума за пределами нормы. Открытие журнала ошибок показало, почему: уведомления и предупреждения.

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

Уведомления и предупреждения

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

Примером может быть следующее. Если у вас есть пустой массив $aArray , и вы пытаетесь получить доступ к ключу, который не существует, вот так:

 <?php $aArray = array(); $aArray['someKey']; 

Вы получаете уведомление о том, что ключ не существует.

  Примечание: неопределенный индекс: someKey в /var/www/index.php в строке 3

 Стек вызовов:
     0,0009 328920 1. {main} () /var/www/index.php:0 

Вы получаете уведомление о том, что ключ не существует. Но это не нарушает ваш код — фактически, если вы попытаетесь сохранить $aArray['someKey'] в переменной, эта переменная будет инициализирована, как и ожидалось, с нулевым значением.

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

 <?php // $oView = ... our view object // $aMessages = array(); if (/* some expression that signifies an error */) { $aMessages['error'] = 'Error no.2 occurred, contact developer!'; } $aMessages['status'] = 'Finished operation'; $oView->aMessages = $aMessages; 

Вы заметите, что ключ «error» устанавливается только в том случае, если ошибка действительно возникает, то есть если if-выражение в скобках оценивает true.

Код представления выглядел примерно так (упрощенно для целей этой статьи):

 <h1>Operation completed</h1> <?php echo @$this->aMessages['error']; echo '<hr />'; echo $this->aMessages['status']; echo '<hr />'; // ... 

Состояние операции и ошибка отображаются. Но, поскольку они знали о том, что «ошибка» не может быть установлена, они использовали оператор подавления @ чтобы предотвратить печать уведомления на экране.

Удивительное количество разработчиков PHP на самом деле не знает, что даже если вы отключите уведомление на экране, что оно все равно будет зарегистрировано, если ведение журнала включено — значит, ваш журнал ошибок напичкан бессмысленными и относительно большими строками текста. Разработчики часто думают, что @ — это просто законное сокращение от «игнорировать», но это не так — это сокращение от «Я знаю, что мой код здесь отстой, но давайте притворимся, что все в порядке, потому что я не собираюсь делать его лучше».

Когда это использовать?

Так, когда использование подавления фактически допустимо?

Никогда!

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

Это также замедляет работу вашего приложения, потому что оно постоянно должно что-то записывать в журнал ошибок. Представьте себе код выше, который вызывается 1 000 000 посетителей в день интенсивного трафика. Это миллион строк текста в журнале ошибок! Влияние на производительность едва ли незначительно.

В самом деле? Никогда?

При разработке сообщения об ошибках присутствуют по причине. Они помогают вам находить ошибки в вашем коде, прежде чем вы нанесете такую ​​же судьбу вашим пользователям и клиентам. Они указывают вам в правильном направлении, что не так и что нужно исправить. Это верно как для уведомлений, так и для фатальных ошибок — все они помогают вам, разработчику, сделать лучший продукт из возможных. Однако иногда вам может потребоваться проверить некоторые функциональные возможности перед обработкой любых оставшихся уведомлений, которые остались до этого — например, при выводе сгенерированных файлов. Если уведомление распечатывается до начала генерации файла, это означает, что заголовки уже отправлены (поскольку без заголовков ваш браузер не имеет представления о том, как отобразить передаваемый контент), и это означает, что ваш файл не будет отображаться должным образом, поскольку ему необходимо отправьте свои заголовки в браузер, чтобы браузер распознал, что мы имеем дело с реальным файлом.

Также есть редкий случай, когда приходится иметь дело с некоторыми неряшливыми деталями реализации PHP — например, использование функции mail () @mail() ошибку, если почтовый сервер не работает, поэтому выполнение @mail() оправдано.

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

Вы можете спросить, как вы можете заставить себя сделать это? Делая то же самое, что и я, когда создавал свой фреймворк:

 <?php function myErrorHandler($errno, $errstr, $errfile, $errline) { if (!(error_reporting() & $errno)) { // This error code is not included in error_reporting return; } echo "<b>ERROR!</b> [$errno] $errstr<br>n"; echo " Fatal error on line $errline in file $errfile"; echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br>n"; echo "Aborting...<br>n"; exit(1); break; } $old_error_handler = set_error_handler("myErrorHandler"); 

Приведенный выше фрагмент кода заменяет обработчик ошибок по умолчанию пользовательской функцией, которая заставляет приложение «умирать» при любой ошибке, предупреждении или уведомлении.

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

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

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

Вывод

Хороший код — это медаль, которую вы можете привязать к груди. Это трофей, который ты носишь с гордостью. Хороший код следует за вами после того, как вы его оставили, и рассказы, которые он рассказывает тем, кто его унаследует, покажут вас главным героем. Это зависит от вас, чтобы убедиться, что вы главный герой этих историй, а не антагонист.