做好代码复用不简单

前面我们用了那么多示例讨论了代码复用。毫无疑问,几乎所有人都明白代码复用的重要意义,知道要写好代码必须要合理地复用代码。然而,曾经有一份真挚的感情放在你面前你却没有珍惜,那就是你应该复用代码了。等你失去的时候我才后悔莫及,有木有?为什么每当我们应当复用代码的关键时刻,我们却往往选择复制粘贴呢?因为道理非常清楚但实际操作起来却困难重重,因为要实现复用必须要调整原有程序。要调整原有程序,这就不好玩了,我们就不知道该怎样应对了,还是复制粘贴来得简单快捷。 

有一次,我参与了一个财务系统的研发。我在开发一个功能的时候,发现有个数值型参数,有时候在前端传过来的时候数据位数或精度会非常大,造成转型成Number类型的时候会出错,必须转型成BigDecimal。同时,前端传送过来的数据有可能是String类型,也可能是char[]类型。为此我进行了如下的修改: 

Java代码   收藏代码
  1. ……  
  2. Number amount  
  3. Object value = req.getParameter(“amount”);  
  4. try{  
  5.     if (value ==null){  
  6.         amount = null;  
  7.     } else if (value instanceof Number){  
  8.         amount = (Number)value;  
  9.     } else if (value instanceof String){  
  10.         amount = new BigDecimal((String)value).setScale(9, RoundingMode.HALF_UP);  
  11.     } else if (value instanceof char[]){  
  12.         amount = new BigDecimal((char[])value).setScale(9, RoundingMode.HALF_UP);  
  13.     } else {  
  14.         throw new MsgException("数据不是数字!”);  
  15.     }  
  16. }catch(NumberFormatException nfe){  
  17.     throw new MsgException("数据不是数字格式!”);  
  18. }  
  19. ……  


经过测试,该问题得到了修复。但在随后的开发中,我发现系统中许许多多从前端获取数字的程序都需要这段程序。如果当我们每次需要这个功能时都将这段代码拷贝过去,实现现有的功能当然没有问题,但却会为日后的维护埋下隐患。假如有一天这段程序需要调整,难道我们要到整个系统的数百份拷贝中去修改吗?道理大家都明白,关键是这样的问题却在无数软件系统中反复出现。 
在这里问题的关键在于,要让这段程序为其它的程序所复用,不修改它自身是根本没有办法做到的。我们必须从现有程序中将这段程序提取出来形成一个公用函数,为其它程序所复用,然后将该程序修改成对这个公用程序的引用才行。为此我做出了如下修改: 
首先运用“抽取方法”,将这段代码从其它程序中提取出来,放到工具类中形成一个静态调用函数: 

Java代码   收藏代码
  1. /** 
  2. * @param value 
  3. * @return 根据不同的数据格式返回数字类型的数据 
  4. */  
  5. public static Number getNumber(Object value){  
  6.     if(value==null){return null;}  
  7.     if(value instanceof Number){  
  8.         return (Number)value;  
  9.     }  
  10.     try{  
  11.         if(value instanceof String){  
  12.         return new BigDecimal((String)value).setScale(PRECISION,ROUNDMODE);  
  13.         }  
  14.         if(value instanceof char[]){  
  15.         return new BigDecimal((char[])value).setScale(PRECISION,ROUNDMODE);  
  16.         }  
  17.     }catch(NumberFormatException nfe){  
  18.         throw new MsgException("数据不是数字格式!”);  
  19.     }  
  20.     throw new MsgException("数据不是数字!”);  
  21. }  


然后将原程序改为: 

Java代码   收藏代码
  1. ……  
  2. Number amount = XxxUtil.getNumber(req.getParameter(“amount”));  
  3. ……  


这里,我们运用了重构中“两顶帽子”的设计方式,先在不增加新功能的情况下,调整原程序内部结构,即抽取出工具类,以此来适应新功能的需要。经过这样的调整,在实现新功能时就可以大胆复用原有代码了,复用变得不再那么困难。 

然而,我们说,做好代码复用简约而不简单,它考验的是IT攻城狮的设计水平与开发能力。怎么说呢?有时候我们意识到应该复用了,但真正要写好复用真的需要下很多功夫。而每一个复用都是一个分析、设计、重构的过程。 

没有经过重构的、原生态的代码是没有办法复用的,但当我们发现代码需要复用时,切忌不要使用过去那种简单粗暴的复制粘贴。合理运用重构方法,加之以仔细、认真、及时的测试,可以保证既有代码的正确,而使整个系统合理地复用起来,以提高系统的可维护性,关键是你有没有这样的意识。所以,重构是一种习惯。 

然而,复用不是银弹,它不能搞定一切问题。被复用以后,如果公用的代码出现变更,甚至出现一部分客户使用旧程序,一部分客户使用新程序,应当怎么办呢?呵呵,这下好,老革命遇到了新问题。这常常让人十分头疼,而要解决这个问题,我们就进入了一个新的话题,老程序的功能扩展……(续) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值