Написал статейку о классе обработки ошибок. Оцените.

Бочонок

http://frontender.info
Написал статейку о классе обработки ошибок. Оцените.

Приятного времени суток.

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

Буду очень благодарен за любые ваши комментарии. В топике, в личке, на хабре - не важно.
http://silentimp.habrahabr.ru/blog/56416/
 

whirlwind

TDD infected, paranoid
ошибка возникла, но она не критична и ее возможность предусмотрена логикой программы
Вы не с фирмы 1С случайно? А то там тоже план по колву багов иначе денег зарабатывать не на чем. Ошибки не надо обрабатывать.
 

Бочонок

http://frontender.info
Я не очень понял, что вы имеете в виду.
Почему ошибки не надо обрабатывать?

Что касается того что может быть некритическая ошибка, пример:

Перед проведением некого сложного запроса к БД мы делаем запрос к кешу. Кеш генерирует ошибку. О ней сообщается администратору по почте. Он садится и выясняет в чем дело. Пользователь при этом все равно получает свои данные. Только не из кеша а из бд. И знать, что что-то не так с кешем ему не нужно совершенно.
 

atv

Новичок
Бочонок, вся логика по работе с исключениями укладывается в самих исключениях и try ... catch.

Если ошибка "некритическая", т.е. может быть обработана в контексте данного приложения, т.е. такая обработка предусмотрена логикой данного приложения, то ставим try ... catch и обрабатываем её.

Если обработать не можем или не знаем как, останавливаем приложение, только не где попало в коде, а в самом верхнем блоке try ... catch, который охватывает весь код приложения.

Это я к тому, что никакой надстройки вообще не требуется. А вот этот код, это не обработка ошибок. Это просто вывод сообщения об ошибке, сопровождающийся полной остановкой приложения.

PHP:
define('some_err',true);
$err = new error_class("err_overwork");
$test_instance = new test_class;
$test_instance->complex_method();
if($test_instance->err->is_err()!==false){
	$err->fire_err($test_instance->err->is_err(),-1);
}

function err_overwork($error){
	die("Ошибка: ".$error->getMessage()."<br/>Файл: ".$error->getFile()."<br/>Строка: ".$error->getLine());
}
К тому же, если в этом коде произойдёт ошибка, то до проверки "if($test_instance->err->is_err()!==false)" дело не дойдёт, так как приложение остановиться строкой "die("Ошибка: ".$error->getMessage()"

Вместо того, чтобы помещать обработку исключений в многочисленные колбэки, проще поместить эту обработку в блоки try ... catch.
 

Бочонок

http://frontender.info
2zerkms:
Я имею в виду, что ошибка происходит во время его работы и один из методов взводит флаг ошибки.
Дальше можно либо прервать выполнение программы, либо... не прерывать.

2atv:
Бочонок, вся логика по работе с исключениями укладывается в самих исключениях и try ... catch.
Почему вы считаете что try...catch лучше чем callback? Помоему помещать весь код в логическую конструкцию не очень красиво.
Если ошибка "некритическая", т.е. может быть обработана в контексте данного приложения, т.е. такая обработка предусмотрена логикой данного приложения, то ставим try ... catch и обрабатываем её.

Если обработать не можем или не знаем как, останавливаем приложение, только не где попало в коде, а в самом верхнем блоке try ... catch, который охватывает весь код приложения.
Ну... у меня все именно так и присходит, за исключением того, что код не нужно писать в очередной логической конструкции. С перехватом исключений прекрасно справляется set_exception_handler
Это я к тому, что никакой надстройки вообще не требуется. А вот этот код, это не обработка ошибок. Это просто вывод сообщения об ошибке, сопровождающийся полной остановкой приложения.
Эм... как правило вывод сообщения об ошибке это и есть, с моей точки зрения, единственно верная ее обработка.
К тому же, если в этом коде произойдёт ошибка, то до проверки "if($test_instance->err->is_err()!==false)" дело не дойдёт, так как приложение остановиться строкой "die("Ошибка: ".$error->getMessage()"
Если интерпретатор сгенерирует любую ошибку, кроме синтаксической, то ее обработка будет передана колбек функции (err_overwork в данном случае).


Вместо того, чтобы помещать обработку исключений в многочисленные колбэки, проще поместить эту обработку в блоки try ... catch.
И все скрипты нужно будет заключать в try/catch?
Зачем? Помоему писать весь код внутри одного большого трая это не самая удачная идея. Коллбек красивее.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
>вывод сообщения об ошибке это и есть, с моей точки зрения, единственно верная ее обработка.

бывают проекты посложнее
я при ошибке делаю откат транзакции БД, пишку ошибку в лог, отправляю уведомление админу по почте и вывожу специальную страницу с извинением

-~{}~ 04.04.09 14:23:

>Коллбек красивее
а с говном путь сантехники разбираются :)
 

Бочонок

http://frontender.info
2grigori: ну и пожалуйста.
Мой класс позволяет обрабатывать ошибку так, как вам угодно. По крайней мере особых ограничений я на данный момент не вижу.

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

-~{}~ 04.04.09 15:36:

Конструкция try/catch почему то лучше чем перехват исключений через set_exception_handler? Поясните пожалуйста, почему.
 

whirlwind

TDD infected, paranoid
Ошибки не надо обрабатывать. Ошибки надо не допускать.
А если у тебя ошибка потому что тупой юзер вася удалил каталог кеша, то это исключение. Как ты собираешься обрабатывать эту ситуацию? Писать письмо юзеру васе что де он такой нехороший зачем удалил каталог кеша или создавать каталог кеша не лету? Если второе, то это не ошибка а запланированное поведение.

Давайте приведите пример ваших ошибок и мы вместе подумаем что это такое на самом деле.

PS. Вы только подумайте на сколько разбухает ваш код с этой обработкой ошибок. И в этом коде обработки ошибок столько же ошибок сколько и в любом другом вашем коде.
 

Бочонок

http://frontender.info
2whirlwind: если тупой юзер вася удалил каталог кеша, то поддержка сайта должна получить уведомление о том, что кеш умер, а пользователь должен получить данные из другого источника. И да, должен быть сгенерирован новый каталог кеша, или выделен участок памяти, или что либо еще, если есть такая возможность. Система по возможности должна быть сбоеустойчивой.

Пример 1:
Работа кеша. Кеширование реализовано с использованием общей памяти. Этот же класс используется для передачи системных сообщений.

Случай А: у нас сбой в работе кеша при генерации системного сообщения. С помощью set_err взведен влаг ошибки. Скрипт, вызвавший метод и проверивший после его вызова флаг ошибки вызывает исключение c помощью fire_err. Ошибка передана в назначеный разработчиком каллбек обработчик. Обработчк прерывает работу скрипта и выврдит сообщение о ошибке.

Случай Б: у нас сбой в работе кеша при попытке запросить данные, которые мы получаем с помощью запроса в бд. С помощью set_err взведен влаг ошибки. Скрипт, вызвавший метод и проверивший после его вызова флаг ошибки отправляет письмо в службу поддержки о том, что присутствует такая то ошибка. Скрипт получает данные из бд вместо кеша и пользователь продолжает работать ниочем не подозревая.

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

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

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

-~{}~ 04.04.09 18:02:

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

zerkms

TDD infected
Команда форума
Класс кеша ничего не знает о том как обрабатывается ошибка и что с ней вообще происходит. Он только сообщает о ее наличии.
Класс обработки ошибок ничего не знает о том что вызвало ошибку, или как именно с ней обращатся. Все что он делает - хранит информацию о том что она есть и позволяет передать ее обработчику назначеному пользователю.
если забыть, что разговор о каком-то кастомном классе, можно предположить, что автор сих слов говорит о механизме исключений. не?
 

Бочонок

http://frontender.info
zerkms, мой класс использует в том числе механизм исключений.
НО, он позволяет работать так же с флагом ошибки и просто проигнорировать ее, если в каком то контексте это разумно, не поднимаясь вверх по стеку до ближайшего катча.
И он служит удобной оберткой для механизма исключений.
Мой класс предоставлет возможность удобного управления методами обработки исключений, ошибок генерируемых интерпретатором, и ошибок, которые генерируются пользовательским скриптом.
 

cDLEON

Онанист РНРСlub
ЧЕМ ваши колбеки удобнее try {} catch {} ?
Когда вы не хотите подниматься выше по стёку try {} catch{} вы просто не отправляете отловленное исключение ещё выше.
Ваш класс в итоге разведёт кучу навоза вокруг и въезжать в этот навоз будете только вы. Не говоря уже о том, что логика вашей программы становится запутанной.
 

Бочонок

http://frontender.info
Колбеки передаются стандартным же set_error_handler и set_exception_handler. Не более. Вместо нескольких строк которые пришлось бы писать что бы вызвать их напрямую достаточно написать одну строку строку с конструктором класса. При этом try catch это не отменяет - хотите пользуйтесь. fire_err( тоже немного корочем чем trow new Exception(. Кроме того неотловленное исключение просто будет выброшено в поток. Если пользоватся флагами - такой проблемы нет.

Ну... что сказать.
Судя по отзывам - класс бесполезен для всех, кроме меня.
Так тому и быть.
Если удобнее пользоватся исключениями без врапперов и каких то альтернативных методов обработки - пользуйтесь.
 

fixxxer

К.О.
Партнер клуба
>> Вот дали позавчера приглашение на хабр.

Ясно :D
 

Бочонок

http://frontender.info
логика кстати становится неменее запутаной чем при коде повсеместно обернутом в try.

-~{}~ 04.04.09 20:29:

2fixxxer: ну... решил сделать что то полезное. Поделится мыслями. Заодно узнать что об этом думают окружающие. С кем не бывает?
 

atv

Новичок
Почему вы считаете что try...catch лучше чем callback?
В приложении может кидатся сотни различных исключений. Представим, что по логике приложения половину из них нужно обработать. Значит, в твоём случае, для перехвата исключения нужно:

1. назначить колбэк, умеющий обрабатывать перехватываемое исключение
2. выполнить код, в котором может произойти исключение
3. вернуть предыдущий колбек.

в случае с try...catch:
1. в блок try поместить код, в котором может произойти исключение
2. в блок catch поместить обработку исключения, которая к тому же, выполняется в контексте того же метода, т.е. имеет доступ ко всем локальным переменным метода.

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

Сделай эту задачу двумя способами, своим и с помощью try...catch. Результат обсудим.

И все скрипты нужно будет заключать в try/catch?
Зачем???
 

whirlwind

TDD infected, paranoid
Автор оригинала: Бочонок

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

Ошибки не надо обрабатывать. Ошибки надо не допускать.
[skipped]

а еще примеры будут? Все делается гораздо изящнее: без программирования ради программирования. Пишется декоратор делегирующий экземпляру класса БД в случае если кеш не содержит данных.
 
Сверху