замерял PEAR/Benchmark'ом при повторении в 1000 итераций
1. производительность 1000 итераций это показатель для какого размера кода, большого или маленького, а главное является ли 1000 итераций достаточно большой нагрузкой? Все таки 0.1 или 0.2 миллисекунды все таки могут попадать в погрешность. Вот когда скажем 100000 итераций и разница скорости в двух разных вариантах кода равняется допустим 13 секундам....
2.
PHP:
if (file_exists($file_name)) {
if (is_readable($file_name)) {
// Читаем данные из файла
if (($data = file_get_contents($file_name)) === FALSE) {
trigger_error ("Ошибка чтения файла",
E_USER_ERROR);
restore_error_handler();
return FALSE;
}
}
else {
trigger_error ("Файл не доступен для чтения", E_USER_ERROR);
restore_error_handler();
return FALSE;
}
if (is_writeable($file_name)) {
// Открываем фаил для чтения и записи
if (($file_handle = fopen($file_name, 'rb+')) === FALSE) {
trigger_error ("Ошибка открытия файла для чтения и записи",
E_USER_ERROR);
restore_error_handler();
return FALSE;
}
// Проверяем корректность содержимого файла
if (!preg_match($good_file_data, $data)) {
// Выводим предупреждение в случае измененного содержимого
trigger_error ("Данные в файле повреждены", E_USER_WARNING);
// Урезаем весь файл до нулевой длины
if (ftruncate($file_handle, 0) === FALSE) {
trigger_error ("Ошибка очистки файла",
E_USER_ERROR);
// Закрывам файл в случае ошибки
if (fclose($file_handle) === FALSE) {
trigger_error ("Ошибка закрытия файла",
E_USER_ERROR);
restore_error_handler();
return FALSE;
}
restore_error_handler();
return FALSE;
Конечно параноидальность удобна, но все же желательно предоставлять читабельный и более удобный для понимания код, т.к. весь его смысл тонет в нагромождении проверок.
Скажем переписав вот так, не теряя функциональсти код выглядит гораздо удобочитабельней. Поменьше вложенных структур!
PHP:
if( !file_exists($file_name) ) {
throw new e_file_is_not_exists($file_name); }
if( !is_readable($file_name) ) {
throw new e_file_is_not_readable($file_name); }
/*
Обычно пхп функции в случае возникновения серьезных ошибок не только
возвращают FALSE, но и выводят сообщение об ошибке. Можно написать
через set_error_handler преобразователь ошибок в исключения, что позволяет
местами не писать дополнительные проверки, которые по сути дублируются.
Как пример:
ПХП внутри: произошла ошибка при чтении, выводим ошибку, возвращаем "ошибка" ->
-> наш код: проверяем что вернули ошибку, выводим ошибку, возвращаем "ошибка".
В моем же случае, при преобразовании ошибок в исключения, данное дублирование ненужно.
ПХП внутри: произошла ошибка при чтении, выводим ошибку
(-> попадаем на перехват, создаем исключение со всеми данными, сбрасываем его),
возвращаем ошибка.
Наш код: исключение попадает в try catch блок, либо в случае отсутствия такового
будет сбрасываться вверх по вызовам.
*/
// пример 1
// c проверкой
if(($data = file_get_contents($file_name)) === FALSE) {
throw new e_file_error($file_name, "Ошибка понимаешь..."); }
// пример 2
// без проверки, надеямся на перехват свыше
// такой тип будет встречаться далее по тексту.
$data = file_get_contents($file_name);
// пример 3.
// мой любимый, применяю когда нужно добавить много разносторонней информации об ошибке.
// мое исключение наследует arrayaccess, который
// используется для реализации хранения приложений (attachments).
// позволяет не писать исключения, в конструкторе которых множество параметров, которые нужно заполнять.
try {
$data = file_get_contents($file_name);
} catch( Exception $e ) {
$e2 = new e_file_error($file_name);
$e2[] = $e;
throw $e2;
}
if( !is_writeable($file_name) ) {
throw new e_file_is_not_writeable($file_name); }
$file_handle = fopen($file_name, 'rb+');
if (!preg_match($good_file_data, $data)) {
throw new e_file_data_is_corrupt($file_name); }
ftruncate($file_handle, 0);
fclose($file_handle);
Я вот только одного не понял. Для чего нужно везде restore_error_handler(); прописывать?
----
Разница между ошибками и исключениями в том, что исключения гораздо более удобный и функциональный инструмент:
1. Исключение содержит изначально в себе отладочную информацию, столь необходимую программисту: что, где и как, чем просто тупое null или false.
2. Исключение предоставляет способ для перехвата, который не конфликтует с возвращением значения функции. Сами гляньте сколько в пхп различных функций, где у каждой то один то другой метод возвращения ошибки, то false, то null то еще как. Да еще вдобавок нужно его проверять и перепроверять на каждом этапе (поскольку как еще иначе стандартную ошибку отловить?) что излишне загромождает код.
По поводу выведения ошибок, нотисов, варнингов и так далее обычным простым смертным пользователям. Думаю выводить не стоит, достаточно чтоб они отправлялись админу, но перед выкладываем когда на production, все же стоит протестировать и прогнать по всем пунктам, что бы убедиться что все работает нормально. Вообще с выводом ошибок примечательна история про Therac-25
# Аппарат Therac-25 имел много неполадок, которые, по-видимому, не причиняли вреда, и операторы научились игнорировать эти капризы. Это напоминает историю о мальчике, который кричал «волк!». Люди научились не обращать на него внимания. Частые отключения и остановки машины беспокоили операторов. Однако операторы никогда не видели никаких вредных последствий для пациентов из-за этих отключений, поэтому они научились игнорировать их. Нечто, что может иметь серьезные последствия, игнорировалось. Постоянные неполадки также демонстрировали внутреннюю нестабильность и небезопасность машины.
# Когда проявлялась неполадка, Therac-25 выдавал непонятные сообщения, которые не давали обслуживающему персоналу никаких ключей к причинам и следствиям системной ошибки. Конструкция системы не предусматривала адекватной обратной связи, и персонал не мог понять, что происходит. Информация проходила от оператора через программное обеспечение к оборудованию. Когда связь нарушалась, пользователь не имел способов узнать состояние оборудования, поскольку построение программ не позволяло опрашивать оборудование. Ошибка при вводе данных ясно показывает последствия недостатка обратной связи. Например, вместо того, чтобы просто позволить оператору включать пучок лучей после изменения параметров, программы могли быть сделаны так, чтобы облучение не могло начаться до тех пор, пока программа не опросит оборудование о его состоянии и не предоставит эту информацию оператору для проверки.
http://citforum.ru/programming/digest/scofdebug/
Далеко в лес ходить не надо. Какова информативность trigger_error ("Ошибка чтения файла", E_USER_ERROR); ?
Не сказано ни про какой файл, ни где и как произошло событие.
Вот например кусок выводимой ошибки из моего кода. Используется преобразование ошибок в исключения, атачменты и т.д.
PHP:
User Error:
Exception #EFFE73DC9: e_dpf_import_is_fail {
Message: {
Import call 'config:ini_file' is fail.
}
Attachment #0: {
Exception #EF2351921: e_dpf_import_depend_is_unresolved {
Message: {
Depend (pre-) 'config:ini' is unresolved.
}
Attachment #0: {
Exception #EFFE73DC9: e_dpf_import_is_fail {
Message: {
Import call 'config:ini' is fail.
}
Attachment #0: {
Exception #EF2351921: e_dpf_import_depend_is_unresolved {
Message: {
Depend (pre-) 'config:config' is unresolved.
}
Attachment #0: {
Exception #EFFE73DC9: e_dpf_import_is_fail {
Message: {
Import call 'config:config' is fail.
}
Attachment #0: {
Exception #EF2351921: e_dpf_import_depend_is_unresolved {
Message: {
Depend (pre-) 'config:abstract_element_child' is unresolved.
}
Attachment #0: {
Exception #EFFE73DC9: e_dpf_import_is_fail {
Message: {
Import call 'config:abstract_element_child' is fail.
}
Attachment #0: {
Exception #EF0F596E8: e_file_is_not_exists {
Message: {
File 'D:\Develop\wwwroot\dpf\dpf/../packages\config\class.config_abstract_element_child`.php' is not exists.
}