简体   繁体   English

如何重构通用异常的使用?

[英]How to refactor use of the general Exception?

Our code catches the general exception everywhere. 我们的代码到处都捕获了一般异常。

Usually it writes the error to a log table in the database and shows a MessageBox to the user to say that the operation requested failed. 通常,它将错误写入数据库中的日志表,并向用户显示一个MessageBox,以表明请求的操作失败。 If there is database interaction, the transaction is rolled back. 如果存在数据库交互,则事务将回滚。

I have introduced a business logic layer and a data access layer to unravel some of the logic. 我已经介绍了业务逻辑层和数据访问层,以阐明一些逻辑。 In the data access layer, I have chosen not to catch anything and I also throw ArgumentNullExceptions and ArgumentOutOfRangeExceptions so that the message passed up the stack does not come straight from the database. 在数据访问层中,我选择不捕获任何内容,并且还引发ArgumentNullExceptions和ArgumentOutOfRangeExceptions,以使传递到堆栈的消息不会直接来自数据库。

In the business logic layer I put a try catch. 在业务逻辑层中,我尝试了一下。 In the catch I rollback the transaction, do the logging and rethrow. 在catch中,我回滚事务,进行日志记录并重新抛出。

In the presentation layer there is another try catch that displays a MessageBox. 在表示层中,还有另一个尝试捕获显示一个MessageBox。

I am now thinking about catching a DataException and an ArgumentException instead of an Exception where I know the code only accesses a database. 我现在正在考虑捕获DataException和ArgumentException而不是Exception,因为我知道代码仅访问数据库。

Where the code accesses a web service, then I thought I would create my own "WebServiceException", which would be created in the data access layer whenever an HttpException, WebException or SoapException is thrown. 在代码访问Web服务的地方,我想我将创建自己的“ WebServiceException”,每当抛出HttpException,WebException或SoapException时,都将在数据访问层中创建它。

So now, generally I will be catching 2 or 3 exceptions where currently I catch just the general Exception, and I think that seems OK to me. 因此,现在,通常我将捕获2或3个异常,而目前我仅捕获一般的Exception,我认为这对我来说似乎还可以。 Does anyone wrap exceptions up again to carry the message up to the presentation layer? 是否有人再次包装异常以将消息传递到表示层?

I think I should probably add a try catch to Main() that catches Exception, attempts to log it, displays an "Application has encountered an error" message and exits the application. 我认为我可能应该向Main()添加一个try catch,以捕获Exception,尝试对其进行记录,显示“应用程序遇到错误”消息,然后退出该应用程序。 So, my question is, does anyone see any holes in my plan? 所以,我的问题是,有人看到我的计划有任何漏洞吗? Are there any obvious exceptions that I should be catching or do these ones pretty much cover it (other than file access - I think there is only 1 place where we read-write to a config file). 是否有任何明显的例外我应该捕捉或这些错误几乎涵盖了所有内容(除了文件访问权限以外-我认为只有一个地方可以读写配置文件)。

Seems like you are making some good improvements to your application. 似乎您正在对应用程序进行一些很好的改进。 I also generally wrap the most outer most layer of an application in a try/catch Exception block so that unexpected exceptions (eg runtime ones) can allow the application to exit gracefully. 我通常还将应用程序的最外层包装在try/catch Exception块中,以便意外的异常(例如运行时异常)可以允许应用程序正常退出。

One question for you is if it makes sense to delegate to the business logic the responsibility of a data rollback . 对您来说,一个问题是将数据回滚的责任委托给业务逻辑是否有意义。 This would seem better encapsulated in the data access layer. 这似乎更好地封装在数据访问层中。 You could then throw an exception of your choice from the data layer rather than opening up that layer to throwing any old exception, because what happens to your business logic layer if your data layer throws something you didn't expect? 然后,您可以从数据层引发选择的异常,而不是开放该层以引发任何旧异常,因为如果您的数据层引发了意外的事情,那么业务逻辑层会发生什么?

Or what if you later extract your data access layer and replace it with something else? 或者,如果您以后提取数据访问层并将其替换为其他内容,该怎么办? At the very least, you'll have to remove all your rollback logic from the business logic layer. 至少,您必须从业务逻辑层中删除所有回滚逻辑。

I would use try/finally (or the using statement which is equivalent) for your rollback, rather than doing it in a catch block. 我将使用try / finally(或等效的using语句)进行回滚,而不是在catch块中进行回滚。 In particular if you are only catching specific exceptions, you will still want the database rollback to take place if an unexpected Exception type is thrown. 特别是,如果仅捕获特定的异常,则仍然会引发抛出意外的Exception类型的数据库回滚。

With few exceptions I rarely use a catch anywhere except: 除了少数例外,我很少在任何地方使用catch:

  • At a physical tier boundary I use try/catch with log/throw in the catch block so that exceptions can be logged on the server. 在物理层边界,我在catch块中将try / catch与log / throw一起使用,以便可以在服务器上记录异常。 With newer technologies such as WCF exceptions can be logged without a try/catch (eg with a WCF DispatchBehavior). 使用诸如WCF之类的更新技术,无需尝试/捕获即可记录异常(例如,使用WCF DispatchBehavior)。

  • In a top-level handler in the presentation tier. 在表示层的顶级处理程序中。

In the business and data tiers, there will be a lot of try/finally (ie using statements) but almost never a catch. 在业务和数据层中,将进行很多尝试/最终尝试(即使用语句),但几乎没有成功。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM