![]() |
Модераторы: skyboy, MoLeX, Aliance, ksnk |
![]() ![]() ![]() |
|
Dima 2015 |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 287 Регистрация: 16.3.2008 Где: SPb Репутация: 2 Всего: 2 |
Добрый, теперь уже вечер, уважаемые коллеги!
Хотел посоветоваться с опытными людьми - как правильно подходить к выбрасыванию и обработке исключений в проекте, скажем так среднего размера (порядка 100 исполняемых скриптов). Сейчас в нем никаких исключений нет и клас Exception не трогается вообще нигде. У нас сейчас как все сделано. Есть классы, в них ф-ции которые чтото делают, и если сделалось - возвращают ТРУ, иначе - ФАЛСЕ. На этом построена вся логика проекта. Так вот как я понял, есть другой вариант - ф-ции могут возвращать чего им надо, или вообще ничего, а в случае неудачи просто выбрасывать соответствующие исключения, ведь код то после выброса исключения не выполняется, а ловится catch и оттуда уже пляшет... Мне было предложено внедрить систему исключений чтобы она делала 2 вещи - выдавала сообщение юзеру если чтото нетак и писала в админ-лог сообщение если это "нетак" тянет на попытку взлома или несанкционированного доступа. Что я сделла на данный момент? Есть класс наследуемый от базового класса Exception, в его конструктор передается пачка параметров, с которыми работают методы-обработчики исключений.
Основным звеном у меня сдесь является переменная $errorLevel. По ее значению обработчик исключения (метод render() в классе Exceptions) тупым switch-case - ом перебирает ошибки и решает что делать - выводить ли юзеру ошибку (текст которой был передан в конструктор), писать ли лог админу (текст тоже был передан в конструктор) и т.д. и т.п. И эта схема на все случаи жизни - неверное заполнение форм, попытка взлома, неверный логин-пароль, ошибка БД и прочее прочее прочее... В исполняемых скриптах я делаю следующее:
Вот в общем то так. Но чтото у меня есть подозрение что кривоватый подход. Куча параметров передается в конструктор, 1 ф-ция с кучей case-ов при обработке. Я с большими проектами работаю совсем недавно и вот интересно, может есть уже общий "правильный" подход, используемый в данной задаче. Например была мысль что на каждый логический блок исключений свой класс-наследник - ошибки ввода данных формы, ошибки доступа и тд. Правда так получается что просто куча case-ов заменяется кучей классов и все )))) В общем хочется послушать что скажут те, кто уже собаку съел на этом деле, можно даже послать меня читать ченить умное, желательно по-русски. Хотя я поиск прошерстил уже нехило, в основном встречаются простейшие примеры - аля кидать исключение вот так, ловить вот так... |
||||
|
|||||
Mal Hack |
|
|||
![]() Мудрый... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 9926 Регистрация: 15.2.2004 Репутация: 122 Всего: 261 |
Лично я всегда исходил из такой позиции:
1. Надо отличать исключения и проверку работы функции на ошибку. 2. Исключения надо ловить там, где они есть. 3. Проверку выполнения надо делать там, где может быть ошибка (возвращена функцией) 4. Реализация своих исключений должна быть тогда, когда это явно проще с точки зрения обработки (большое кол-во последовательных операций) |
|||
|
||||
Dima 2015 |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 287 Регистрация: 16.3.2008 Где: SPb Репутация: 2 Всего: 2 |
Mal Hack,
1. А что ты вообще подразумеваешь проверкой ф-ции на ошибку? 2. Мне бы понять где они и с чем их есть вообще ))) У меня с идеологией проблемы видимо. Синтаксис и конструкции я худо-бедно разобрал. А вот где и как они должны применяться не понимаю. 3. Ну и соответственно что ты подразумеваешь под проверкой выполнения... 4. Надо так понимать когда логика сожная - куча вложенных ифов? Тогда проще исключения делать? Чтобы сразу предусмотреть все "плохое", что может случиться... В общем хочется както более развернуто чтоли, а то я даже синтаксис фраз твоих не очень понимаю ))) Хотя может просто голова уже не варит... |
|||
|
||||
Mal Hack |
|
||||
![]() Мудрый... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 9926 Регистрация: 15.2.2004 Репутация: 122 Всего: 261 |
fp = fopen() if(!fp) {error} http://www.php.net/manual/en/language.exceptions.php
см. п.1.
Это уже зависит от задачи, точнее от способа ее реализации ![]() |
||||
|
|||||
Dima 2015 |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 287 Регистрация: 16.3.2008 Где: SPb Репутация: 2 Всего: 2 |
Mal Hack, понятно... : )))
Видать это токо с опытом приходит. По сслыке что ты дал я ходил уже раз 10 : )) |
|||
|
||||
solenko |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1473 Регистрация: 15.1.2006 Где: Украина Репутация: 34 Всего: 67 |
Когда удобны исключения? Когда у вас огромная вложенность взаимосвязанных операций.
Например, Проверить есть ли жизнь на марсе -> отправить экспедицию -> запустить корабль -> запустить двигатель У вас на последнем этапе выясняется, что корабль забыли заправить. Вы генерите exception, который отлавливается в самой верхней функции. Итог -- отсутствие кучи проверок + общественность оповещена, что в этот раз выяснить ничего не удалось + причина ушла в лог. Ну и, естественно, exception оно на то и исключение, чтобы генерится при внештатной работе скрипта. Лично я против их использования, вместо обычных проверок, например, прав доступа. Но это уже дело вкуса и религии ) -------------------- Ла-ла-ла-ла Заметьте, нет официального подтверждения, что это не просто четыре слога. |
|||
|
||||
Dima 2015 |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 287 Регистрация: 16.3.2008 Где: SPb Репутация: 2 Всего: 2 |
solenko, пример порадовал ))))
Вообще тема интересная конечно, мне начинает казаться что грамотное использование исключений сродни искусству. Жаль народ вяло отвечает... |
|||
|
||||
solenko |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1473 Регистрация: 15.1.2006 Где: Украина Репутация: 34 Всего: 67 |
Забыл упомянуть, что все функции в иерархии должны генерить exception, кастомного класса и, соответственно, в верхней функции нужно ловить только его.
-------------------- Ла-ла-ла-ла Заметьте, нет официального подтверждения, что это не просто четыре слога. |
|||
|
||||
Dima 2015 |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 287 Регистрация: 16.3.2008 Где: SPb Репутация: 2 Всего: 2 |
solenko, прости, а что ты называешь верхней ф-цией?
|
|||
|
||||
solenko |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1473 Регистрация: 15.1.2006 Где: Украина Репутация: 34 Всего: 67 |
Dima 2015, ну в моем примере это "Проверить есть ли жизнь на марсе". Суть в том, что генерация MarsException будет означать, что скрипт, в принципе, отработал корректно, но по какой-то причине не смог выполнить все. А если у тебя случился просто Exception, то речь уже идет действительно о ошибке.
-------------------- Ла-ла-ла-ла Заметьте, нет официального подтверждения, что это не просто четыре слога. |
|||
|
||||
sTa1kEr |
|
||||||
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
Dima 2015, когда следует использовать екзепшены, советую прочитать этот пост.
1. Бессмысленно тут передавать __FILE__ и __LINE__, т.к. эти данные и так содержатся в экзепшене. 2. Использовать экзепшены только для логирования ошибок - все равно что забивать гвозди микроскопом, т.к. это значительно более гибкий и мощьный инструмент. 3. В данном куске кода экзепшены не нужны вовсе, т.к. не правильный логин/пароль - это вовсе не исключительная ситуация. Исключительная ситуация была бы, к примеру, если бы логин и пароль был верный, но запись о пользователе отсутствовала. Попробую объяснить на примере.
И еще, применимо к PHP:
В идеале, любой скрипт должен работать именно в таком режиме. |
||||||
|
|||||||
Dima 2015 |
|
||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 287 Регистрация: 16.3.2008 Где: SPb Репутация: 2 Всего: 2 |
sTa1kEr, спасибо большое за пост. Собираю информацию об эксепшенах по крупицам, твоя крупица была одной из самых больших )))
Теперь по пунктам.
Это как раз и сделано для того, что ты написал в конце. Все дело в том что у меня всего 1 класс - наследник от Exception. Как я понимаю для нормальной работы с ними этих классов должно быть много - на каждый вид исключения свой. Даже у тебя в примере их 2 + еще ErrorException, итого уже 3. Так вот __FILE__ и __LINE__ передаются с учетом того, что может быть установлен обработчик ошибок ПХП set_error_handler, у него то эти параметры обязательными являются и они должны пойти в конструктор соответствующего эксепшена. Правда немного пугает количество возможных исключений. Пустое поле, попытка взлома, ошибка ПХП скрипта, ошибка БД, не найдена запись... так количество классов исключений перевалит за количество классов самого проекта : )))) 2. Ну я вот и пытаюсь разобраться с его гибкостью... пока все что придумалось. Теперь по твоему примеру...
Вот это вообще повергло в тихий шок... Я уже уяснил что catch ловит все исключения указанного класса и всех его потомков, т.е. catch (Exception $ex) поймает вообще все исключения, что были. Т.е. тут ты их ловишь и снова выбрасываешь получается... жесть, как она есть. Честно говоря сложно следить за такой логикой. И еще, не очень понял фразу
|
||||||
|
|||||||
sTa1kEr |
|
||||
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
Если собрался пользоватся исключениями, то забудь про set_error_handler() раз и на всегда. Используй его только для http://php.net/errorexception .
Все. И не надо никаких __FILE__, __LINE__. Не надо создавать их на каждый чих. Обычно в среднем требуется по одному исключению на компонент. Если необходимо перехватить и обработать конкретное исключение, то тогда создай его. Иначе достаточно общего исключения. Например, у тебя логика приложения не зависит от того какая именно ошибка в БД произошла, то для всех исключений связанных с БД достаточно одного класса DbException например. А если хочешь отдельно обрабатывать ошибки вставки и отдельно ошибки удаления записей из БД, то наследуешь от DbException -а DbInsertException и DbDeleteException. Тогда перехватывая DbException, попрежнему будешь ловить все ошибки БД, но приэтом если понадобится, то сможешь так же ловить и конкретно ошибки вставки или удаления. А часто может быть достаточно внутренних исключений или же базового Exception. http://www.php.net/~helly/php/ext/spl/classes.html - тут можешь посмотреть какие есть в PHP встроенные исключения. На самом деле в данном примере последний catch не обязателен (хоть и не мешает), я просто хотел показать как с ними можно работать, но немного не тот пример привел. А происходит примерно следующее: Открывая блок try, мы говорим, что ожидаем исключительную ситуацию в этом блоке. После блока идет выборка какое исключение и как мы будем обрабатывать (примерно тоже самое что и со switch case -ами) В первом catch-е мы ловим конкретные исключения FileNotFoundException и обрабатываем его полностью, в результате чего функция корректно отрабатывается и возращает false. А во втором блоке уже ловим все остальные, что-то делаем с ними и явно бросаем дальше. Т.е. в моем примере это равносильно тому, если бы вообще не писать второй catch, тогда бы все остальные исключения просто проходили дальше в выше стоящий блок try или если больше блоков try нету то выдавался бы fatal error. Еще пример, если нам надо обработать все исключения, кроме какого-то конкретного
Т.о. из этого блока дальше пробрасыватся будут только SomeException. |
||||
|
|||||
Dima 2015 |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 287 Регистрация: 16.3.2008 Где: SPb Репутация: 2 Всего: 2 |
sTa1kEr, жжесть. Как она есть. Я так и подозревал что не так это все просто. Пока видимо мне придется оставить так как есть, буду по-тихоньку разбираться и учиться использовать всю гибкость исключений. А тебе спасибо еще раз, буду переодически возвращаться в эту тему подглядывать. Вот именно таких примеров я и искал, чтоб показали как работает, а не просто синтаксис. И почему-то сложно найти, ни в книгах, ни в инете...
|
|||
|
||||
yurik_l |
|
|||
тарантиноман Профиль Группа: Участник Сообщений: 49 Регистрация: 17.9.2006 Репутация: 1 Всего: 3 |
||||
|
||||
![]() ![]() ![]() |
Правила форума "PHP" | |
|
Новичкам:
Важно:
Внимание:
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | PHP: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |