一:发现问题
先来说如何重构业务层的try{}catch{}finally{}代码块,我看过很多代码,异常处理这一块大致分为两种情况,一种是每个方法都大量的充斥着try{}catch{}finally{},这种方式的编程已经考虑到了异常处理,还有一种就是没有try{}catch{}finally{}的代码,因为根本就没有考虑代码的异常处理。每当我看到这样的代码,我都很忧伤。从程序的健壮性来看第一种还是要比第二种情况好,至少在编程意识中,随时想到了异常情况,有一种基本的编程思想。
比如:一个业务单据的多表插入,关联修改,虚拟删除等都是一些基本的操作,但是又是比较容易引起错误的操作,在这些方法上都会加上try{}catch{}finally{}对代码进行有效的防错处理。早期的代码是这样的。
public Boolean Save(AccountModel accountData) { Boolean result = false; try { //TODO ... result = true; } catch { } finally { } return result; } public Boolean Edit(AccountModel accountData) { Boolean result = false; try { //TODO ... result = true; } catch { } finally { } return result; } public Boolean VirDelete(AccountModel accountData) { Boolean result = false; try { //TODO ... result = true; } catch { } finally { } return result; }
仅仅定义了添加,修改,删除几个空方法,就写了三四十行代码,如果业务稍微复杂些,异常处理的代码很快就会突破百行大关。虽然复制,粘贴try{}catch{}finally{}很好使,但是业务逻辑代码大量充斥着这样的try{}catch{}finally{}代码,确实显得做事不够利落。
二:解决问题
那怎样来解决这件棘手的事呢,首先定义一个公用的try{}catch{}finally{},如下如示:
public class Process { public static bool Execute(Action action) { try { action.Invoke(); return true; } catch (Exception ex) { //1,异常隐藏 //2,异常替换 //3,异常封装 //写日志 return false; } finally { } } }
上边的代码定义了公用的try{}catch{}finally{},最关键是怎么运用起来,如下代码:
protected void Page_Load(object sender, EventArgs e) { AccountModel accountData = new AccountModel(); //准备传入的参数 Boolean result = false; //接收返回的值 Process.Execute(() => result = Save(accountData)); //执行方法 } public Boolean Save(AccountModel accountData) { Boolean result = false; //TODO ... result = true; return result; } public Boolean Edit(AccountModel accountData) { Boolean result = false; //TODO ... result = true; return result; } public Boolean VirDelete(AccountModel accountData) { Boolean result = false; //TODO ... result = true; return result; }
这样的精简过的代码,是不是感觉心情很舒畅。
三:提升与扩展
对于知足者常乐的人来说,到第二个步骤就可以洗洗睡了。但是对于精益求精的人来说,问题仍然没有完。我们来说一个应用场景,在WCF中的应用,我们知道WCF服务端的异常,不经过的设置,服务端的异常是无法抛到客户端的。但是在正式环境中,不可能对进行serviceDebug的配置。正确的处理是在服务端对异常进行隐藏,替换,或者封装。
比如我们在服务端捕获了一个已知异常,但是这个异常会暴露一些敏感的信息,所以我们对异常进行替换,抛出新的异常后,我们还要把这个异常怎样传输给客户端。首先们要明确WCF中的一些基本常识,就是WCF中的数据传递要遵循WCF的数据契约,服务端抛到客户端的异常(异常其实也是数据),所以必须要给异常定义异常契约。
[DataContract(Name = "WCFException")] public class WCFException { [DataMember(Name = "Type")] public String Type { get; set; } [DataMember(Name = "StackTrace")] public String StackTrace { get; set; } [DataMember(Name = "Message")] public String Message { get; set; } }
然后处理异常的公共方法改写为:
public static bool Execute(Action action) { try { action.Invoke(); return true; } catch (Exception ex) { //1,异常隐藏 //2,异常替换 //3,异常封装 //写日志 WCFException exception = new WCFException { Type = "Error" , StackTrace = ex.StackTrace , Message = ex.Message }; throw new FaultException(exception , new FaultReason("服务端异常:" + ex.Message) , new FaultCode(ex.TargetSite.Name)); } finally { } }
这样在服务端抛出的异常,就能在客户端捕捉到。现在是不是感觉自己又提升了一些,想成为编程高手是指日可待了。
四:举一反三
异常的处理也不过如此,那是不是应该举一反三,看看事务的处理应该怎么办?比如现在大量的访求都用到了事务,如下代码:
public Boolean Save(AccountModel accountData) { OracleConnection conn = new OracleConnection("连接字符串"); IDbTransaction trans = conn.BeginTransaction(); Boolean result = false; try { //TODO ... trans.Commit(); result = true; } catch { trans.Rollback(); } finally { } return result; }
特别是 trans.Commit(); trans.Rollback(); 这样的代码出现在每个与事务相关的方法中, 让我感觉到代码的臃肿,以及隐陷约约的失望。
经过我几天的翻阅资料终于实现了事务的公用访求提取。使用方法如下代码所示:
[TransactionAttribute] [ExceptionAttribute] public bool Save(DataContext dContext, Dictionary<string, string> dtoPara) { Boolean returnVal = true; //TODO ... return returnVal; }
就是在一个方法上加[TransactionAttribute]就表示这个方法写在了事务中,反之,不在事务中,加[ExceptionAttribute]就表示这个方法作了异常处理,反之,不作异常处理。通过反射或者AOP都能实现Attribute编程的效果。
相关推荐
在给定的【标题】"精简自己 20% 的代码 - 文章 - 伯乐在线1" 和【描述】中,主要讨论的问题是如何优化业务层中的 `try{}catch{}finally{}` 结构,以减少冗余代码并提高代码的可读性和可维护性。 传统的做法是在每个...
### 代码重构:现有代码优化的关键知识解析 代码重构,这一概念在软件开发领域中扮演着至关重要的角色,它指的是在不改变代码外部行为的前提下,对现有代码进行修改以提高其内部结构和可读性,从而提升软件的质量和...
《重构:改善既有代码的设计》是一本由Martin Fowler所著的经典IT著作,专注于软件开发过程中的一项重要技术——重构。重构是指在不改变软件外部行为的前提下,对代码进行修改以改进其内部结构,使得代码更易理解和...
重构不是新增功能或修复bug,而是在现有功能的基础上,对代码进行优化和精简,使代码更加健壮、易于理解和维护。 #### 重构的目的 1. **提高代码质量**:通过清理不必要的复杂性,使得代码更易于阅读和理解。 2. *...
- **折叠继承体系(Collapse Hierarchy)**:精简继承树,去除不必要的层次,提高代码的可读性和可维护性。 - **合并未决条件(Consolidate Conditional Expression)**:将多个相似的条件表达式合并,减少代码冗余。 - ...
【标题】: "软件设计模式与重构大作业-心算大师游戏" 【描述】: 这是一个关于软件设计模式和重构的项目,具体是为西南...重构过程应逐步进行,确保每次小改动都能通过测试,以保证重构过程中代码的稳定性和正确性。
标题中的“基于Springboot精简了代码,改变为单体”指的是这个开源项目采用Spring Boot框架,对原有的代码进行了优化和精简,将其重构为一个单体应用。Spring Boot是Java开发者的常用工具,它简化了Spring应用的初始...
### 《代码之美_精简版.pdf》知识点总结 #### 一、背景及起源 - **书籍起源**:《Beautiful Code》是由Greg Wilson发起并在2006年构思的项目,旨在从全球范围内优秀的软件开发者和计算机科学家那里收集有价值的...
- **我做了什么**:作者通过对原有代码的逐步重构,实现了代码的精简、优化和重构。 - **是什么原因让我引入了BUG**:在重构的过程中,作者意识到过于激进的修改可能会引入新的问题。 - **我是如何修改的**:通过...
- **代码重构**:代码重构可能导致行数增减,但可能提高代码质量。 - **嵌套结构**:循环、条件语句和函数调用可能使单行代码产生多行效果,需综合考虑。 6. **高级话题** - **圈复杂度(Cyclomatic Complexity...
3. **代码重构**:介绍如何通过重构提高代码质量,包括识别坏味道的代码、提炼函数、提取类等重构技术,以及如何在不改变外部行为的情况下改善代码结构。 4. **数据结构与算法**:探讨常见的数据结构(如数组、链表...
6. **媒体查询优化**:针对不同设备和屏幕尺寸的媒体查询应当精简和优化,避免不必要的加载。考虑使用`@import`或`<link>`按需加载响应式样式表,减少非必需的样式加载。 7. **避免使用!important**:过多使用`!...
新闻阅读应用重构:基于Android开发,包含83个文件,包括28个PNG图像文件、...该项目是一个新闻阅读应用的重构版本,采用了谷歌原生的抽屉布局,使代码量精简,界面更加清爽,旨在为用户提供一个更优化的新闻阅读体验。
javascript 之吝啬精简代码是指在前端开发中,学习如何吝啬自己的代码,写出更加简洁高效的代码。下面是相关知识点的总结: 一、吝啬代码 吝啬代码是指在编写代码时,尽量少用代码实现相同的功能。例如,在使用 ...