程序开发中异常的处理方式

时间:2021-01-23 18:04:34

在开始这篇文章之前我先声明一下:这不是一篇讲述如何捕获异常的文章,更没有过多的代码阐述,而是根据自身经验讲述一种开发过程中常见的异常处理方式。到底是什么意思呢?不妨用一个例子来帮助阐述。

在实际开发中往往碰到这种情况:让你在短时间内开发一个小程序,例如期限为三天,这个程序要在三天后交给顾客使用,没有大量的时间去设计和思考并且使用此程序的人只是一般用户且用户量较大。这个时候你如何既保证完成工作又能够保证程序容错性呢?这就是我们必须思考的问题了,毕竟这个程序要交给大量的用户使用啊,而且用户素质又千差万别,很多配置的东西我们肯定不能够保证用户都做到完全无误吧。这样一种情况下我想程序异常处理肯定是很多开发者着重思考的问题吧。

请注意,上面的描述我主要强调:用户使用、大量用户、时间短等几个突出点,因此我下面要说的处理方式在这几种情况下使用应该也是更合适的(当然在其他情况下是否很好用我就不保证了,因为程序开发的设计情况不是三言两语能够概括的)。并且在此我也描述一下我遇到的情况(最近遇到很多类似情况,举一个例子吧):项目经理告诉我原来考核数据的管理都是在Excel中的,现在想使用我们的系统来管理,但是对于用户可能觉得使用Excel录入数据比较方便,所以希望我们开发一个小工具来将这些Excel中的数据导入数据库,并且用户是全市各个单位,大概有三百多个(各个单位使用程序的时候需要配置各自的节点),牵扯数据比较多了,另外注意各个单位的考核指标是不同的,需要动态读取,今天是周一,周四我们准备将程序分配给用户让他们自己使用程序将数据导入。

情况就是这样,和我上面描述的差不多。我接到任务后当然首先做的就是初步规划,想想三天应该没有问题,接着就想如何应对程序异常,三百多个用户使用,导入的Excel各种各样,而且牵扯到几个配置点,怎么保证程序能够合理应对各种操作而不出现问题呢?

根据情况我设计了考核对象、考核主体、考核指标、考核批次、考核类型、对象指标考核结果、对象指标主体考核结果、对象结果、目录管理类等大概十几个类,而这其中牵扯到用户数据操作的类(这些类通常也是需要异常处理的)主要是对象指标考核结果、对象指标主体考核结果、对象结果三个类,因为各种导入方法都在这三个类中,除此之外当然是主程序类了(其他类当然也牵扯到各种操作,处理方法类似)。举例来说对象指标主体考核结果类会存储各个主体对考核对象的各种评价得分,这其中就包括导入方法Import(主程序调用此方法)。当然导入的时候就牵扯到异常的处理,如果导入过程中遇到异常我们在哪里捕获,以及捕获之后该如何处理,变成了我们的必须思考的问题。根据情况我最终的处理方式是这样的:为了详细记录异常我首先定义了一个错误容器类(其实主要是有一个StringBuilder类型的属性来记录所有错误),它是一个单例模式类,它负责记录整个程序中所有的异常信息;然后在对象指标主体考核结果类的Import方法中我用try catch捕获异常(请注意也可以根据if判断抛出异常并不是只有直接使用try catch才可以throw你的异常,并且异常在一个方法中可以出现多处),并且在catch中我首先将自己想给出的提示(例如:"XXX出错,请检查XXX")和程序异常(例如:ex.message)记录到错误容器类中,然后使用Throw ex将异常抛出(供其上级捕获,注意可以有多层上级程序,此时程序将逐级捕获,例如调用它的主程序类);在调用它的主程序中(我这里是直接在主程序调用,当然也可以不直接在主程序中调用)再次利用try catch捕获异常(这个异常捕获一定要有,因为这是程序入口,在这里进行异常捕获可以捕捉所有异常),然后如果遇到异常就不在抛出了,而是在记录错误容器之后一同写入错误日志中,然后提示用户(例如MessageBox.Show("XXX"))"应用程序出现异常,异常已记录到错误日志!"。同样其他的类中也这样做,就可以捕获所有的异常,而且最终可以给出用户调整方式(如上面说的:请检查XXX)此时用户就可以根据提示修改错误重新执行程序了。更重要的是我觉得不至于因为异常捕获而打乱了面向对象的程序设计方法(之所以这样说是因为很多初学者认为只有将所有的操作写在一个方法中才可以根据不同情况捕获异常)。

当然,像上面的例子我们紧紧捕获异常还不够,还有很重要的一点就是对于事务的处理,很明显我们一个Excel有三个导入类来分别导入到不同的表中,如何安排事务呢?事务写到哪个类中呢?这要根据情况,如果你认为如果一条数据出错所有的数据都不导入,当然事务要写到主程序中(因为主程序调用这三个类的导入方法),这个当然要根据实际情况而定。另外值得一提的是如果希望灵活应用事务,尽量选择.Net2.0的事务机制,而不是.Net1.1,使用方法可以看我的另外一篇博客".Net2.0中新的事务类型"一文。

总结:上面说了那么多可以用简短的话来阐述:在被调用类(被主程序或其他类调用的类)中捕获异常记录到容器类中,然后抛出;在调用类(非主程序类)中继续捕获,然后同样是记录到错误容器继续向上抛出;依此方法直到最后在主程序中(入口程序类)捕获异常(记住这个捕获一定要捕获所有可能异常的情况)然后连同此次错误信息一并记录到错误容器,写入错误日志,给出相应提示。