`
fangang
  • 浏览: 860279 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
311c4c32-b171-3767-b974-d26acf661fb2
谈谈用例模型的那些事儿
浏览量:37620
767c50c5-189c-3525-a93f-5884d146ee78
一次迭代式开发的研究
浏览量:67633
03a3e133-6080-3bc8-a960-9d915ed9eabc
我们应当怎样做需求分析
浏览量:405587
753f3c56-c831-3add-ba41-b3b70d6d913f
重构,是这样干的
浏览量:85370
社区版块
存档分类
最新评论

做好代码复用不简单

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

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

……
Number amount
Object value = req.getParameter(“amount”);
try{
	if (value ==null){
	    amount = null;
	} else if (value instanceof Number){
	    amount = (Number)value;
	} else if (value instanceof String){
	    amount = new BigDecimal((String)value).setScale(9, RoundingMode.HALF_UP);
	} else if (value instanceof char[]){
	    amount = new BigDecimal((char[])value).setScale(9, RoundingMode.HALF_UP);
	} else {
	    throw new MsgException("数据不是数字!”);
	}
}catch(NumberFormatException nfe){
	throw new MsgException("数据不是数字格式!”);
}
……


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

/**
* @param value
* @return 根据不同的数据格式返回数字类型的数据
*/
public static Number getNumber(Object value){
	if(value==null){return null;}
	if(value instanceof Number){
	    return (Number)value;
	}
	try{
	    if(value instanceof String){
		return new BigDecimal((String)value).setScale(PRECISION,ROUNDMODE);
	    }
	    if(value instanceof char[]){
		return new BigDecimal((char[])value).setScale(PRECISION,ROUNDMODE);
	    }
	}catch(NumberFormatException nfe){
	    throw new MsgException("数据不是数字格式!”);
	}
	throw new MsgException("数据不是数字!”);
}


然后将原程序改为:

……
Number amount = XxxUtil.getNumber(req.getParameter(“amount”));
……


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

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

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

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

相关文档
遗留系统:IT攻城狮永远的痛
需求变更是罪恶之源吗?
系统重构是个什么玩意儿
我们应当改变我们的设计习惯
小步快跑是这样玩的(上)
小步快跑是这样玩的(下)
代码复用应该这样做(1)
代码复用应该这样做(2)
代码复用应该这样做(3)
做好代码复用不简单
软件可以这样维护


特别说明:希望网友们在转载本文时,应当注明作者或出处,以示对作者的尊重,谢谢!
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics