Зачем нужны throw Exception?

Вурдалак

Продвинутый новичок
Фанат, ты что-нибудь слышал о принципе «tell, don't ask»? Ты ведь просто взял и переврал слова fisher'а и fixxxer'а. Есть объект, занимающийся валидацией — и тут никто не спорит, что есть задача сказать нам. Но ведь мы можем и исключить валидатор из кода:
PHP:
public function handle(Request $request)
{
	if ($this->getValidator()->isValid($request)) {
		$this->save($request);

		return $this->createRedirectResponse();
	} else {
		// provide errors and other shit

		return $this->createErrorResponse();
	}
}
->
PHP:
public function handle(Request $request)
{
	try {
		$this->save($request);

		return $this->createRedirectResponse();
	} catch (InvalidArgumentException $e) {
		return $this->createErrorResponse();
	}
}
Причина, по которой так делать не стоит в этом конкретном случае, пожалуй заключается только в том, что во втором случае пользователю будет известен лишь факт ошибки, потому что исключения нужны программисту, а не пользователю. Ну, и валидаторы еще могут быть разными в зависимости от прав пользователя, который делал запрос.

Теперь вопрос: почему ты считаешь, что мы не можем взять и исключить проверку существования файла перед попыткой его удалить? Зачем нам интересоваться его состоянием, если это делается и так уже внутри объекта? Сколько можно повторять, что пример просто гнилой, потому что состояние может измениться после проверки и перед удалением?

Ты преподносишь вариант с file_exists + unlink как единственно верный в контексте когда файла может не быть. Я считаю лишь, что вариант с try ... catch лишь более правильный, но не единственно допустимый, простому потому что масштаб мелкий и еще и потому что это PHP: здесь нет и, возможно, никогда не будет исключений на уровне языка из unlink. Попробуй иногда принимать альтернативные решения как допустимые, может тогда тебя все бесить перестанет в чужом коде. Это ж PHP, тут приходится идти на какие-то компромиссы и выбирать меньшее зло.
 
  • Like
Реакции: WMix

AmdY

Пью пиво
Команда форума
Вот коллега наткнулся на пример хорошо характеризующий исключения. https://github.com/zendframework/zf2/blob/master/library/Zend/Mail/Headers.php#L92
Исключения применяются, когда нужно прервать поток выполнения, они осуществляют выход из скоупа и предастовляют интерфейс для трейса, чтобы программист мог вылавливать нетипичную ошибку.
 

Silentland

Новичок
Слышал, в Зенде, вообще, исключения очень грамотно используются. А почему считаете (или коллега считает), что это для того, чтобы программист мог вылавливать нетипичную ошибку? То же относится и к предыдущему посту «пользователю будет известен лишь факт ошибки, потому что исключения нужны программисту, а не пользователю».

Масса прошлых советов сводится к выводу: используй try ... catch только для исключительных ситуаций, только чтобы сообщить программисту, а для валидации нужно if ... else или что попроще, а через try ... catch валидировать — зло. ОК. Вот поймал программист ошибку и что ему делать? Заменять все try ... catch на if ... else потому что теперь же это не исключительная ситуация, он же теперь знает как ее обработать, теперь же можно написать альтернативную ветку обработки...

Видимо, у меня уже каша в голове... И пока в нее укладывается только такой алгоритм
PHP:
try {

} catch (InvalidArgumentException $e) {
    // Код валидатора
    // if ... else
    // switch ... case
}
В другом посте как раз его и использую http://phpclub.ru/talk/threads/Зачем-нужны-throw-exception.74500/#post-665743

Путаницу вносит то, что некоторые ошибки ничего не выбрасывают. Т.е. такой код не сработает
PHP:
try {
    $_FILES
} catch (Exception $e) {}
Поэтому приходится по-старинке
PHP:
if ($_FILES['error']) ...
ИМХО такие штуки как $_FILES['error'] или ф-ции для работы с БД, об ошибках которых можно узнать из mysql_error главные претенденты на эмуляцию с throw ... catch
 

Фанат

oncle terrible
Команда форума
Фанат, ты что-нибудь слышал
Ты что-нибудь слышал о принципе "Show me the code"?
Вот мой код:
PHP:
if (file_exists($file)) {
    unlink($file);
}
Покажи мне код, который ты написал бы здесь. Предположим, что пусть даже нечестное, но исключение при ошибке кидается. Покажи мне код.

Сколько можно повторять, что пример просто гнилой, потому что состояние может измениться после проверки и перед удалением?
Это, на самом деле, третий случай. Очень удобный для троллей и истеричек. Многопоточность на деле бывает очень редко, но выпячивается так, как будто это самый массовый кейс. Так что на самом деле всё наоборот - это с многопоточностью кейс гнилой. В соответствии с принципом Оккама в примере выше ты можешь его не рассматривать.
 

Фанат

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

Дело в том, что исключения очень сильно отличаются от обычных ошибок (которые худо-бедно отлавливаются еррор хендлером и могут быть им там где-нибудь внутри себя обработаны).
Отличаются тем, что у нас может быть бесконечное количество типов исключений (и - следовательно - хендлеров), и тем, что обработка делается по месту, в блоке catch.
То есть, теоретически, их область применения шире, и они могут применяться для обработки не только критических ситуаций.
Об этом и идёт спор.

К примеру, исключения http*. Они очень удобны, но назвать совершенно штатную 301 после поста критической рука не поднимается.

Ну, или спор идёт попросту вокруг определения понятия "критическая ситуация", но я бы не хотел, чтобы к этому скатывалось.
 

Фанат

oncle terrible
Команда форума
Заменять все try ... catch на if ... else
Да.
Тебе привели две причины, почему это надо сделать.
1. В случае обработки формы, исключительной ситуацией является наличие ошибок во ВСЕЙ форме, а не в одном отдельном поле. Ты НЕ должен прерывать обработку формы при наличии ошибки в одном поле. Ошибки пользователю надо отдать сразу все, а не скармливать по одной после каждой попытки.

2. Если же ты заворачиваешь в трай-кетч КАЖДУЮ проверку, т.е., по факту используешь трай-кетч в качестве тяжеловесной замены иф-елс - тут снова помянем старика Оккама: if ... else транслируются в прямо в инструкции процессора. В две инструкции. Учитывая же, сколько этих инструкций, переключений контекстов и и памяти потребуется для обработки исключения - ответ, на мой взгляд, очевиден.
Заметь, я НЕ хочу сказать, что применение исключений хоть сколько нибудь замедлит твою программу. Не замедлит. Речь о здравом смысле. О том, что гвозди не забивают микроскопом.
 

Beavis

Banned
Чтобы лучше понять в каких случаях целесообразно использовать исключения, можно почитать описания типов исключений из стандартной библиотеки:
http://php.net/manual/en/spl.exceptions.php

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

Silentland

Новичок
Многопоточность на деле бывает очень редко, но выпячивается так, как будто это самый массовый кейс
Кажется, когда есть многопоточность, то всегда существует метод блокировки (заблокировал, проверил, разблокировал), который сводит все к примитиву.

Фанат, думаю, понял ход рассуждений, наконец-то дошло. Получается в моем случае должен сказать пользователю, что он и файл пытается загрузить больше положенного и место у него закончилось, да еще и кол-во превышено. Можно сделать вывод, что throw .. catch не стоит использовать если ошибка не убивает процесс или требуется проверка на все ошибки. Тут идеальным был бы вариант использовать в блоке catch что-то типа goto $e->getLine(); для продолжения работы скрипта. Не знаю, предусмотрена ли такая функция. Хотелось бы сделать код более единообразным.
 

cDLEON

Онанист РНРСlub
Silentland
Все ваши ошибки - ошибки модели. Обычно каждую проверку в модели выносят в отдельный метод. По-этому эта не читаемая херня, которую вы предлагаете добавить в язык, там абсолютно не нужна. Другой вопрос, что можно вместо исключений использовать обычный return с "специализированным ответом". Но это будет ни чем не лучше, чем исключения. Даже хуже. Return не обязывает делать проверки результата, и в случае, если ошибка в результате проигнорирована, добавляет геморроя при отладке. Необработанный экзепшн же, выскочит на уровень выше. И, скорее всего, будет обработан чем то вроде 500 HTTP ошибки клиенту + помещён куда-нибудь в лог.
 

Вурдалак

Продвинутый новичок
Ты что-нибудь слышал о принципе "Show me the code"?
Не прикидывайся дурачком:
PHP:
try {
	unlink($file); 
} catch (ErrorException $e) { }
Это, на самом деле, третий случай. Очень удобный для троллей и истеричек. Многопоточность на деле бывает очень редко, но выпячивается так, как будто это самый массовый кейс. Так что на самом деле всё наоборот - это с многопоточностью кейс гнилой. В соответствии с принципом Оккама в примере выше ты можешь его не рассматривать.
Клиника.
 
  • Like
Реакции: WMix

Вурдалак

Продвинутый новичок
К примеру, исключения http*. Они очень удобны, но назвать совершенно штатную 301 после поста критической рука не поднимается.
Здесь как раз вполне подходит return + какой-то особенный response, тогда не нужно будет делать каких-то непонятных различий между 301, 404 и 200. Вот как раз где исключения я использовать не очень люблю.
 

Фанат

oncle terrible
Команда форума
Все ваши ошибки - ошибки модели. Обычно каждую проверку в модели выносят в отдельный метод. По-этому эта не читаемая херня, которую вы предлагаете добавить в язык, там абсолютно не нужна. Другой вопрос, что можно вместо исключений использовать обычный return с "специализированным ответом". Но это будет ни чем не лучше, чем исключения. Даже хуже. Return не обязывает делать проверки результата, и в случае, если ошибка в результате проигнорирована, добавляет геморроя при отладке. Необработанный экзепшн же, выскочит на уровень выше. И, скорее всего, будет обработан чем то вроде 500 HTTP ошибки клиенту + помещён куда-нибудь в лог.
cDLEON, я не пойму, ты за белых или за красных? Я даже не нашел ключевой фразы, чтобы процитировать.
Ты считаешь, что исключения лучше? при этом на каждое поле формы - свой тип исключения?
 

Фанат

oncle terrible
Команда форума
Не прикидывайся дурачком:
Зачем так сложно?
Можно было просто написать
PHP:
@unlink($file);
Пустой кетч - та же собака, только кода больше.
И точно так же, как и собака, пропустит ошибку с правами доступа.
Ты написал глупость.
Напиши нормальный код, который реально написал бы в реальной программе, а не на форуме, тупо потроллить.
тогда и поговорим.
 

Вурдалак

Продвинутый новичок
Зачем так сложно?
Можно было просто написать
PHP:
@unlink($file);
PHP:
<?php

function exception_error_handler($errno, $errstr, $errfile, $errline ) {
	throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler('exception_error_handler');

try {
	unlink('XXX');
} catch (ErrorException $e) {

}

@unlink('YYY');
xxx@xxx:/xxx/www$ php exception.php
PHP Fatal error: Uncaught exception 'ErrorException' with message 'unlink(YYY): No such file or directory' in /xxx/www/exception.php:14
Stack trace:
#0 [internal function]: exception_error_handler(2, 'unlink(YYY): No...', '/xxx/www/...', 14, Array)
#1 /xxx/www/exception.php(14): unlink('YYY')
#2 {main}
thrown in /xxx/www/exception.php on line 14
А чем твой код отличается от собаки? Ничем.

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

У тебя нет никаких аргументов. Весь код, который ты никогда не видел в жизни для тебя нереален. Не будь клоуном, дружок.
 

AmdY

Пью пиво
Команда форума
Silentland Слышал, в Зенде, вообще, исключения очень грамотно используются.
Как видно из примера не очень то и грамотно, пришлось целый метод копипастить из-за этой херни. попробуй код этого класса переписать без исключений и уловишь суть отличий.
 

Фанат

oncle terrible
Команда форума
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
нет-нет, ты опять не понял.
про хендлер я тебе сразу написал - можешь считать, что он есть,
Предположим, что пусть даже нечестное, но исключение при ошибке кидается.
Речь не про него.

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

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

флоппик

promotor fidei
Команда форума
Партнер клуба
Вурдалак, забей. Клиент не адекватен уже давно, и не слышит никого, кроме себя.
 
Сверху