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

Вурдалак

Продвинутый новичок
newARTix
Тебе никто не гарантирует, что в момент между проверкой на доступность и открытием, файл, например, не удалят.
 

iceman

говнокодер
где то можно и не обрабатывать если некорректные данные пришли от пользователя и явно ему влепить - ошибку, в других, можно поставить дефолтные, либо взять с другого источника значения для продолжения работы другого блока кода

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

sverel

Новичок
iceman
> исключения не для перехвата ошибки, а для создания ЛОГИКИ программы с учетом ошибки

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

> это явная ошибка программиста
Я для простоты понимания так пишу. Естественно, реальная программа сложнее и в неё будет addElement($elementType). Если уш так интересно, то $elementType - берётся из БД, ведь админ сам может создавать сущности (как в нормальной ЦМС), а типы элементов зависят от редакции ЦМС и подключенных модулей. Таким образом админ может создать, например раздел "новости" и сказать, что одно из полей там является datePicker-ом, а потом отключить модуль "Расширенные элементы форм" и получить багу при добавлении/редактировании новости.

-~{}~ 09.06.10 13:20:

newARTix
К сожалению, баги бывают всегда. Баги есть даже во FreeBSD, я уж не говорю про макОС, Убунту и тем более виндовс :) И программист о них должен узнать самым первым и исправить. Для этого вызывается НОТИС/ВАРНИНГ, а myErrorHandler отсылает мне мыло.

Кроме того, нотисы могут возникать не только по вине кривой программы. Например, в своих довольно сильно нагруженных проектах я самый первый узнавал о том что:
1. Упал MySQL,
2. Закончилось место на диске,
3. Скрипту не хватает оперативы.

Тут же звонил сис.админу и все баги устранялись в течении 15 минут. Заказчик, даже не узнавал о сбое так же как большинство постоянных посетителей.
 

iceman

говнокодер
> addElement($elementType)
ну и что мешает тебе при рендеринге (я думаю это будет происходить в цикле) обработать данное исключение и вставить обычный input с текстом - данный элемент отсутствует... НО конечно, можно оставить как ошибку, это тебе выбирать, изминение значений "системной-вспомогательной" таблицы - я бы считал за ошибку программы.

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

sverel

Новичок
iceman
> например, в мастере создания заявки,
Это логика программы. Получается, что логика у Вас раскинута в нескольких местах. По моему, это очень плохо - кол-во кода не уменьшается, зато читабельность значительно ухудшается. Через пол годика не разберёшся откуда что берётся. Проще написать несколько дополнительных if так же как Вы здесь по русски написал описывая задачу: "если .. то ... а если ... тогда ... ну а если и это не так, то .... "
 

iceman

говнокодер
ну в pl/sql есть тип исключения - others - с ним и трассеровкой, я всегда узнаю где ошибка... в пхп я х3 ...
 

newARTix

Новичок
Вурдалак
sverel
да я ж не против. Я и не говорю что их не бывает. Я говорю что логику на них не нужно делать. И юзеру показывать.
Вот именно что *ошибки* предназначены для пинка программисту, а не логики приложения. У меня тоже на мыло высылается, не открыли америку :)
 

sverel

Новичок
> исключения не для перехвата ошибки, а для создания ЛОГИКИ программы с учетом ошибки

Вся логика программы описана внутри пакета QuickForm. Для меня это обычное сообщение об ошибке.

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

И что же Вам не нравится: если класс генерит ошибку, то я сам решаю критичная она или нет. Стоит ли её выводить или нет. Я сам это всё решаю в своём обработчике.
А вот если класс выплюнул throw, а у меня нет отдельного блока try/catch, то я, не смогу на неё забить и продолжить выполнять тот блок try внутри которого был throw. Т.е. я мало что тут решаю.

-~{}~ 09.06.10 13:37:

newARTix
Да согласен, поэтому вся логика у меня в одном месте, и myErrorHandler - я никогда не дописываю. Мой пост относился к статье из второго поста в которой предлагалось повышать стабильность, за счет "исправления ошибок на лету". Именно ОШИБОК. И предлагалось для этого использовать try/catch. Для любителей таких конструкций я и написал про обработку исключений внутри myErrorHandler :)
 

iceman

говнокодер
sverel
приведи мне такой случай, когда не сможешь обработать...

PHP:
try {
   $form = new QuickForm2();
   $form->addElement('myDate'); // не существующий тип элемента
   $form->addElement('submit');
   $form->display();
} catch(...) { ... }
но ты говоришь что элементы динамические

то код будет у тебя таким
PHP:
$form = new QuickForm2();
цикл {
  try {
    $form->addElement($elType);
  } catche(...) {
    $form->addElement('input');
  }
}
$form->addElement('submit');
$form->display();
может я что-то не догоняю?
 

AmdY

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

Вурдалак

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

iceman

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

Исключение будет ошибкой - если она не обработанна.
 

tenshi

Новичок
Автор оригинала: sverel
Да. Но try ставится в самом начале - в точке входа в программу. А в самом конце стоит catch которые собирает все возможные исключения.

В вышеуказанной статье рассказывается про бОльшую стабильность за счет того что некоторые ошибки можно "вылечить". Например, я подключаю PEAR-класс QuickForm.
PHP:
try {
   $form = new QuickForm2();
   $form->addElement('myDate'); // не существующий тип элемента
   $form->addElement('submit');
   $form->display();
} catch(...) { ... }
Здесь я пытаюсь вставить элемент которого не суествует 'myDate'. При этом QuickForm выплюнет throw new HTML_QuickForm2_NotFoundException();
Вообще-то эту ошибку можно вылечить, заменив навороченный date-picker на обычный инпут - это не так юзабельно, но зато стабильность программы будет высокой. Однако, механизм try/catch не позволяет продолжить выполнение программы дальше и субмит не будет добавлен. И даже $form->display() не будет выполнен.
Так как же их лечить? Или каждую строку своего кода вставлять в try/catch?
PHP:
try {
  $form = new QuickForm();
} catch (...) {...}
try {
  $form->addElement('myDate');
} catch (...) {...}
try {
  $form->addElement('submit');
} catch (...) {...}
try {
  $form->display();
} catch (...) {...}

Бред.
PHP:
   $form = new RecoverableQuickForm2();
   $form->addElement('myDate'); // не существующий тип элемента
   $form->addElement('submit');
   $form->display();

class RecoverableQuickForm2 extends QuickForm2 {
    function addElement( $type ){
        try {
            parent::addElement( $type );
        } catch( $e ){
            parent::addElement( 'text' );
        }
    }
}
 

sverel

Новичок
iceman, tenshi
это велосипед. Код должен быть таким:
PHP:
цикл {
  if ($form->isRegisteredType($elType)) {
    $form->addElement($elType);
  } else {
    $form->addElement('input');
  }
}
Читабельнее и понятнее. А реально дело обстоит так: когда подключаешь чужой класс плюющийся исключениями, то они используются мной ТОЛЬКО для уведомления об ошибках. Т.е. фактически, это и есть уведомления содержащие в себе: сообщение, трейс, файл, строку и т.д...

Насчет разнесения логики в своей программе:
Мне самому, что бы реализовать логику построенную на Exception-ах, придётся для каждой исключительной ситуации мастерить отдельный класс myException вместо простого if/else. Этот велосипед сложнее, чем if/else. В Вашем примере с циклическим выводом quickForm для реализации такой логики, ведь потребовался класс ExceptionNotFoundElement. Причем, этот класс пустой! Но для него создан отдельный файлик. Обезъянья работа, блин. Проще if/else-ов понатыкать. Разве нет?

P.S.> надеюсь, мы ушли от идеи повышать стабильность за счет обработки исключений внутри catch? Подключение к запасному серверу должно быть в программе и должно работать на while.
 

tenshi

Новичок
это велосипед. Код должен быть таким:
цикл {
if ($form->isRegisteredType($elType)) {
$form->addElement($elType);
} else {
$form->addElement('input');
}
}
а если это не тип, а пользователь лежащий в базе? будешь делать два запроса?
 

sverel

Новичок
Тогда будет выплюнуто другой Exception-класс и Вам потребуется писать для него отдельный catch. Так же как мне придётся писать отдельный elseif. Но в моём подходе не придётся руками создавать ещё один класс-Exception.
 

tenshi

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

iceman

говнокодер
sverel
> Читабельнее и понятнее
это конкретно в твоем случае
 

Вурдалак

Продвинутый новичок
Автор оригинала: AmdY
ошибка и исключение - это две разные вещи. исключения генерируются программистом и их можно обработать. ошибки могут возникать по независящим от разработчика причинам и программа может не знать как их обрабатывать и просто выводим "боже мой, всё сломалось, разработчики курите лог".
— по какому условию ты будешь выводить «боже мой, всё сломалось, разработчики курите лог»?
 

AmdY

Пью пиво
Команда форума
Вурдалак
по такому, как пишу require вместо include и выволнение дальше не возможно: недоступен файл, отвалился сервер бд.......
 
Сверху