`
zhang_xzhi_xjtu
  • 浏览: 536622 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

实践中的重构12_不要乱用异常

 
阅读更多
code review的时候,发现了如下代码。

	/**
	 * 验证一个字符串是一个长度为10,且内容都是数字。
	 * */
	public static boolean validate(String str) {
		if (str == null || str.length() != 10) {
			return false;
		}

		// 纯数字
		try {
			Long.valueOf(str);
		} catch (NumberFormatException ex) {
			return false;
		}

		return true;
	}

第一反应是异常这么用,好奇怪。异常不应该这么用的啊,也许是为了图省事吧。
但是还是应该把异常用在异常情况下,而不是这么误用。这个用法和用异常判断文件的结束没有什么太大的区别。

仔细看了看,不仅仅是异常用的比较奇怪,这个方法是有漏洞的。
明明方法接口的约定是判断长度和数字,但是因为是用Long的valueOf方法,通过异常来实现,结果像"-100000000"这样本来不合法的字符串可以通过这个校验了。

重构后代码如下,直白的完成该方法的接口约定。

	/**
	 * 验证一个字符串是一个长度为10,且内容都是数字。
	 * */
	public static boolean validate2(String str) {
		if (str == null || str.length() != 10) {
			return false;
		}

		char[] data = new char[str.length()];

		str.getChars(0, str.length(), data, 0);

		for (int i = 0; i < data.length; i++) {
			char c = data[i];
			if (c < '0' || c > '9') {
				return false;
			}
		}

		return true;
	}

分享到:
评论
24 楼 xibaiben 2010-12-30  
使用正则表达式是不是会抛出异常?
23 楼 gdpglc 2010-12-30  
logicgate 写道
gdpglc 写道
书是用来活学活用的,不是用来做教条的。

不过是一个数字验证,用不着上纲上线。

勿以恶小而为之,勿以善小而不为。


用道德来讨论代码唉!

effective java 里 前边还说 工厂方法比构造方法如何如何好,你是不是把所有的构造都换成工厂方法了呢?

软件最有意思的地方就是,教条不起作用,且害处很大,问题都得具体情况具体分析,每个问题,都要考虑前因后果。书上的一名话就方之四海皆准了...



22 楼 dwangel 2010-12-30  
hobitton 写道
这,,为啥不用regex呢?奇怪……
重构出来的代码看起来一坨坨的,觉得可读性很一般。很好奇string转换成char的array的时候为啥要这样写。

用不用regex其实无所谓,但是string本来就有charAt方法,为啥还要转换呢?
21 楼 jzinfo 2010-12-30  
不要使用异常来作为系统流程的判断

重构前和重构后的代码都比较垃圾。

应该使用正则表达式来进行。
20 楼 mtnt2008 2010-12-30  
楼主实现的没有问题

如果是一个常用方法的话,因为效率的问题,没有使用regex,虽然那样可读性更好一些
19 楼 Durian 2010-12-30  
logicgate 写道
gdpglc 写道
书是用来活学活用的,不是用来做教条的。

不过是一个数字验证,用不着上纲上线。

不以恶小而为之,不以善小而不为。

---------------------------
看到你的回复,我想起一句话:中国很多程序员是认认真真的制造垃圾代码。
18 楼 logicgate 2010-12-30  
gdpglc 写道
书是用来活学活用的,不是用来做教条的。

不过是一个数字验证,用不着上纲上线。

勿以恶小而为之,勿以善小而不为。
17 楼 gdpglc 2010-12-30  
logicgate 写道
gdpglc 写道
logicgate 写道
异常还是不要乱抛的好。

第一种写法,代码很清晰,你称之为 乱抛异常吗?


《Effective Java》 chapter 8:

引用
• Because exceptions are designed for use under exceptional circumstances, few, if any, JVM implementations attempt to optimize their performance. It is generally expensive
to create, throw, and catch an exception.
• Placing code inside a try-catch block precludes certain optimizations that modern
JVM implementations might otherwise perform.
• The standard idiom for looping through an array does not necessarily result in
redundant checks; some modern JVM implementations optimize them away.

The moral of this story is simple: Exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow. A well-designed API must not force its client to use exceptions for ordinary control flow.


最重要的是,这里明明不用异常就可以把事情做的更好。


书是用来活学活用的,不是用来做教条的。

不过是一个数字验证,用不着上纲上线。
16 楼 logicgate 2010-12-30  
gdpglc 写道
logicgate 写道
异常还是不要乱抛的好。

第一种写法,代码很清晰,你称之为 乱抛异常吗?

《Effective Java》 chapter 8:
引用
• Because exceptions are designed for use under exceptional circumstances, few, if any, JVM implementations attempt to optimize their performance. It is generally expensive to create, throw, and catch an exception.
• Placing code inside a try-catch block precludes certain optimizations that modern JVM implementations might otherwise perform.
• The standard idiom for looping through an array does not necessarily result in redundant checks; some modern JVM implementations optimize them away.

The moral of this story is simple: Exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow. A well-designed API must not force its client to use exceptions for ordinary control flow.

最重要的是,这里明明不用异常就可以把事情做的更好。
15 楼 yvfish 2010-12-30  
字符串转换为数值用异常没有这么大的罪吧(虽然程序的本意是进行数值格式检查),当然了,用异常比不用异常性能会差一点,但也比楼主所讲的方法效率高吧。
14 楼 gdpglc 2010-12-30  
logicgate 写道
异常还是不要乱抛的好。

有些人说楼主重构的代码象一砣。。。其实可能是楼主为了说明问题,直接把代码放在这里了。

实际项目中如果经常需要判断数字,完全可以把这段代码提取出来放到utility class里。


你的意思是,乾坤大挪移后,东西变好了是吧。

第一种写法,代码很清晰,你称之为 乱抛异常吗?
13 楼 ch_space 2010-12-30  
超级潜水员 写道
重构出来的代码跟坨屎一样.

+1
12 楼 logicgate 2010-12-30  
异常还是不要乱抛的好。我觉得用regex判断会更优雅。
11 楼 zhang_xzhi_xjtu 2010-12-30  
ouchxp 写道
LZ对重构的理解有偏差..

重构不是改BUG.
重构不是讲解代码规范
重构不是优化代码效率.

重构的目的是在不改变"软件之可察行为"前提下,提高其可理解性,降低其修改成本.


标题的重构的确有一定的误导性。这个我近期会改掉的。
10 楼 starmb 2010-12-30  
原来代码是一个,经过lz重构后变成了一坨。。。
原来代码固然不是个好方法,经过lz重构后的代码虽然完成了所需的期望,但是以牺牲可读性为代价的。满足你的希望,没有错,可你不能强加你的思想于别人,那等同于弓虽女干.可以感觉到你的水平其实并不比原代码作者高哪里去。
9 楼 whaosoft 2010-12-30  
jiangshaolin 写道
请参考《实现模式》和《重构》

上面怎么说的 说说为什么不能乱用exception?
8 楼 jiangshaolin 2010-12-30  
请参考《实现模式》和《重构》
7 楼 ouchxp 2010-12-30  
LZ对重构的理解有偏差..

重构不是改BUG.
重构不是讲解代码规范
重构不是优化代码效率.

重构的目的是在不改变"软件之可察行为"前提下,提高其可理解性,降低其修改成本.
6 楼 sxq51189540 2010-12-30  
为什么不用正则表达式去验证
5 楼 hobitton 2010-12-30  
这,,为啥不用regex呢?奇怪……
重构出来的代码看起来一坨坨的,觉得可读性很一般。很好奇string转换成char的array的时候为啥要这样写。

相关推荐

Global site tag (gtag.js) - Google Analytics