Comments 102
> Теперь по попорядку
Исправьте :)
Идея не нова, но реализация понравилась. Спасибо за материал.
Исправьте :)
Идея не нова, но реализация понравилась. Спасибо за материал.
0
Один момент состоит в том что Fatal Error, который наиболее неприятен, это решение не перехватит. Как это сделать можно посмотреть в Debug_ErrorHook с dklab'а.
В остальном решение хорошее, спасибо.
В остальном решение хорошее, спасибо.
+2
Спасибо за подсказку. Решение до гениальности простое — register_shutdown_function();
Учту в следующей версии библиотеки.
Учту в следующей версии библиотеки.
+4
UFO just landed and posted this here
Спасибо. Обязательно посмотрю.
Я тоже думал о подобном решении. Только кроме логирования я хочу еще и правильный ответ выдать. Мой вариант писать в header особую метку. Если метки нет (значит скрипт не правильно отработал), то reverse proxy отдаст 500 ошибку и залогирует событие. Это может пригодится при автоматическом тестировании.
Баг в ПХП из-за которого приходится так извращатся bugs.php.net/bug.php?id=50921
Я тоже думал о подобном решении. Только кроме логирования я хочу еще и правильный ответ выдать. Мой вариант писать в header особую метку. Если метки нет (значит скрипт не правильно отработал), то reverse proxy отдаст 500 ошибку и залогирует событие. Это может пригодится при автоматическом тестировании.
Баг в ПХП из-за которого приходится так извращатся bugs.php.net/bug.php?id=50921
0
>register_shutdown_function не всегда срабатывает при Fatal Error.
Несогласен. Можете показать пример кода, когда она не срабатывает? Если вы имеете ввиду при E_PARSE в том же файле где определена register_shutdown_function(), то это логично и естественно — т. к. PHP-код из этого файла даже не успеет превратится в байт-код для интерпретатора.
Несогласен. Можете показать пример кода, когда она не срабатывает? Если вы имеете ввиду при E_PARSE в том же файле где определена register_shutdown_function(), то это логично и естественно — т. к. PHP-код из этого файла даже не успеет превратится в байт-код для интерпретатора.
0
> таги pre
чоткий поцан х)
> Универсальное решение
> Error и assertion обработчики будут бросать ErrorException.
даже фатальные? ;-) если фатальные ошибки молча сглатываются, то это фигня, а не универсальное решение.
> При вызове setupHandlers можно установить формат вывода, передав экземпляр класса
почему слой работы с исключениями у тебя общается напрямую с клиентом, игнорируя фронт контроллер, который специально для того и предназначен, чтобы скрыть от приложения способ, которым клиент подключается к серверу?
> Для создания нового формата достаточно создать класс, который будет наследоваться от абстрактного класса exceptionHandlerOutput и реализовать один метод (output).
в чём сакральный смысл наполнять приложение грудой классов из одного единственного метода в каждом?
> Как я и сказал выше логирование можно включать по желанию.
может лучше наоборот — по желанию отключать?
> exceptionHandlerLog::uncaughtException
из названия константы не очевиден её смысл.
чоткий поцан х)
> Универсальное решение
> Error и assertion обработчики будут бросать ErrorException.
даже фатальные? ;-) если фатальные ошибки молча сглатываются, то это фигня, а не универсальное решение.
> При вызове setupHandlers можно установить формат вывода, передав экземпляр класса
почему слой работы с исключениями у тебя общается напрямую с клиентом, игнорируя фронт контроллер, который специально для того и предназначен, чтобы скрыть от приложения способ, которым клиент подключается к серверу?
> Для создания нового формата достаточно создать класс, который будет наследоваться от абстрактного класса exceptionHandlerOutput и реализовать один метод (output).
в чём сакральный смысл наполнять приложение грудой классов из одного единственного метода в каждом?
> Как я и сказал выше логирование можно включать по желанию.
может лучше наоборот — по желанию отключать?
> exceptionHandlerLog::uncaughtException
из названия константы не очевиден её смысл.
-8
Кто-то настроение испортил?
- 1. Про фатальные ошибки обсудили в комментариях выше
- 2. Я обрабатываю только необработанные исключения, можно обрабатывать и на уровне приложения; в bootsrap файле может быть что-то типа
try{ myApplication::dispatch(); } catch(Exception $e){ //обработка }
Я предложил один из вариантов... - 3. Сакральный смысл — сделать расширяемое решение. Груда классов вряд ли понадобится — достаточно будет 1 или 2 кастомных обработчика (зависит от потребностей приложения)
0
неа о0"
2. не можно, а нужно. пользователю надо выдавать нормальную страничку с сообщением об ошибке. с навигацией, поиском и прочими плюшками.
3. через обычные функции его не расширить?
2. не можно, а нужно. пользователю надо выдавать нормальную страничку с сообщением об ошибке. с навигацией, поиском и прочими плюшками.
3. через обычные функции его не расширить?
-2
2. пользователю надо выдавать нормальную страничку с сообщением об ошибке. с навигацией, поиском и прочими плюшками.
Я только за.
3. через обычные функции получится не ООП код. А я предпочитаю ООП
Я только за.
3. через обычные функции получится не ООП код. А я предпочитаю ООП
0
а… религия… понятно х)
0
это не религия, это легкая поддержка кода, читаемость, reusablity, encapsulation, modularity и многое другое.
0
какое всё это умеет отношение к заворачиванию функций в классы?
+3
это ООП, детка. читай книги, их пишут умные люди, педалить можно научиться быстно, писать красивые приложения очень сложно… можно сделать все, но как, это уже другой вопрос
-4
эта спесь со временем пройдёт, оставив после себя лишь чувство стыда за свою юношескую фанатичность
0
разница между функцией и объектом, в том что объект еще может иметь состояние. Например, мне нужно реализовать формат вывода ошибок для SOAP сервера, для того чтобы вернуть SoapFault мне нужен инстанс SoapServer. В класс инстанс SoapServer можно передать, например, как параметр конструктора (см. код). А как это сделать для функции? Через глобальную переменую…
Если вас и этот аргумент не убедил, тогда я прошу помощь зала
Если вас и этот аргумент не убедил, тогда я прошу помощь зала
0
В ООП должна быть логика, а когда под ООП подразумевается «понаделать классов», то спешу огорчить, это даже не ООП.
Про «многое другое» не скажу, а вот легкая поддержка кода, читаемость, reusablity, modularity реализуется грамотным проектированием приложения и качественной реализацией.
Про «многое другое» не скажу, а вот легкая поддержка кода, читаемость, reusablity, modularity реализуется грамотным проектированием приложения и качественной реализацией.
+2
Мне одному кажется, что все попытки втащить в PHP куски кода и стиль из Явы и прочих Си-шарпов — это все от банального незнания (и нежелания знать) самого языка и чувства ложного превосходства над «быдло-кодерами на похапе»?
Или я ошибаюсь (допускаю и такой вариант)?
Или я ошибаюсь (допускаю и такой вариант)?
+4
Это не стиль Явы или Си-шарпа это стиль ООП. Я считаю, что ООП код гораздо проще поддерживать, он гораздо компактней и понятней. Но это дело вкуса.
+3
ОК, объяснюсь.
Вы пытаетесь обрабатывать ошибки интерпретатора средствами самого интерпретируемого языка. Это один подход.
Есть другой, реализованный в PHP и «родной» для языка — обработка ошибок интерпретатора передается внешнему обработчику, который делает то, что Вам надо — вывод стека вызовов, запись в лог, вывод на экран. В контексте PHP это более правильно, именно так построен стандартный обработчик и xdebug.
Вопрос к Вам: почему бы Ваш замечательный функционал не реализовать расширением к PHP, не было бы это правильнее?
Вы пытаетесь обрабатывать ошибки интерпретатора средствами самого интерпретируемого языка. Это один подход.
Есть другой, реализованный в PHP и «родной» для языка — обработка ошибок интерпретатора передается внешнему обработчику, который делает то, что Вам надо — вывод стека вызовов, запись в лог, вывод на экран. В контексте PHP это более правильно, именно так построен стандартный обработчик и xdebug.
Вопрос к Вам: почему бы Ваш замечательный функционал не реализовать расширением к PHP, не было бы это правильнее?
+3
UFO just landed and posted this here
Рискую напороться на минуса. Мне вот всегда было непонятно, что же это за «PHP-way». Т.е. вот есть куча языков и считается, что у каждого свои преимущества и недостатки, и вообще, думать надо для специфического языка по-своему. Так вот: я никогда не улавливал чего-то специфического, что предлагает PHP. Ну, точнее один момент уловил — когда нужно что-то архи-, мегапростое, то проще писать небольшой скрипт на PHP, чем мучиться с настройкой Hibernate, написанием шаблонов, контроллеров, разворачиванием всего этого дело на Tomcat. Что же насчёт больших проектов — непонятно, где преимущество подхода PHP и в чём же именно он отличается в предлагаемых средствах от Java (и вообще, нафига ему динамическая типизация). Т.е., например, я прекрасно понимаю, зачем динамическая типизация в Python и почему ряд задач на нём решается на порядок выразительнее чем на Java. А в PHP как раз для «больших» приложений начали утаскивать чуть ли не один-в-один ООП из Java, причём, похоже, динамическая типизация обеспечивает там одно «преимущество» — отсутствие необходимости аннотации типов. Оно сомнительно на фоне того, что те же Scala или F# вполне себе статически типизированы, но при том не требуют аннотации типов. А вот то, что поддержка в IDE из-за этого никакая — это, конечно, просто ужасно.
Так что я думаю, нечего пинать явистов с претензиями «вы нас не понимаете». Как мне кажется, у PHP своя ниша образовалась исторически. А может, из-за низкого порога вхождения. Но никак не потому, что PHP вносит что-то принципиально новое в мышление человека, пишущего на нём, и что мир PHP сильно отличается от Java, C# или Python.
Так что я думаю, нечего пинать явистов с претензиями «вы нас не понимаете». Как мне кажется, у PHP своя ниша образовалась исторически. А может, из-за низкого порога вхождения. Но никак не потому, что PHP вносит что-то принципиально новое в мышление человека, пишущего на нём, и что мир PHP сильно отличается от Java, C# или Python.
+1
Единственно правильная работа с похапе — это выкинуть его на хуй и осилить какой-нибудь язык программирования.
-36
так почему же вы этого не сделали?
0
Чем же он вам так не угодил? Расскажите подробнее о его недостатках перед другими языками, может тогда вы бы выглядели не так банально. Например тежи разработчики facebook с вами не согласны.
0
Недостатки, пожалуй, относительные, но каждый раз о них рассказывать…
Что сейчас на ум приходит
— нет настоящего FastCGI (частично решается opcode кешерами, но все равно сохранить объект между запросами без сериализации невозможно)
— Не очень удобная работа с исключениями (решается использованием фреймворков)
— Нет поддержки многопоточности и, вроде бы, асинхронных сокетов тоже (не всегда актуально, но многие любят на PHP демонов и всяких грабберов/парсеров писать)
— пространства имен появились совсем недавно и почти нигде не используются (это ваще ужасно). Разделитель пространств имен — обратный слеш — отдельный спор.
— Относительно много-длинно-словный синтаксис
да и тут еще немного написано ru.wikipedia.org/wiki/PHP#.D0.9A.D1.80.D0.B8.D1.82.D0.B8.D0.BA.D0.B0
По поводу FaceBook, мне кажется, использует PHP т.к. у них
1) накопилась большая кодовая база, переписывать слишком затратно
2) есть большие команды относительно дешевых разработчиков
3) они уже транслятор php в c++ написали…
Ну и реалтаймовые ответственные вещи у них давно на Java/C++/Python пишут (Cassandra, Tornado etc)
Что сейчас на ум приходит
— нет настоящего FastCGI (частично решается opcode кешерами, но все равно сохранить объект между запросами без сериализации невозможно)
— Не очень удобная работа с исключениями (решается использованием фреймворков)
— Нет поддержки многопоточности и, вроде бы, асинхронных сокетов тоже (не всегда актуально, но многие любят на PHP демонов и всяких грабберов/парсеров писать)
— пространства имен появились совсем недавно и почти нигде не используются (это ваще ужасно). Разделитель пространств имен — обратный слеш — отдельный спор.
— Относительно много-длинно-словный синтаксис
да и тут еще немного написано ru.wikipedia.org/wiki/PHP#.D0.9A.D1.80.D0.B8.D1.82.D0.B8.D0.BA.D0.B0
По поводу FaceBook, мне кажется, использует PHP т.к. у них
1) накопилась большая кодовая база, переписывать слишком затратно
2) есть большие команды относительно дешевых разработчиков
3) они уже транслятор php в c++ написали…
Ну и реалтаймовые ответственные вещи у них давно на Java/C++/Python пишут (Cassandra, Tornado etc)
-2
То есть, для средне статистического веб приложения недостатков практически нет?
Зато есть жирный достаток в виде: «есть большие команды относительно дешевых разработчиков»
Зато есть жирный достаток в виде: «есть большие команды относительно дешевых разработчиков»
+1
По идее, для среднестатистических проектов используют фреймворки/CMS, которые многие проблемы решают. И это нормально.
Но да, для простых приложений PHP пригоден (если забыть про неоптимальный синтаксис и несогласованность многих функций), более сложные могут начать тормозить из за слишком толстых фреймворков/оберток
Но да, для простых приложений PHP пригоден (если забыть про неоптимальный синтаксис и несогласованность многих функций), более сложные могут начать тормозить из за слишком толстых фреймворков/оберток
0
А! еще вспомнил! Бесит что нельзя передать аргументом функции другую функцию/класс как таковую, только строку с ее именем (вроде того, как в Javascript назначаются каллбеки). Не знаю как такая возможность правильно называется, к сожалению.
0
в 5.3 можно делать так:
$greet = function($name)
{
printf(«Hello %s\r\n», $name);
};
ну а потом передать ее куда угодно. Оно?
$greet = function($name)
{
printf(«Hello %s\r\n», $name);
};
ну а потом передать ее куда угодно. Оно?
0
Лямбда — функции? Хм, не уверен что это именно то… Уже существующую функцию, видимо, можно передать только обернув в лямбду…
А можно ли передать не функцию а класс?
Учитывая, что я забыл уже где мне это было как то очень нужно, возможно что это не так уж и важно.
А можно ли передать не функцию а класс?
Учитывая, что я забыл уже где мне это было как то очень нужно, возможно что это не так уж и важно.
0
array('Class', 'Method') — вот так можно
А в будущих версиях будет и нормальный синтаксис.
А в будущих версиях будет и нормальный синтаксис.
0
В PHP 5.3 есть возможность задать метод __invoke, класс обладающий таким методом можно вызывать как функцию, ну и соот-но использовать как callback тоже, а-ля:
class ErrorHandler { public function __invoke($severity, $message, $file, $line) { throw new ErrorException($message, 0, $severity, $file, $line); } } set_error_handler(new ErrorHandler);
0
А можно меня, тупого, ткнуть пальцем туда, где он детектит ошибки? :)
0
Я тоже как-то заморочился проблемой отлова ошибок, при чем, Fatal тоже нужно было обязательно отловить.
Ничего лучше не придумал, чем:
<?
ob_start(«fatal_error_handler»);
set_error_handler(«handle_error»);
…
ob_end_flush();
?>
Если есть варианты отлова и вывода фаталов, ткните пожалуйста -)
Ничего лучше не придумал, чем:
<?
ob_start(«fatal_error_handler»);
set_error_handler(«handle_error»);
…
ob_end_flush();
?>
Если есть варианты отлова и вывода фаталов, ткните пожалуйста -)
0
require на require_once подправьте
0
зачем, если он это делает один раз за все существование запроса?
если можно обойтись без require_once, лучше обходиться, он медленнее из-за соответствующей проверки.
если можно обойтись без require_once, лучше обходиться, он медленнее из-за соответствующей проверки.
0
Экономия на спичках? Типа того, чтобы использовать одинарные кавычки вместо двойных?
0
Да, это очень важно в высоконагруженных приложениях. Как правило люди, забывающие эти правила допускают очень много таких мелочей, которые в итоге можно еще ускорить на 5-20%
0
1. В высоконагруженных проектах нужно использовать APC и иже с ними, в таком случае проблема отпадает сама собой.
2. Разница есть только в случае использования относительных путей.
3. Если вообще не использовать require_once, в некоторых случаях придётся писать обёртки вокруг require, и не факт, что оно будет работать быстрее.
4. Обычно оптимизация алгоритмов даёт куда больше, чем 5%.
Итого: оптимизировать лучше в другом месте (например, поставить кэшер опкода).
2. Разница есть только в случае использования относительных путей.
3. Если вообще не использовать require_once, в некоторых случаях придётся писать обёртки вокруг require, и не факт, что оно будет работать быстрее.
4. Обычно оптимизация алгоритмов даёт куда больше, чем 5%.
Итого: оптимизировать лучше в другом месте (например, поставить кэшер опкода).
+1
Я не призываю писать обертку над require, я призываю не использовать require_once там, где он явно не нужен, тут именно такая ситуация.
APC кеширует опкод или он еще и оптимизирует что-то?
Я не против оптимизации алгоритмов, я призываю писать правильно всюду, даже в мелочах.
APC кеширует опкод или он еще и оптимизирует что-то?
Я не против оптимизации алгоритмов, я призываю писать правильно всюду, даже в мелочах.
0
APC берёт на себя все require* и include* запросы и обрабатывает их сам и без лишней возни, вообще не касаясь файловой системы (если файл уже в кэше). require_once как раз подтормаживает ввиду многократных state директорий.
«Писать правильно» — среди прочего это означает, что при подключении файлов с классами, нужно использовать require_once. В большинстве ситуации, инициализация данного модуля должна быть где-то в начале кода, но бывает всяко, и теоретически может случиться повторное включение файла. Хотя, это скорее исключение.
«Писать правильно» — среди прочего это означает, что при подключении файлов с классами, нужно использовать require_once. В большинстве ситуации, инициализация данного модуля должна быть где-то в начале кода, но бывает всяко, и теоретически может случиться повторное включение файла. Хотя, это скорее исключение.
0
Я все же НЕ считаю, что выбрасывать исключение по notice или warning было бы хорошей идеей.
Я сам для обработки ошибок использую www.firephp.org и всем доволен, кроме случаев, когда в стэке оказываются данные большого размера ))
Правда в этом случае лишаемся обработчика для CLI. Зато при включенной обработке ошибок, если они и возникнут, то не каждый их сможет увидеть!
Использовать Firephp проще простого
Я сам для обработки ошибок использую www.firephp.org и всем доволен, кроме случаев, когда в стэке оказываются данные большого размера ))
Правда в этом случае лишаемся обработчика для CLI. Зато при включенной обработке ошибок, если они и возникнут, то не каждый их сможет увидеть!
Использовать Firephp проще простого
0
С моим решением можно использовать FirePhp (он же WildFire). Для этого нужно создать класс exceptionHandlerOutputFirephp и экземпляр этого класса передать как параметр для setupHandlers. Могу попозже выложить код такого класса.
0
$firephp = FirePHP::getInstance(true);
$firephp->registerErrorHandler();
$firephp->registerExceptionHandler();
$firephp->registerErrorHandler();
$firephp->registerExceptionHandler();
+1
Хорошо написанная программа не notice не warning не бросает. Соответсвенно, notice говорит о том. что где-то недоработка (проблема), надо разбираться
+1
UFO just landed and posted this here
Я считаю, что "
Хотя у меня в классе есть настройка, которая говорит какие ошибки превращать в исключения. По умолчанию E_ALL. Те ошибки которые не будут превращаться в исключения будут залогированы с флагом lowPriorityError.
PHP Notice: Use of undefined constant myvar - assumed 'myvar'
" и "PHP Warning: mysql_connect(): [2002] A connection attempt failed
" вполне достойны для того, чтобы бросить исключение.Хотя у меня в классе есть настройка, которая говорит какие ошибки превращать в исключения. По умолчанию E_ALL. Те ошибки которые не будут превращаться в исключения будут залогированы с флагом lowPriorityError.
0
Она умеет писать в файл (или куда-то еще) фаталы и неотловленные исключения?
Отловить то их не проблема, а вот прологировать — так и не разобрались как, т.к. после неотловленного эксепшна или фатала PHP режет любые попытки открыть хендлы или соединения.
Отловить то их не проблема, а вот прологировать — так и не разобрались как, т.к. после неотловленного эксепшна или фатала PHP режет любые попытки открыть хендлы или соединения.
0
error_log умеет
0
error_log пишет не туда, куда надо (например, если я хочу писать XML в другое место).
Так или иначе, проблемы с другими хранилищами остаются открытыми. В нашем случае было бы удобно писать в какой-нибудь Redis и собирать потом демоном для отправки в баг-трек.
Возможно только открывать соединение до возникновения фатала, но это расточительно и бессмысленно, если фатала в итоге все равно нет.
Так или иначе, проблемы с другими хранилищами остаются открытыми. В нашем случае было бы удобно писать в какой-нибудь Redis и собирать потом демоном для отправки в баг-трек.
Возможно только открывать соединение до возникновения фатала, но это расточительно и бессмысленно, если фатала в итоге все равно нет.
0
error_log($messge."\n", 3, 'path/to/my-errors.log') пишет туда куда надо
А какие XML данные вы собираетесь писать при фатале, которых нет в стандартных логах вебсервера и php?
А какие XML данные вы собираетесь писать при фатале, которых нет в стандартных логах вебсервера и php?
+1
Умеет. Это вообще никогда не было проблемой, если в fopen путь к файлу абсолютный задаётся.
0
Спасибо за ссылку. Может возьму оттуда идеи. Смущаает следующее (то что сразу заметил):
- 1. на главной написано «Just 20kb of 100% OOP source code», а настройки сделаны через глобальные константы;
- 2. коду два года (так написано на главной), а в коде есть тудушки с элементарными вещами, за такое время можно было додлеать
0
1. на главной написано «Just 20kb of 100% OOP source code», а настройки сделаны через глобальные константы;
Это просто для примера. Если бы подробнее разобрались, то поняли бы, что они там могут как угодно задаваться.
2. коду два года (так написано на главной), а в коде есть тудушки с элементарными вещами, за такое время можно было додлеать
Последний коммит был 19 января 2010, см. лог. Тудушки там абсолютно не критичны.
0
Вопрос несколько не в тему. Возможно уважаемый автор что-то посоветует. Вопрос по отладке. Как отлаживать сайт, если:
а) Редактирование php файлов происходит по FTP(SSH) (через Aptana)
б) На сайте нет прямых вызовов скрипта, все через mod_rewrite
в) Хочу просто обновить страницу в бразуере и чтоб перекинуло в редактор на брейкоинт.
Какие переменные из этого уравнение нужно выкинуть, а какие добавить чтобы решить задачу? С XDebug никогда не работал.
а) Редактирование php файлов происходит по FTP(SSH) (через Aptana)
б) На сайте нет прямых вызовов скрипта, все через mod_rewrite
в) Хочу просто обновить страницу в бразуере и чтоб перекинуло в редактор на брейкоинт.
Какие переменные из этого уравнение нужно выкинуть, а какие добавить чтобы решить задачу? С XDebug никогда не работал.
-3
я думаю самый простой вариант — xDebug, FireFox и easyXdebug
0
Да по хорошему в Aptana (eclipse) встроен клиент для XDebug и настроить это дело довольно просто.
Только желательно чтоб сервер и Aptana на одном компьютере находились (точнее — чтобы СЕРВЕР МОГ подключаться к компьютеру с Aptana — типа внешний IP или одна сеть)
mod_rewrite особого значения не имеет
На шаред хостинге скорее всего такое настроить не удастся.
Только желательно чтоб сервер и Aptana на одном компьютере находились (точнее — чтобы СЕРВЕР МОГ подключаться к компьютеру с Aptana — типа внешний IP или одна сеть)
mod_rewrite особого значения не имеет
На шаред хостинге скорее всего такое настроить не удастся.
0
class exceptionHandlerOutputAjaxFactory extends exceptionHandlerOutputDefaultFactory
класс!
класс!
0
В PHP аж три «механизма ошибок»: собственно ошибки (error), исключения (exception) и утверждения (assertion). Свести три механизма к одному — exception.
Поправьте меня, если ошибаюсь. Типов ошибок в программе примерно два:
1. Ожидаемые (expected error, checked exception — не получилось открыть файл по причине его отсутствия)
2. Не ожидаемые (unexpected error, unchecked exception — закончилась память, неверный индекс массива, ошибка логики и так далее). Иногда не ожидаемые еще делят на системные (access violation) и программные (неверный аргумент функции, закончилась память, ошибка логики).
Я правильно понимаю, что Вы для всех типов ошибок хотите применять исключения?
0
Exception применяются для ошибок которые можно обработать на програмном уровне. Фактически все те, которые можно было бы обойти дополнительными проверками, например file_exists() перед чтением файла или array_key_exists для неверного индекса массива.
0
Тоесть, если я правильно понял фразу «которые можно обработать на програмном уровне», то для всех типов ошибок, которые я выше перечислил. Тогда это вызывает ряд вопросов:
1. Из кода будет не видна работа с ожидаемыми ошибками. Тоесть мы будем видеть вызовы функций, но не будем знать — обрабатывает ли программа от них ожидаемые ошибки где-нибудь выше или нет. Это, наверное, не очень хорошо.
2. Добавление кода в любую функцию будет очень стремным процессом, так как по ее сигнатуре не будет видно, ожидаются ли от нее ошибки (тоесть если функция/метод возвращает bool, то понятно что от нее ожидают ошибки и добавляемый код эту ошибку может вернуть. А если функция ничего не возвращает и кидает исключения — то добавляя любой код мы сильно рискуем тем что он кинет исключение ожидаемой ошибки, которое выше никто не обработает).
1. Из кода будет не видна работа с ожидаемыми ошибками. Тоесть мы будем видеть вызовы функций, но не будем знать — обрабатывает ли программа от них ожидаемые ошибки где-нибудь выше или нет. Это, наверное, не очень хорошо.
2. Добавление кода в любую функцию будет очень стремным процессом, так как по ее сигнатуре не будет видно, ожидаются ли от нее ошибки (тоесть если функция/метод возвращает bool, то понятно что от нее ожидают ошибки и добавляемый код эту ошибку может вернуть. А если функция ничего не возвращает и кидает исключения — то добавляя любой код мы сильно рискуем тем что он кинет исключение ожидаемой ошибки, которое выше никто не обработает).
0
Да такой подход предполагает внимательную обработку исключений. В месте где обработка критична нужно будет обработать все исключения (вплоть до верхнеуровневого — Exception) пример кода.
Где обработка менее критична, можно оставить это на откуп глобального обработчика — try...catch на самом верхнем уровне в бутсрапе или exceptionHandler.
Такой подход не означает, что не нужно делать проверки в коде, он даже стимулирует — потому, что вместо ворнинга, который можно игнорить получаешь исключение.
Где обработка менее критична, можно оставить это на откуп глобального обработчика — try...catch на самом верхнем уровне в бутсрапе или exceptionHandler.
Такой подход не означает, что не нужно делать проверки в коде, он даже стимулирует — потому, что вместо ворнинга, который можно игнорить получаешь исключение.
0
Да такой подход предполагает внимательную обработку исключений. В месте где обработка критична нужно будет обработать все исключения (вплоть до верхнеуровневого — Exception)
Не боитесь, что код достаточного большого и сложного проекта, построенного по такой архитектуре, будет плохо читаем из-за того, что громную его часть будет составлять олинаковые россыпи try… catch? Не опасаетесь ошибок из-за copy-paste и замыливании взгляда при таком количестве одинаковых блоков?
0
При правильном использовании try catch код становится более читабельным, чем при использовании if else. При if else обычно получается лесенка, и всякие else условия отвлекают от основной логики. При exception код «выпрамляется», можно четко увидеть позитивную ветку логики. Вот для сравнения два примера: код на if else, код на exception. И совсем экстремальный вариант при преобразовании ошибок в exception, не скажу что это правильный вариант, так как это определный magic — все таки разработчик должен точно знать и обрабатывать все ошибочные ситуации.
Насчет замыливания глаза, это для каждого по своему. А copy-paste в первую очередь зависит от квалификации и ответсвености разработчика. И архитектура не может ни стимулировать ни предотвратить этого.
Насчет замыливания глаза, это для каждого по своему. А copy-paste в первую очередь зависит от квалификации и ответсвености разработчика. И архитектура не может ни стимулировать ни предотвратить этого.
+1
Код с использованием if-else выглядит как лесенка только если нужно ручное сворачивание стека. А так как у нас есть классы, то… if-else без лесенки
0
ну так конечно симпатичней. А если нужно передать из функции кроме факта ошибки(return false) еще и детали ошибки, то можно передать скажем ассоциативный массив, в котором будет тип/номер ошибки, меседж, ит.п; но массив это не стандартизация, если несколько разработчиков, то каждый может создавать ключи в массиве кто какие хочет — заменяем массив объектом (инстанс класса ошибки); теперь типы ошибок тоже надо бы стандартизовать — проще простого, вводим константы, чтоб они не висели в глобальном скопе кладем их в класс ошибки. А теперь, хочется еще и иметь возможность передать эту ошибку выше, т.е. в функцию которая вызвала функция…
Так слово за слово. Где-то в конце этих рассуждений, можно прийти к модели очень сильно напоминающую исключения. И понять, что получился кривоватый велосипед, для работы с которым написан мануал, при работе с «велосипедом» он диктует как кодить (обязательно должен быть ретерн в функции, на выходе нужно проверить ни является ли объект инстансом класса ошибки и.т.п). Но если остановится где-то на ранних стадиях, то такой подход имеет право на жизнь. А если вы начинаете что-то изобретать, я бы посоветовал использовать готовое
Так слово за слово. Где-то в конце этих рассуждений, можно прийти к модели очень сильно напоминающую исключения. И понять, что получился кривоватый велосипед, для работы с которым написан мануал, при работе с «велосипедом» он диктует как кодить (обязательно должен быть ретерн в функции, на выходе нужно проверить ни является ли объект инстансом класса ошибки и.т.п). Но если остановится где-то на ранних стадиях, то такой подход имеет право на жизнь. А если вы начинаете что-то изобретать, я бы посоветовал использовать готовое
0
А если нужно передать из функции кроме факта ошибки(return false) еще и детали ошибки, то можно передать скажем ассоциативный массив, в котором будет тип/номер ошибки, меседж, ит.п
Как показывает достаточно широкая практика, из функции надо очень-очень редко вернуть что-то отличное от false. Более того, для исключений возврат дополнительной информации приводит к необходимости… нового класса исключения :). Так что тут как бы паритет в области, которая случается раз в пару месяцев (для библиотек — чуть чаще, но мы же не всегда пишем библиотеки?) и ни на что не влияет.
Я правильно понимаю, что больше аргументов в пользу использования исключения для обработки ожидаемых ошибок нету?
0
Как показывает достаточно широкая практика, из функции надо очень-очень редко вернуть что-то отличное от false
Ну вот в приведенном примере, задача вывести информативное сообщение пользователю. Если нет конекта к базе «сервер временно не доступен», если какой-то файл не читаем «Не возможно открыть файл <имя файла>», если какой-то файл не подходит по формату «Не верный формат файл <имя файла>».
Если действительно в функции есть два исхода true/false и неудача происходит только по одной различимой причине, то подход с return true/false тоже подойдет. Но с другой стороны если, когда-то нужно будет расширить функционал, то придется делать или исключения или собственный механизм работы с ошибками. Вариант с собственным механизмом работы с ошибками мне не нравится. Остаются исключения.
0
Вопрос как и где рапортовать пользователю неудачи — это как правило архитектурный вопрос. Как обычно делают:
pastebin.com/DKid5jbf
pastebin.com/DKid5jbf
0
А если view надо отделить от model/control?
0
Как уже говорилось выше, это вопросы архитектуры приложения. Мало ошибку поймать — очень часто с ней надо что-то делать :). Рассмотрим самую простую ситуацию когда у нас есть веб страничка, где в качестве UI выступает HTML, а в качестве Model выступает написанный на php код, который выполняется на сервере. Ну и хотим мы, значит, в случае ошибки выдать пользователю подробный лог своих внутренностей (btw, задача странная, обычно это на сервере в лог складируется, а наружу у нас классическое хабровское 'что-то случилось, попробуйте еще разок').
Соответственно, код у нас будет выглядеть примерно следующим образом (PHP знаю плохо, поэтому ограничимся псевдокодом):
Соответственно, код у нас будет выглядеть примерно следующим образом (PHP знаю плохо, поэтому ограничимся псевдокодом):
// Временный объект, будет собирать нам ошибки. $handler = new ErrorHandler(); соединим $database.ReportError с $handler.OnError // Все сломалось? if( ! $database.DoSomeComplexAction() ) { // Получаем текст с красивым сообщением о том, что именно поломалось внутри // $database. $text = $handler.PrettyPrint(); // Информируем соответствующий View о том, что пользователю нужно // показать страничку с нашими внутренностями. $erro_view.Show( $text ); }
+1
Настоятельно вас прошу указать под какой лицензией распространяются данные исходные коды.
Так же смею настоять на AS-IS?
Так же смею настоять на AS-IS?
0
2Offenso. Достаточно будет, если я напишу это в комментарии?
Код распространяется под «лицензией» AS-IS. Вы можете копировать, модифицировать код без указания автора и без уведомления автора. Можно использовать в коммерческих проектах. Хотя сейчас, мне этот код не кажется идеальным и я бы не использовал его в коммерческих проектах.
Мнения автора могут не совпадать с его точкой зрения (с)
Код распространяется под «лицензией» AS-IS. Вы можете копировать, модифицировать код без указания автора и без уведомления автора. Можно использовать в коммерческих проектах. Хотя сейчас, мне этот код не кажется идеальным и я бы не использовал его в коммерческих проектах.
Мнения автора могут не совпадать с его точкой зрения (с)
0
Sign up to leave a comment.
Правильная обработка ошибок в PHP