Как посмотреть дампы bsod windows 10

Где вы перехватываете исключения?

Тренинги, которые я организую

Представьте себе приложение по шаблону проектирования MVC или что-то похожее, написанное например на Nette, в котором мы хотим вывести подборку статей где-нибудь в боковом меню. Если этот выбор не загружается, это не должно препятствовать отображению основного содержимого страницы. Модель может выглядеть так:

Шаблон бокового меню:

Исходный код доступен на GitHub.

Как видите, в модели используется Dibi, который выдает исключение DibiException в случае ошибки. И мне интересно, как вы справитесь с этим исключением. Будете ли вы лечить это уже в модели, в ведущем или, может быть, позволите ему подняться на самый высокий уровень? И если вы еще не зафиксировали это в модели, используете ли вы комментарий к документации @throws? И не было бы странно, если бы докладчик узнал о реализации модели через тип исключения? Или, может быть, перевести его на другое исключение в модели? И как на самом деле будет выглядеть блок catch?

Также обратите внимание, что в шаблоне есть ссылка на Article:bests — это будет страница, где основным содержанием будет просто список лучших статей, и поэтому желательно, чтобы он заканчивался на пятьсот, если список не нагрузка. И печатать информацию о пустом списке, если еще нет статей, отмеченных как подборка. Мне кажется логичным, что эта страница внутри вызывает тот же метод модели Article::getBests .

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

Обсуждение

Снайпер:

Перехватывать исключение dibi прямо в модели и транслировать его в какое-либо другое, например, ArticleException, которое затем будет обрабатываться в контроллере. @throws само собой разумеется.

В качестве альтернативы можно вернуть пустой объект данных из модели в контроллер, что зависит от конкретных требований.

Якуб Врана :

Спасибо за ответ. Не могли бы вы также написать код, чтобы мы могли поговорить конкретно?

Требования четко сформулированы. Итак, вы возвращаете пустой объект данных или создаете исключение? А как вы поступаете с пустым объектом данных в действии Article:bests? Там надо различать два состояния — произошла ошибка или еще ничего не отмечено.

Снайпер:

Я не вижу Primo в Nette, но в Zend это было бы примерно так:

Модель Db_Article
класс Db_Article расширяет Zend_Db_Table_Abstract
<

/**
* Возвращает список ЛУЧШИХ статей
*
* @return Zend_Db_Table_Rowset_Abstractстраницы Статья: лучшая? На том желательно, чтобы он заканчивался на пятьсот, если возникает ошибка.

Снайпер:

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

сама статья:лучшая страница была бы действием контроллера, на что я бы отреагировал в ней:

класс ArticleController расширяет Zend_Controller_Action
<

публичная функция bestAction()
<
$dbModel = new Db_Article ();
$это -> вид -> лучшие = $dbModel -> выбрать лучший(); // если я ничего не найду, я просто продам пустое поле представлению
if (empty( $this —> view —> bests )) <
$this —> _ответ -> установить код (505);
// или установить несколько голосов
>
>

Якуб Врана :

Хорошо, спасибо за объяснение.

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

Мартин:

Якуб Врана :

Спасибо за ответ. Не могли бы вы также написать, какой код вы будете использовать для регистрации ошибки?

Что, если бы было семь необязательных компонентов? Тогда каждый из них будет иметь этот конверт вокруг себя?

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

Мартин:

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

абстрактный класс UnnecessaryComponent <
функция renderDetail() <
try <
renderData();
> catch ( Exception $e ) <
//логировать ошибку
>
>

абстрактная функция renderData();
>
?>
что касается регистрации,
::processException ( $e );
?>
должно быть достаточно.

что касается критичности и вероятности, я, вероятно, неправильно понял часть предложения: «какая ошибка должна иметь вероятность, чтобы ее не стоило рассматривать как фатальную».

Якуб Врана :

Чего именно UnnecessaryComponent может быть предком? А что будет внутри renderData()?

Недостаток ведения журнала с помощью Debug::processException() состоит в том, что в процессе разработки он ведет себя иначе, чем в рабочей среде, поэтому поведение ошибок трудно смоделировать. В продакшене всегда заходят и продолжают, в разработке либо продолжают молча, либо переигрывают весь экран (в зависимости от второго параметра).

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

Мартин:

должен быть предком BestArticlesComponent. только семь компонентов, которые я покажу вам некритические части на странице.

renderData компонента BestArticlesComponent может выглядеть примерно так:
public function renderData() <
$this -> шаблон —> bestArticles = Статья :: findBests ();
>
?>

Я думаю, что не проблема установить класс Debug так, чтобы его также можно было рассматривать локально как производственную среду. в любом случае, у меня не так много опыта в этом, так что я бы не корил себя за это.

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

Якуб Врана :

Как вы вписываете компоненты в текущий презентатор или в шаблон? Я правильно понимаю, что для загрузки данных для одного компонента (теперь одной строки) я буду определять один класс?

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

Читайте также:  Как восстановить кэш windows 10

Мартин:

Я подогнал компонент следующим образом (из .phtml template-y):
< виджет Лучшие статьи >
?>
и да, я легко определяю один класс — если я хочу использовать данную часть страницы где-то еще, у меня есть очень простое повторное использование.

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

Якуб Врана :

Я еще многое здесь упускаю — недостаточно создать класс и написать в шаблоне. Компонент также должен иметь возможность отображать себя, он должен загружать шаблон и так далее. Не могли бы вы добавить код в полный пример, чтобы я мог получить общее представление?

Ошибка разобрана, но последствия неприятны: «Полдня мы не получали заказов, потому что не удалось загрузить самые продаваемые товары.»

Мартин:

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

если игнорировать ошибки, может быть точно такая же проблема: полдня мы не получили ни одного заказа, потому что у нас было что-то вроде этого для продукта:
= getAvailableCount ( $product );
if ($count > 0) <
$allowBuying = true;
> иначе <
$allowBuying = false ;
>
?>
без разницы. то есть к тому, что об этой ошибке точно не сообщат как о критической. и именно поэтому это будет обсуждаться намного позже.

Якуб Врана :

Не могли бы вы написать весь класс? То есть включая метод render() и возможную регистрацию этого класса.

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

Мартин:

фффф, но это ты 😉 даже если текстовое поле в качестве редактора не очень 🙂
компонент BestArticlesComponent.php :

класс BestArticlesComponent расширяет UnnecessaryComponent <
общедоступную функцию renderData() <
$this -> шаблон —> bestArticles = Статья :: findBests ();
>
>
?>

шаблон BestArticlesComponent.phtml:

h3 > href=» » > Подборка статей и > h3 >
ул >

если > a href = » id >» > < $статья ->название > и > если >

ul >

?>

и все, вы просто включаете его в любой шаблон, используя:
< виджет Лучшие статьи >
?>

коды шаблонов не PHP, но я не знаю, как сделать здесь не-php код.

что касается второй части, то важность ошибки для меня довольно абстрактное понятие. одна и та же ошибка может быть «важной» по-разному в разных местах. Нужно ли придавать значимость ошибке? соответственно Разве не важно придавать им важность с точки зрения использования или контекста?

Якуб Врана :

Но это даже не половина кода. Наследование от Control отсутствует, метод должен называться только render(), отсутствует настройка файла шаблона, отсутствует его рендеринг, отсутствует метод createComponentBestArticles. Кроме того, в следует писать строчную букву.

Что касается серьезности ошибки, даКонечно. Например. метод Article::findBests() вызывает серьезную ошибку, если мы вызываем его на странице, предназначенной для перечисления подборки статей, и менее серьезную ошибку, если мы вызываем его только из бокового меню.

Мартин:

Якуб Врана :

Мартин:

Мартин Грушка:

v6ak:

Мартин:

v6ak:

Мартин:

v6ak:

Мартин:

v6ak:

Франта:

v6ak:

Итак, я решил взглянуть на макросы и реализовать что-то подобное, хотя я сделал немного более приземленным по сравнению с первоначальной идеей. А пока возьмем его (BasePresenter) скорее как пример, какую-то наспех состряпанную концепцию.

Я также добавил пару скриптов для имитации ошибки ссылки, настроил ленивые ссылки (чтобы ошибка отображалась в нужном месте) и добавил балластный текст до и после этой части, чтобы показать, что ошибка в этой части не поставит под угрозу рендеринг остальных. Только в режиме отладки вся страница покрывается BSOD Nette при возникновении ошибки.

Якуб Врана :

Том:

Якуб Врана :

Том:

Попробую, хотя бы примерно 🙂

Ведущий:
попробуйте <
$this -> шаблон —> bestArticles = Article :: findBests ();
> catch ( NoArticleException $e ) <
$this -> шаблон —> bestArticlesError = true ;
>
?>

И шаблон что-то вроде:

ЕСЛИ $bestArticlesError
произошла ошибка, попробуйте позже
ИНАЧЕ, ЕСЛИ $bestArticles
список
ИНАЧЕ
подходящие статьи не найдены

Якуб Врана :

Том:

Якуб Врана :

Том:

Якуб Врана :

v6ak:

Модель:
/** @returns Массив со статьями или null в случае ошибки */
класс Article <
статическая функция findBests() <
try <
return dibi :: query («SELECT * FROM [article] WHERE [best]» )-> получить все();
> catch( Exception $e ) <
// Возможно, какая-то запись журнала
возвращает null ;
>
>
>
?>

Ведущий: оставить как есть в статье

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

Якуб Врана :

Спасибо. Не могли бы вы указать, как будет выглядеть вход в систему? Не знаю, почему все это пропускают.

Как бы выглядел ведущий для события Article:bests? В случае ошибки в базе он должен получить пятьсот (потому что это его основная деятельность).

Якуб Врана :

Юкр:

Здравствуйте. Лично мне не нравится ни один из предложенных вариантов, так как я придерживаюсь мнения, что исключение вообще не должно попадать на уровень представления с нижних уровней (ни BLL, ни адаптеров). Только тот, который выбрасывается уровнем представления (но я не могу придумать такой компонент в PHP). Я предпочитаю решение, в котором исключение перехватывается на уровне BLL, с возвратом простого объекта, информирующего о (не)успехе действия, а коллекция заполняется через параметр ссылки. Я только время от времени использую PHP (в то время ASP.NET WebForms), поэтому, надеюсь, мой пример будет понятен. Если нет, извините 😉

//возвращаем объект
класс Результат
<
public $isSuccessful ;
общественное сообщение $;
// или другая информация, которую мы хотим передать на уровень представления
>

// слой BLL
класс Foo
<
статическая функция findBests (& $bestArray )
<
$result = new Result ();
$результат -> isSuccessful = истина ;

попробуйте
<
$bestArray = dibi :: query («SELECT * FROM [article] WHERE [best]» )-> получить все(); // Я предполагаю, что он возвращает массив
>
catch( Exception $e )
<
$result -> успешно = ложь;
$результат -> сообщение = $е-> получитьсообщение();

// Я обычно также регистрируюсь здесь
>

вернуть $результат;
>
>
?>

Надеюсь, мои намерения читабельны. Я извиняюсь перед знатоками PHP за путаницу. 😉

Мартин:

Юкр:

Объявление 1) Как я уже писал в определении результата, это полностью зависит от вас, что вы отправляете для информации. Лично я использую Message как еще один объект, который содержит больше информации (текст, трассировка и т. д.), которую нужно показать на уровне представления в случае ошибки. Это был такой быстрый выигрыш, что можно было написать «что-то пошло не так» и написать сообщение об ошибке из Exception. В конце концов, вы можете отправить все исключение как свойство объекта Result, это зависит от вас.

Объявление 2) Да, именно так. Не вижу в этом проблемы — наоборот. 🙂

Якуб Врана :

Юкр:

Извините, Якуб, я пока мало играю с MVC (ни в PHP, ни в ASP.NET), но я бы сказал, что использование может быть следующим (ну ладно, это быстрое решение на случай, если вам не нужно дальше работать в презентере с объектом Result — например, у вас нет дальнейших действий в зависимости от успешной загрузки bestArticles.

Читайте также:  Как сохранить свои файлы при переустановке windows 10

класс ArticlePresenter <
функция renderDetail ( $id ) <
// сюда будет загружаться основное содержимое страницы — деталь статьи
// кроме того, мы также загрузим выборку статьи для бокового меню
$ это -> шаблон —> лучшие статьи = массив();
$это -> шаблон —> результат = Статья :: findBests ($this->template->bestArticles );

>
>
?>

Я бы лично решил шаблон так:

Подборка статей

Я всегда вхожу в BLL (если вам нужна модель) после обработки ошибки в блоке catch. Там это сугубо индивидуально и зависит от того, хотите ли вы войти в БД/файловую систему/почту или используете для этого другой инструмент.

Якуб Врана :

Спасибо за описание, кромеимя переменной $result ясно (такая переменная, вероятно, потребуется для каждого компонента).

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

Юкр:

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

Прошу прощения за неточность, конечно, было бы понятнее поставить вместо результата статьиBestResult, особенно если этот принцип используется во всех вызовах BLL/model.

Мартин:

холоднее:

Юкр:

Юкр:

1) Исключительно из принципа многоуровневой разработки приложений. Почему бы просто не сделать все это на одном слое?
2) Одно дело перехватить исключение, другое — отправить его в чисто информационном объекте. Кроме того, дело в том, что в случае ошибки мы обычно хотим инициировать другое действие, не относящееся к уровню представления: вход в систему, отправка электронного письма и т. д. Если вы поймали это только на уровне представления, вы все это пришлось бы делать самому, а самое главное, вы бы делали это Х раз снова и снова. (один и тот же метод вы будете использовать не один раз) Так вы просто вызываете метод, а с точки зрения уровня представления вас интересует только, получилось нормально или нет и что он сказал о себе, когда произошла ошибка.

Мартин:

1, какое отношение распространение ошибок имеет к нескольким архитектурам? и особенно если вы все равно отправляете эти исключения?

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

3, а как бы вы написали метод getBestOrRandom, который бы вытаскивал лучшие статьи и если их не меньше десяти, то случайным образом выбирал бы десять? схемы достаточно, и я предполагаю, что вы будете использовать там методы getBest?

Юкр:

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

1) Теперь я сожалею о том, что отправил все Исключение, потому что вы держитесь за него изо всех сил. Это была просто моя лень. 🙂 Не стесняйтесь отправлять только несколько строк информации выше (где была ошибка и некоторая болтовня) и генерировать Exception ниже как таковой. К вашему сведению — проблема не в распространении ошибок, а в их обработке в зависимости от места возникновения. Это не догма, это, безусловно, вопрос личного мнения, но лично я довольно строго отношусь к уровню представления того, за что она должна отвечать.

2) Я не пользуюсь Нетте, поэтому не хотел бы идти по тонкому льду. 😉 Я имел в виду x раз использования именно в том случае, если вы обрабатываете ошибки с бизнес-уровня только на уровне представления. Если бы вы использовали бизнес-метод в нескольких местах, вам пришлось бы повторить обработку снова (т. е. try-catch на уровне представления).

3) Очень просто (это набросок):

общедоступная статическая функция getBestOrRandom (& $bests )
<
$result = new Result ();
$результат -> isSuccessful = истина ;

попробуйте
<
$bests = array();
$resBest = self :: getBest ( $bests );

if( $resBest —> isSuccessful )
<
if( count ( $bests ) 10 )
<
// дополнительная информация из случайного
$random = массив ();
$resRand = self :: getRandom ( $random );

if( $resRand -> isSuccessful )
<
//объединить $random и $bests
>
else
<
// не удалось завершить
// опять же, это зависит от понимания метода // если да,затем:
$результат -> успешно = ложь;
// любая дополнительная информация согласно определению Результат
>
>
>
else
<
// тут только от вас зависит, является ли это ошибкой всего метода
// или мы попробуем заполнить те 10 из случайных
>

>
catch( Exception $ex )
<
$result -> успешно = ложь;
// любая дополнительная информация согласно определению Результата
>

вернуть $result ;
>
?>

Сознаюсь без пыток — в очень сложной композиции может показаться, что кода много, но если вы используете другие методы того же объекта (возвращающие Result), у вас есть прекрасная возможность решить, когда и при каких обстоятельствах какая ошибка является ошибкой всех методов и когда попытаться загрузить данные по-другому (см. ваш пример с OR random)

Мартин:

именно за эти три 🙂
не проще ли написать:
.

общедоступная статическая функция getBestOrRandom (& $bests )
<
$best = self :: getBest ();
$count = количество ( $best );
if ($count 10) <
$random = getRandom (10 — $count);
вернуть слияние ( $best , $random );
> иначе <
вернуть $best ;
>
>
?>
?

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

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

Юкр:

Я нигде не писал, что код короткий в случае сворачивания. Но вы не теряете возможности самостоятельно определять серьезность ошибок. Если запечете (см. ваш пример), заверните все в try-catch и ничего не говорите. 😉 Я все еще не могу согласиться с тем, что вы должны фиксировать это выше, но мы, вероятно, не согласны с этим 😉

Что касается параметра, то в C#, где я его использую, параметр определяется как «out» (http://msdn.microsoft.com/en-us/library/t3c….71%29.aspx) с тот факт, что это всегда объект (я использовал поле только для этого примера PHP), который все равно переинициализируется перед использованием (нас не интересует его старое значение из логики дела, потому что мы будем заполнять его в БЛЛ). В PHP я также использую исключительно объект в качестве параметра для заполнения — обычно это коллекция.

Читайте также:  Как зайти под root windows

Мартин:

ad «Я нигде не писал, что код короткий на случай сворачивания.» — вы так не говорите, а я говорю, что это ужасно долго и необъяснимо 😉

ad «Но вы не теряете возможность самостоятельно определять серьезность ошибок. Если вы запечете это (см. ваш пример), оберните все это в try-catch и ничего не говорите. ;)» — я не сделал Я не понимаю этого, вы можете это объяснить? где вы хотите определить серьезность ошибок? и как мне обернуть ваш getBest() в try-catch, так как большинство исключений перехватываются внутри, правильно?

Юкр:

Это уже шоу для двоих, так что мы должны как-то его закончить. 😉 Под try-catch я имел в виду, что если бы бизнес-уровень не возвращал Result (то есть мой метод не использовался бы) и вам было все равно, где произошла ошибка (будь то при поиске Best или Random), можно завернуть и не решать в какой части произошла ошибка. Поскольку ваш пример возвращает не результат, а прямой массив,такое решение, вероятно, может быть использовано. Либо можно оборачивать каждый вызов и тем самым различать важность возможной ошибки в catch, но глупость в том, что уже нельзя вернуться из catch.

Я думаю, что мы уже излишне анализируем его, и первоначальный смысл теряется. Итак, вернемся к корню всей статьи: лично я бы вылавливал ошибки из слоя BLL и Adapter исключительно на слое BLL или самое позднее на последнем слое перед слоем представления, но точно не на нем. И я все время думаю об этом споре.

Жена все равно от компа меня отталкивает, спасибо за очень интересную и полезную дискуссию — всегда рад, есть над чем подумать. Желаем приятно провести время.

Лемруш:

холоднее:

С другой стороны, каждая операция может легко генерировать собственное исключение (Exception_Db_Cache, Exception_Db_Query и т. д.) и перехватывать нужное мне исключение на более высоких уровнях.

Эти исключения могут (и я думаю, должны) иметь общего предка, чтобы их можно было перехватить одним уловом.

v6ak:

Михал Приныч:

Якуб Врана :

Михал Приныч:

Юкр:

холоднее:

Да, исключения, это тема.

Я был бы рад, если бы это вылилось в статью с каким-то выводом 🙂

Я сам не использую диби. Я ловлю исключение в своих приложениях на уровне ArticlePresenter (как предложил Мартин), когда я не привязан к DIBI.

Однако исключения DIBI необходимо преобразовать в собственные исключения — например, в переопределении метода query(). Я также могу свободно решить, поймать ли исключение (и, возможно, зарегистрировать его, что может быть методом log() самого исключения) или позволить ему всплыть — и тогда пользователь получит упомянутое сообщение «мы облажались» и в то же время я автоматически зарегистрирую его.

Я также хотел бы знать, с БД, какие все типы исключений считаются релевантными,то есть с какой степенью детализации вы работаете. Если вам достаточно Exception_Database или у вас есть Exception_Database_Query, Exception_Database_Select, Exception_Database_Update .

Якуб Врана :

холоднее:

Якуб Врана :

Якуб Врана :

Джейкоб:

Якуб Врана :

Если бы был метод, который обычно возвращает массив, возвращает пустой массив, когда данные не найдены, генерирует предупреждение и возвращает false в случае ошибки, то мы бы закончили с созданием компонента для боковое меню — узнавали бы о любых ошибках с помощью стандартного механизма PHP, не надоедали бы этим пользователю, выполняли бы задание на букву.

На отдельной странице мы генерировали бы пятьсот при возврате false.

В отличие от исключений я также вижу пару недостатков:

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

Якуб Врана :

Ондржей Миртес:

Я не знаю, повторяю ли я уже сделанное предложение, я только просмотрел 60 сообщений.

Распределение ответственности понятно с точки зрения MVC — модели все равно, кто будет звонить и будут ли это критические данные для этого человека или нет. Таким образом, модель должна генерировать исключение в случае сбоя, и программист должен решить, позволить ли всплыть DibiException или преобразовать его в более абстрактное BestArticlesException.

публичная функция getBestArticles()
<
try <
return dibi ::ВыбратьВсе(‘.’);
> catch ( DibiException $e ) <
throw new BestArticlesException (‘Не удалось получить лучшие статьи.);
>
>

>
?>

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

класс ArticlePresenter расширяет BasePresenter
<

публичная функция renderDetail ( $id )
<
$this -> шаблон —> article = ArticleModel :: getArticle ( $id );

попробуйте <
$this -> шаблон —> лучшие статьи = модель статьи :: getBestArticles ();
> catch ( BestArticlesException $e ) <
$this -> шаблон —> лучшие статьи = массив();
>

>
?>

Шаблон просто проверяет количество статей в поле. Если он пуст, я могу скрыть весь блок, и пользователю не нужно будет видеть раздражающее сообщение «лучшие статьи не найдены».

0 > //пустой тоже можно использовать, но он не работает с более сложными коллекциями
h3 > Популярные статьи h3 >
ул >

если > a href = » id >» > < $статья ->название > и > если >

ul >

?>

Также по поводу разной серьезности исключений — в рамках KISS (http://jdem.cz/gx7d9) я бы не стал усложнять, чем нужно, и делить исключения на те, на которые я рассчитываю ( BestArticlesException) и те, на которые я не рассчитываю (обычно низкоуровневое исключение, всплывающее во всех слоях и указывающее на какие-то большие проблемы). Я бы регистрировал такие исключения с помощью какого-то единого механизма (Nette\Debug) ипоказал пользователю пятьсот.

Например в Doctrine 2 я могу запросить один результат в запросе DQL — getSingleResult(). Правильная и совсем не странная ситуация заключается в том, что запрошенный мной результат не существует, и поэтому я получаю исключение NoResultException (кто-то может ввести несуществующий идентификатор в URL). Я должен учитывать эту ситуацию в любом случае, перехватывать NoResultException и как-то определять это состояние.

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

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

Поделиться с друзьями
ОС советы