Где я должен обрабатывать исключения, в BLL, DAL или PL?
Какое место лучше всего подходит для обработки исключений ? BLL, DAL или PL ?
Должен ли я разрешить методам в DAL и BLL выбрасывать исключения вверх по цепочке и позволять PL обрабатывать их? или я должен справиться с ними в BLL ?
Например
Если у меня есть метод в моем DAL, который выдает "ExecuteNonQuery" и обновляет некоторые записи, и по одной или нескольким причинам, затронуты 0 строк. Теперь, как я должен сообщить своему PL, что произошло ли исключение или действительно не было никаких строк соответствует условию. Должен ли я использовать "try catch" в моем PL-коде и сообщить ему об исключении, или я должен обрабатывать исключение в DAL и возвращать какой-то специальный код, например (-1), чтобы позволить PL различать (исключение) и (нет строк, соответствующих условию, т. е. нулевые строки затронуты) ?
7 ответов:
Нет смысла допускать исключение, которое выбрасывается в пузыре DAL до PL - как пользователь должен реагировать, если соединение с базой данных не может быть установлено?
Перехватывать и обрабатывать исключения рано, если Вы можете обрабатывать их. Не стоит просто проглатывать их, не выдавая подсказку или лог-сообщение - это приведет к серьезным трудностям и ошибкам, которые трудно отследить.
Это огромная тема с множеством ненужных споров (люди с громкими голосами дают плохую информацию!) Если вы готовы иметь дело с этим, следуйте совету s1mm0t, это в основном приемлемо.
Однако, если вы хотите получить односложный ответ, Поместите их в PL. серьезно. Если вам это сойдет с рук, поместите обработку ошибок в глобальный обработчик исключений (все ошибки должны регистрироваться и давать код для поиска журнала в производственной среде по соображениям безопасности (особенно если веб), но дайте полную информацию назад во время разработки по соображениям скорости).
править: (уточнение) вы должны иметь дело с некоторыми ошибками везде - но это не является нормой "каждой функции". Большую часть времени пусть они всплывают до PL и обрабатывают глобальную ошибку .NET с помощью вашего собственного кода: регистрируйте полный стек вызовов оттуда через общую процедуру, доступную со всех 3-х уровней через обработчики событий (см. редактирование внизу сообщения). Это означает, что вы будете не попробовать / поймать посыпали через все ваши код; просто разделы, которые вы ожидаете и ошибка и может обрабатывать его прямо там, или, некритические разделы, с помощью которых вы регистрируете ошибку и информируете пользователя о недоступной функциональности (это еще более редко и для сверхнадежных/критических программ)
Кроме того, при работе с элементами с ограниченными ресурсами я часто использую ключевое слово using или try/finally/end try без catch. для многопоточных флагов блокировки / мьютекса / предотвращения повторного входа / и т. д. вам также нужно попробовать / окончательно во всех случаях так ваша программа все еще работает (особенно статусные приложения).
Если вы используете исключения неправильно (например, чтобы иметь дело с не-ошибками, когда вы должны использовать оператор IF или проверять его, то операция iffy будет работать, прежде чем вы попытаетесь это сделать), эта философия развалится еще больше.
Примечание, в толстых клиентских приложениях, особенно когда есть возможность потерять значительные суммы или ввод пользователей, вы можете быть лучше с большим количеством try / catches, где вы пытаетесь сохранить данные (помечено как не-пока-действительный, конечно).
EDIT: Еще одна необходимость, по крайней мере, иметь процедуру ведения журнала в PL - это будет работать по-разному в зависимости от платформы. Приложение, над которым мы работаем, делится BLL/DAL с 3 версиями PL: an ASP.Net версия, версия winforms и версия регрессионного тестирования пакетного режима консольного приложения. Вызываемая процедура протоколирования фактически находится в BLL (DAL только выдает ошибки или полностью обрабатывает любые, которые он получает или повторно выбрасывает их). Однако это поднимает событие, которое обрабатывается PL;в интернете он помещает его в журнал сервера и делает веб-стиль отображения сообщения об ошибке (дружественное сообщение для производства); в WinForms появляется специальное окно сообщения с информацией технической поддержки и т.д. и регистрирует ошибку за кадром (разработчики могут сделать что-то "секретное", чтобы увидеть полную информацию). И, конечно, в тестовой версии это гораздо более простой процесс, но и другой.
Не знаю, как бы я это сделал в BLL, если бы не передача параметра "какая платформа", но поскольку она не включает winforms или ASP-библиотеки, от которых зависит ведение журнала, это все равно будет трюком.
Короткий ответ-это зависит!
Вы должны обрабатывать исключение только в том случае, если вы можете сделать с ним что-то полезное. "Что-то полезное" опять же зависит от того, что вы делаете. Возможно, вы захотите зарегистрировать детали исключения, хотя на самом деле это не обработка, и вы действительно должны повторно бросить исключение после регистрации в большинстве случаев. Вы можете обернуть исключение в какое-то другое (возможно, пользовательское) исключение, чтобы добавить дополнительную информацию к исключению. Как @mbeckish касается, вы можете попытаться восстановить исключение, например, повторяя операцию - вы должны быть осторожны, чтобы не повторить попытку навсегда, однако. Наконец (извините за каламбур) вы можете использовать блок finally для очистки любых ресурсов, таких как открытое соединение с БД. То, что вы решите сделать с этим исключением, повлияет на то, как вы его обработаете. Вполне вероятно, что существует не так уж много полезных вещей, которые можно сделать со многими исключениями, кроме как сообщить пользователю, что ошибка произошла, и в этом случае было бы более чем приемлемо обработать исключение в слое пользовательского интерфейса и сообщить о проблеме пользователю (вероятно, вы должны также зарегистрировать исключение, далее по вашим слоям).
Когда вы сами создаете исключения, вы должны всегда создавать исключения только в "исключительных" окружностях, поскольку есть большие накладные расходы при создании исключений. В вашем примере вы предполагаете, что вы можете подумать о создании исключения, если никакие записи не обновляются вашей операцией. Это действительно исключительный случай? Лучше всего в этой ситуации было бы вернуть количество обновленных записей - это все еще может быть условием ошибки, о котором нужно сообщить пользователю, но не исключительным, как ошибка команды, потому что соединение с БД было нарушено.
Это разумная статья о наилучших методах обработки исключений.
Слой, который знает, что нужно сделать, чтобы исправить ситуацию, должен быть слоем, который обрабатывает исключение. Например, если вы решили обрабатывать ошибки взаимоблокировки, повторяя запрос определенное количество раз, то вы можете встроить это в свой DAL. Если он продолжает отказывать, то вы можете позволить исключению всплывать на следующий уровень, который затем может решить, знает ли он, как правильно обрабатывать это исключение.
Все слои в вашем приложении должны корректно управлять исключениями. Это известно как поперечное срезание кукурузного зерна, потому что оно появляется во всех ваших слоях. Я верю, что с помощью фреймворка, такого как Enterprise Exception Block с unity, вы получите лучший код в целом. Взгляните на этот пост
Http://msdn.microsoft.com/en-us/library/ff664698 (v=PandP.50).aspx
Это займет некоторое время, чтобы освоить его, но есть много примеров и скринкаст вокруг там.
Способ обработки исключений зависит от технических и бизнес-потребностей. Для сложных и очень важных обновлений базы данных включает параметры, которые передают небольшой список известных ошибок резервного копирования дл. Таким образом, известные сценарии ошибок могут быть решены программно в некоторых случаях. В других случаях ошибка должна быть зарегистрирована, и пользователь должен быть уведомлен об ошибке.
Я практикую оповещение человека об ошибках. Конечно, Регистрация даст нам подробную информацию, но это нет замены времени отклика человеческого существа. И не только это, но зачем заставлять разработчиков смотреть системные журналы только для того, чтобы увидеть, идут ли дела на юг? Разговоры о ненужных затратах.
Если у вас есть время определить потенциальные ошибки/исключения и программно решить их, то обязательно сделайте это. Много раз ошибки / исключения являются неожиданными. Вот почему важно быть готовым к этому неожиданному и что может быть лучше, чем вовлечение человека.
В целом, при планировании обработки исключений следует занимать оборонительную позицию. Программы растут или умирают. Часть роста-это внедрение ошибок. Так что не крутите свои колеса, пытаясь убить их всех.
Вопрос к вам заключается в том, где уместно исключение? Если это исключение доступа к данным, оно должно быть поймано в DAL. Если это логическое исключение, оно должно быть поймано в BLL. Если это исключение презентации, то в PL.
Например, если ваш DAL выдает исключение, оно должно возвращать null или false или что-то еще в вашем BLL. Ваш BLL должен знать, что делать, если DAL возвращает null, возможно, он передает его прямо через, возможно, он пытается вызвать другой функция и т. д. То же самое происходит с вашим PL, если BLL проходит через null из DAL или возвращает что-то конкретное, то уровень представления должен быть в состоянии уведомить конечного пользователя, что была проблема.
Конечно, вы не получите подробных сообщений об исключениях,но это хорошо для ваших пользователей. Вы должны иметь гибкую систему регистрации, чтобы перехватывать эти исключения и сообщать о них в базу данных или ip: порт или что вы решите.
По существу, вам нужно думать в терминах разделения проблем Если проблема связана с данными или логикой, она должна быть обработана соответствующим образом.
Comments