Никита К.
1594 повідомлення
#15 років тому
Вопрос к программистам: Как вы обрабатываете ошибки?

Например, если Вам надо передать в функцию какие либо параметры Вы
1. Сначала проверяете поступившие данные, а уже затем передаёте их функции
2. Передаёте их функции и проверяете их уже внутри

Далее, пользуетесь ли Вы механизмом обработки исключений try...catch?

Просто ведь можно написать, например,
if(file_exists($file)) $fp = fopen($file, 'r');


а можно
try {
$fp=fopen($file,"a");
if (!$fp) throw new Exception("open");

}
catch (Exception $e) {
show_error_page();
}


С одной стороны, первый вариант - короче.
С другой, второй - универсален. Один блок try{} позволит в результате обработать все возникающие исключения.

Я, всё таки склоняюсь к тому, что надо использовать try{}. Интересно послушать что считают другие =)
Андрей К.
1172 повідомлення
#15 років тому

<?php
$start=time()+microtime();
$counter=0;
for($i=0;$i<100000;$i++) {
if(file_exists('xxx.xxx'))
$fp=@fopen('xxx.xxx','r');
if(!$fp) {
$counter++;
}
}
$end=time()+microtime();
echo $end-$start.'<br /><br />';

$counter=0;
$start=time()+microtime();
for($i=0;$i<100000;$i++) {
try {
$fp=fopen('xxx.xxx','r');
if (!$fp)
throw new Exception("open");
}
catch (Exception $e) {
$counter++;
}
}
$end=time()+microtime();
echo $end-$start;
?>



0.228845119476

1.27323293686


Думаю мой ответ вы поймете.

P.S. Исключения использую только там, где нет возможности нормально проверить результат операции.
Никита К.
1594 повідомлення
#15 років тому
Н-да, разница в 6 раз это многовато... =)

А по поводу обработки данных до передачи в качестве параметра или после?
Здесь, насколько я понимаю разницы во времени не будет =)
Алексей С.
115 повідомлень
#15 років тому
Цитата ("tvv"):
Использование @ категорически не приемлемо.

К тому же при ошибке @ тормозит работу функции в несколько раз.
Андрей К.
1172 повідомлення
#15 років тому
Цитата ("tvv"):
Вместо этого для замеров, если конечно у Вас не PHP4, лучше использовать: $start = microtime(true);

Угу, забыл про нее. Давным давно не делал таких замеров через код.

Цитата ("tvv"):
Использование @ категорически не приемлемо. Конечно, в некоторых способах без него не обойтись (например при вызове функции mail в ряде конфигураций), или позволяется на демо примерах для подавления предупреждающих сообщений при получении входящих параметров, но это не тот случай.

Подробнее, почему? Разработчики PHP сами рекомендуют ее использовать. Даже в скорости потери почти нет, зато не выдаст сообщений об ошибках. И уж тем более видно прирост скорости при использовании такой проверки, а не при ловле исключений.



Цитата:
If the open fails, an error of level E_WARNING is generated. You may use @ to suppress this warning.
Андрей К.
1172 повідомлення
#15 років тому
Цитата ("trueW3C"):
К тому же при ошибке @ тормозит работу функции в несколько раз.


Здесь она возникает достаточно редко, когда файл есть, но открыть его нельзя. Все-таки перед ней стоит еще одна проверка.
Вадим Т.
3240 повідомлень
#15 років тому
Упс... мое вышестоящее сообщение нечаянно затерлось... жаль.

Цитата ("Lisio"):
Цитата ("tvv"):
Использование @ категорически не приемлемо. Конечно, в некоторых способах без него не обойтись (например при вызове функции mail в ряде конфигураций), или позволяется на демо примерах для подавления предупреждающих сообщений при получении входящих параметров, но это не тот случай.

Подробнее, почему? Разработчики PHP сами рекомендуют ее использовать. Даже в скорости потери почти нет, зато не выдаст сообщений об ошибках. И уж тем более видно прирост скорости при использовании такой проверки, а не при ловле исключений.

Можете дать ссылку, где разработчики PHP рекомендуют это безобразие использовать?

Это для быстрого ламерского затыкания дыр когда-то давно ввели, причем там, где не важна производительность.
И это работает весьма медленно, так как при использовании этого оператора выполняется ряд внутренних операций, которые в большинстве случаев избыточны (например подготавливается блок информации об ошибке, эта информация копируется в $php_errormsg если включена опция track_errors, и т.д. ).
В общем, это рудимент.

Про потери времени — а Вы замер сделайте. Только не на файловых операциях, где оно незаметно, а например на каком-то вычислительном процессе.
Вадим Т.
3240 повідомлень
#15 років тому
Цитата ("Lisio"):
http://ru2.php.net/manual/en/function.fopen.php

Цитата:
If the open fails, an error of level E_WARNING is generated. You may use @ to suppress this warning.

Это не рекомендация использовать @, а информация о самом простом (и ламерском) способе подавить предупреждающие сообщения.
Андрей К.
1172 повідомлення
#15 років тому
В том-то и дело, что я использую ее только на файловых операциях. В других случаях можно обрабатывать либо через условия, либо через исключения. И я бы не стал называть его ламерским. В данном конкретном случае это очень удобная фишка, очень хорошо вписывающаяся в код и не требующая громоздких конструкций для ненужной работы. Да и сами замечания возникают крайне редко. Про другие случаи я не говорю, т.к. сам использую ее только на работе с файлами.
Вадим Т.
3240 повідомлень
#15 років тому
<?php

$start = microtime(true);
for ($i = 0; $i < 1000000; ++$i) {
$x = @$_GET;
}
$stop = microtime(true);
printf("%.3f\n", $stop - $start);

$start = microtime(true);
for ($i = 0; $i < 1000000; ++$i) {
$x = isset($_GET) ? $_GET : null;
}
$stop = microtime(true);
printf("%.3f\n", $stop - $start);


У меня выдает в среднем:

2.294
0.258

Теперь почувствуйте разницу...
Вадим Т.
3240 повідомлень
#15 років тому

<?php

$_GET = '';

$start = microtime(true);
for ($i = 0; $i < 1000000; ++$i) {
$x = @$_GET;
}
$stop = microtime(true);
printf("%.3f\n", $stop - $start);

$start = microtime(true);
for ($i = 0; $i < 1000000; ++$i) {
$x = isset($_GET) ? $_GET : null;
}
$stop = microtime(true);
printf("%.3f\n", $stop - $start);


Даже если ошибок нет, все равно имеем в среднем:

1.113
0.496
Андрей К.
1172 повідомлення
#15 років тому

$sort = isset($_POST) ? 1 : 0;
$album = isset($_POST) ? (int)$_POST : 0;
$album_title = isset($_POST) ? trim($_POST) : '';
$resize = isset($_POST) ? 1 : 0;
$size = isset($_POST) ? (int)$_POST : 0;


Это выдержка из моего текущего личного проекта. Найдите тут @
Вадим Т.
3240 повідомлень
#15 років тому
Сразу скажу, при этой демонстрации я умышленно не ставил error_reporting(0), как это обычно сделано на продакшен серверах, что дало бы небольшое преимущество первому способу без дополнительной проверки (но только при отсутствии ошибок!). Но это в любом случае сделало бы @ бессмысленным, так что все равно мой пример показателен.
Андрей К.
1172 повідомлення
#15 років тому
tvv, не вижу поводов для спора. Я использую @ при файловых операциях и не вижу в этом ничего ламерского и предосудительного. Код читается лучше. Скорость не падает. В других случаях, как показал на примере, я использую конструкции проверки, похожие на ваши.
Вадим Т.
3240 повідомлень
#15 років тому
Цитата ("Lisio"):
Я использую @ при файловых операциях и не вижу в этом ничего ламерского и предосудительного. Код читается лучше. Скорость не падает. В других случаях, как показал на примере, я использую конструкции проверки, похожие на ваши.

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

В продакшен же коде это не нужно вообще, так как warnings все равно вырубаются (иначе имеем тормоза), и в этом случае оператор @ мало того что не имеет смысла, так еще и добавляет лишнего.
И да, это касается всех случаев, в том числе и файловых операций.

И код читается не лучше, так как @ просто лишний. Мало того что лишний символ, так еще и неизбежно у просматривающего этот код возникает куча вопросов, например зачем тут этот @ поставлен, и т.д.

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

Ну ладно, это мелочи, конечно. Вряд ли стоит отвлекаться на это.
Андрей К.
1172 повідомлення
#15 років тому
По поводу логики. Когда я пишу скрипты, часть кода нередко переношу в другие модули, или в другие проекты. А когда проект другой, то можно забыть выставить error_reporting в 0. Ведь движок не всегда собственного написания, а ставить это в каждый скрипт не вижу смысла. Если повезет, то такой движок могут запустить на хостинге, где php.ini настроен на выброс в output всех предупреждений и юзеры видят на экране то, что им не нужно. Можете называть параноидальной перестраховкой, но я предпочту оставить один символ лишним.

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

По поводу оптимизации. Вы не ошиблись, сделав про меня такой вывод. И в данном случае делаю исключение. Объясню почему. Насколько нормальным является возникновение ошибки или предупреждения в коде? Как правило, это экстраординарная ситуация, которая либо никогда не произойдет, либо произойдет в настолько редчайших случаях, что я предпочту пожертвовать парой миллисекунд в месяц в угоду читабельности кода. А если ошибка не произошла, то и замедления не будет, т.к. за один прогон двига не будет более 1-2 таких @.

P.S. Посчитав меня пароноиком оптимизаций вы не ошиблись. Но я еще и параноик читабельности. А символ @ IMHO либо читается лучше, либо просто не мешает этому.
Фрилансер У.
248 повідомлень
#15 років тому
Цитата ("Lisio"):
т.к. совершенно убежден, что проверка условиями практически всегда удобнее и читабельнее, чем конструкции с исключениями.

Да, очень читабельно, гибко и совсем неизбыточно.
if ($d->query('sql1')) die($d->error());
if ($d->query('sql2')) die($d->error());
// ...
if ($d->query('sql3')) die($d->error());
if ($d->query('sql3')) die($d->error());



try
{
$d->query('sql1');
$d->query('sql2');
$d->query('sql3');
$d->query('sql4');
} catch (DatabaseException $e) {
echo $e->message();
// другие действия
}
Андрей К.
1172 повідомлення
#15 років тому
werewolf, зря смеетесь. Вы бы еще так написали:


try {
// Весь движок
}
catch (Exception $e) {
// Сорри, косяк вышел
}


Так даже круче получится.
Фрилансер У.
248 повідомлень
#15 років тому
А что в этом плохого? Ошибки можно категоризировать и в зависимости от типа принимать разные действия.
Андрей К.
1172 повідомлення
#15 років тому
Для этого можно использовать стандартные проверки, не даром же функции возвращают результат своего выполнения. А если пихать в один try столько кода, то получится, что создается не проект, а универсальная система обработки ошибок.