论坛首页 Java企业应用论坛

实践中的重构06_方法调用顺序和性能

浏览 8059 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-11-15   最后修改:2011-02-26
所有性能优化的书都告诉我们不要优化。但是,如果开发一个大型系统或者关键系统。在写code的时候,性能还是应该有所考虑的。
	public boolean f_0(String userId) {

		// isLoginAgainInMonth is local call.
		boolean isLoginAgainInMonth = isLoginAgainInMonth(userId);
		// isGardUser is ws call.
		boolean isGardUser = isGardUser(userId);

		return isLoginAgainInMonth || isGardUser;
	}

上面的code判断了一个用户是本月的非第一次登录,或者是一个受保护的用户,是的话返回true,做一些处理。
大眼一看,这段代码当然是没有什么问题的。但是加上性能的考量,问题就出来了。
isLoginAgainInMonth是一个local call,isGardUser是一个ws call,当isLoginAgainInMonth为true的时候是可以直接返回的,多调用一次isGardUser就多一次ws开销,这个开销包括网络开销,内存开销,甚至db开销。如果该代码被大量执行次数放大的话,所消耗的资源还是很可观的。
这里调整代码来强调方法的调用顺序对性能的影响。重构后为:
	/**
	 * Note: 为了性能考量,先调用本地方法,后调用ws服务,当可以判断出结果的时候,尽早返回。
	 * */
	public boolean f_1(String userId) {
		// isLoginAgainInMonth is local call.
		if (isLoginAgainInMonth(userId)) {
			return true;
		}

		// isGardUser is ws call.
		return isGardUser(userId);
	}

还有一种利用短路特性的写法。
	/**
	 * 不推荐的写法。
	 * */
	public boolean f_2(String userId) {
		return isLoginAgainInMonth(userId) || isGardUser(userId);
	}



这种写法利用短路的特性达到了同样的功能,并且看上去代码更简洁。
但是,应该承认的是,并不是所有程序员对短路的特性都掌握了,同时,即使掌握短路的程序员看到这段代码的时候也未必能够意识到这里的短路和性能相关。该写法没有达到强调方法调用顺序和性能的关系的作用,因此不推荐这种写法。

谢谢tuti的建议。
   发表时间:2010-11-15   最后修改:2010-11-15
zhang_xzhi_xjtu 写道


		//isLastLoing is local call.
		boolean isLoginAgainInMonth=isLoginAgainInMonth(userId);
		
		if(isLoginAgainInMonth){
			return true;
		}
		
		//isGardUser is ws call.
		boolean isGardUser=isGardUser(userId);
		
		return isGardUser;




这样如何?
	
		return isLoginAgainInMonth(userId)||isGardUser(userId);

0 请登录后投票
   发表时间:2010-11-15  
tuti 写道
zhang_xzhi_xjtu 写道


		//isLastLoing is local call.
		boolean isLoginAgainInMonth=isLoginAgainInMonth(userId);
		
		if(isLoginAgainInMonth){
			return true;
		}
		
		//isGardUser is ws call.
		boolean isGardUser=isGardUser(userId);
		
		return isGardUser;




这样如何?
	
		return isLoginAgainInMonth(userId)||isGardUser(userId);



这个当然也行,最早我也是这个想法,但是考虑到未必所有的人都知道短路,才用长一点的方式写,这样可以突出早返回这个特性,后来的程序员也就不会忽略这个东西了。
0 请登录后投票
   发表时间:2010-11-15  
zhang_xzhi_xjtu 写道
tuti 写道
zhang_xzhi_xjtu 写道


		//isLastLoing is local call.
		boolean isLoginAgainInMonth=isLoginAgainInMonth(userId);
		
		if(isLoginAgainInMonth){
			return true;
		}
		
		//isGardUser is ws call.
		boolean isGardUser=isGardUser(userId);
		
		return isGardUser;




这样如何?
	
		return isLoginAgainInMonth(userId)||isGardUser(userId);



这个当然也行,最早我也是这个想法,但是考虑到未必所有的人都知道短路,才用长一点的方式写,这样可以突出早返回这个特性,后来的程序员也就不会忽略这个东西了。



这样如何?
		
		if(is_login_again_in_month(userId)){
			return true;
		}
		return is_gard_user_via_call_ws(userId);


0 请登录后投票
   发表时间:2010-11-15   最后修改:2010-11-15
tuti 写道
zhang_xzhi_xjtu 写道
tuti 写道
zhang_xzhi_xjtu 写道


		//isLastLoing is local call.
		boolean isLoginAgainInMonth=isLoginAgainInMonth(userId);
		
		if(isLoginAgainInMonth){
			return true;
		}
		
		//isGardUser is ws call.
		boolean isGardUser=isGardUser(userId);
		
		return isGardUser;




这样如何?
	
		return isLoginAgainInMonth(userId)||isGardUser(userId);



这个当然也行,最早我也是这个想法,但是考虑到未必所有的人都知道短路,才用长一点的方式写,这样可以突出早返回这个特性,后来的程序员也就不会忽略这个东西了。



这样如何?
		
		if(is_login_again_in_month(userId)){
			return true;
		}
		return is_gard_user_via_call_ws(userId);




这个也考虑过,只是为了方便调试,一般把方法的返回值都独立出来。
0 请登录后投票
   发表时间:2010-11-15  
zhang_xzhi_xjtu 写道


这个也考虑过,只是为了方便调试,一般把方法的返回值都独立出来。


方便在哪?
0 请登录后投票
   发表时间:2010-11-16  
gdpglc 写道
zhang_xzhi_xjtu 写道


这个也考虑过,只是为了方便调试,一般把方法的返回值都独立出来。


方便在哪?


以后还要加判断什么地,多加几个你就知道这么写会改起来容易
0 请登录后投票
   发表时间:2010-11-16  
我觉得短路多好,简单易懂,那两个变量看着就不舒服。
0 请登录后投票
   发表时间:2010-11-16   最后修改:2010-11-16
seele 写道
gdpglc 写道
zhang_xzhi_xjtu 写道


这个也考虑过,只是为了方便调试,一般把方法的返回值都独立出来。


方便在哪?


以后还要加判断什么地,多加几个你就知道这么写会改起来容易

以后等需要再变....
尽量不过度设计.....

PS:你的设计像是在说拷贝很方便,来用拷贝方式吧.

我的项目有有很多这样的提前预判过期的东西.
我用一个cache类(后来是包)放.
刚刚改成定时抓取的,(需求....)
0 请登录后投票
   发表时间:2010-11-16  


这个也考虑过,只是为了方便调试,一般把方法的返回值都独立出来。

我也想知道到底方便在哪里?
楼主的上一个帖子,不是也直接这样了吗?


实践中的重构05_简洁的代码

if (a|| b|| c) {
   return true;
}
return false;


可以改为

return a|| b|| c;
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics