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

实践中的重构08_集合判空时的可读性

阅读更多
代码的可读性应该还是着重强调的,毕竟,代码是给人读的。如
if(null==a)

这样的代码,看的出是从c惯用法继承下来,试着读一下,当null不为a,则如何如何。至少我读起来有点别扭。我还是喜欢这样的形式,当a不为null,则如何如何。
当然,更厉害的是经常看到如下的片段
if(list.size()==0)
if(list.size()<1)

ok,size==0这个我还可以想的通为什么这么写,但是<1这种写法真的让人无语。
if(list.isEmpty())

这样当然更进一步。为什么呢,因为使用size是因为我们知道该类的内部实现,判断时涉及了类的实现,而isEmpty只是语义上判断一个列表是否为空,不涉及实现细节。
还有一种挺常见的,好的做法是集合类引用对象永远不用判null。
    if(list!=null && !list.isEmpty()){  
      // do something.  
    }  

我们可以把对list的判null和判空抽出来,变成
    if(!CollectionUtil.isEmpty(list)){  
      // do something.  
        }

更进一步。
    if(CollectionUtil.isNotEmpty(list)){  
      // do something.  
    }  

问题在于,null和empty在特定的上下文中真的是一样的吗。
分享到:
评论
20 楼 mercyblitz 2010-12-21  
zhang_xzhi_xjtu 写道
mercyblitz 写道
zhang_xzhi_xjtu 写道
代码的可读性应该还是着重强调的。


if(null==a)

这样的代码,至少我读起来有点别扭。

当然,更厉害的是
if(list.size()<1)

我知道有些人喜欢写成
if(list.size()==0)

ok,这个我还可以想的通为什么这么写,但是<1这种写法真的让人无语。

if(list.isEmpty())

这样当然更进一步。

毕竟,代码是给人读的。

好吧,其实一般都是这么用的
if(list!=null && !list.isEmpty()){
//xixihaha
}


我们可以把对list的判null和判空抽出来,变成
if(!CollectionUtil.isEmpty(list)){
//xixihaha
}


问题在于,null和empty在特定的上下文中真的是一样的吗。




list.size()==0 没有什么可读性差的。只是个人风格地问题。


为什么不这么写呢?

if(CollectionUtil.isNotEmpty(list))



这样写的可读性更好。
问题在于,null和empty在特定的上下文中真的是一样的吗。



不能完全肯定和否定,很多业务需要区分null和empty的!

一般null通过断言判断,在参数传递时,但是CollectionUtil类为了容错性,必须判断null到做empty!
19 楼 zhang_xzhi_xjtu 2010-12-20  
mercyblitz 写道
zhang_xzhi_xjtu 写道
代码的可读性应该还是着重强调的。


if(null==a)

这样的代码,至少我读起来有点别扭。

当然,更厉害的是
if(list.size()<1)

我知道有些人喜欢写成
if(list.size()==0)

ok,这个我还可以想的通为什么这么写,但是<1这种写法真的让人无语。

if(list.isEmpty())

这样当然更进一步。

毕竟,代码是给人读的。

好吧,其实一般都是这么用的
if(list!=null && !list.isEmpty()){
//xixihaha
}


我们可以把对list的判null和判空抽出来,变成
if(!CollectionUtil.isEmpty(list)){
//xixihaha
}


问题在于,null和empty在特定的上下文中真的是一样的吗。




list.size()==0 没有什么可读性差的。只是个人风格地问题。


为什么不这么写呢?

if(CollectionUtil.isNotEmpty(list))



这样写的可读性更好。
问题在于,null和empty在特定的上下文中真的是一样的吗。

18 楼 mercyblitz 2010-12-20  
zhang_xzhi_xjtu 写道
代码的可读性应该还是着重强调的。


if(null==a)

这样的代码,至少我读起来有点别扭。

当然,更厉害的是
if(list.size()<1)

我知道有些人喜欢写成
if(list.size()==0)

ok,这个我还可以想的通为什么这么写,但是<1这种写法真的让人无语。

if(list.isEmpty())

这样当然更进一步。

毕竟,代码是给人读的。

好吧,其实一般都是这么用的
if(list!=null && !list.isEmpty()){
//xixihaha
}


我们可以把对list的判null和判空抽出来,变成
if(!CollectionUtil.isEmpty(list)){
//xixihaha
}


问题在于,null和empty在特定的上下文中真的是一样的吗。




list.size()==0 没有什么可读性差的。只是个人风格地问题。


为什么不这么写呢?

if(CollectionUtil.isNotEmpty(list))






17 楼 zhang_xzhi_xjtu 2010-12-20  
一切行为都要受到实际情况的限制。

16 楼 smallhand 2010-12-20  
tuti 写道
zhang_xzhi_xjtu 写道
我是完全同意集合为空的情况下不返回null而是返回一个空集合这个惯例的。
但是有以下两种情况会有纠结的地方。
1 底层代码无法改动,加入一个间接层会提高别的程序员的使用成本。
2 大型项目中,一个人所能改动的代码是有范围限制的,对于自己没有改动权限的代码问题,最多提提建议。所以这个重构也只能局限在自己的系统中。


既然知道什么是对的,那就要去做。
说说都知道,但都不去做,那和不知道又有什么区别呢。
软件开发,本来就是个协作游戏,需要相互沟通和反馈,这在大型项目中,尤其重要。

极限编程(XP)主要的价值观包括:沟通,简单,反馈,勇气,尊重。
换言之,如果缺少“沟通,反馈,勇气,尊重”,那么“简单”也是做不到的。

这个返回null不就是个例子吗?

我同意你的看法。但是就我们公司来说,即使你有想法要动,公司领导也不同意。因为他们大多要的是稳定,能用就行。我们的jdk还是1.4的,浏览器IE7有的功能不能用。但是就是说以后再动。也是无奈啊
15 楼 yuan 2010-12-20  
:) 是呀,既然是一起做事,代码还是集体所有好些。面子问题一边去。

说来说去,agile对程序员的素质是有要求的,选人、组建团队很关键,招聘是第一关。招聘搞好了,麻烦事会少很多。扯远了……
14 楼 tuti 2010-12-19  
zhang_xzhi_xjtu 写道
我是完全同意集合为空的情况下不返回null而是返回一个空集合这个惯例的。
但是有以下两种情况会有纠结的地方。
1 底层代码无法改动,加入一个间接层会提高别的程序员的使用成本。
2 大型项目中,一个人所能改动的代码是有范围限制的,对于自己没有改动权限的代码问题,最多提提建议。所以这个重构也只能局限在自己的系统中。


既然知道什么是对的,那就要去做。
说说都知道,但都不去做,那和不知道又有什么区别呢。
软件开发,本来就是个协作游戏,需要相互沟通和反馈,这在大型项目中,尤其重要。

极限编程(XP)主要的价值观包括:沟通,简单,反馈,勇气,尊重。
换言之,如果缺少“沟通,反馈,勇气,尊重”,那么“简单”也是做不到的。

这个返回null不就是个例子吗?
13 楼 zhang_xzhi_xjtu 2010-12-19  
yuan 写道
tuti 写道
list 就不应该为null

对,除非是第3方库某个本该返回集合的方法返回了个null才需要这么处理(我认为那也是这个库的作者不专业,而且即使是第3方库也可以自己修改)。如果是自己写的方法,从语义上说,这个方法的返回值如果是一个集合,那在该方法运行结果是这个集合为空的情况下,怎么也不应该返回null。1是影响可读性,2是其它每个调用该方法的地方还要处理这个null。返回null是自己给自己找麻烦。

LZ在另一帖中 写道
get底层的服务,别人未必想的那么周全,如果它的注释中,没有声明一定不返回null的话,我觉得判一下null是比较安全的做法。


如果给自己一个“集合为空的情况下不返回null而是返回一个空集合”的原则,就不会有这个问题。

而且即使遇到别人的代码在返回空集合时用null替代,这时候是把别人的代码改简单些好呢?还是把自己的代码改复杂来适应别人的代码好?

这样的话,lz在http://www.iteye.com/topic/841196中的代码最后可以变成这样:
	private List<User> getUserList2(int size) {

		List<User> userList = new ArrayList<User>();

		userList.addAll(getUserListFromSource1(size - userList.size()));
		
		if (userList.size() >= size) return userList;

		userList.addAll(getUserListFromSource2(size - userList.size()));
		
		if (userList.size() >= size) return userList;

		userList.addAll(getUserListFromSource3(size - userList.size()));

		return userList;
	}

而且这代码还有改进的余地。但是没有上下文(对getUserList的调用;还有getUserListFromSourcex的定义),我只能写成这样。


我是完全同意集合为空的情况下不返回null而是返回一个空集合这个惯例的。
但是有以下两种情况会有纠结的地方。
1 底层代码无法改动,加入一个间接层会提高别的程序员的使用成本。
2 大型项目中,一个人所能改动的代码是有范围限制的,对于自己没有改动权限的代码问题,最多提提建议。所以这个重构也只能局限在自己的系统中。
12 楼 zhang_xzhi_xjtu 2010-12-19  
这个方法我记得在代码大全2里面有介绍过,也是一种好的方法。
我的平铺直叙也是这个意思,尽量使代码语言贴近自然语言。

11 楼 baby8117628 2010-12-18  
学习了 这个方法不错哦 翻译法...
10 楼 yeshucheng 2010-12-18  
检验下自己,也是一个不合格的程序员,反省学习
9 楼 yuan 2010-12-18  
tuti 写道
楼上给解释一下

其实蛮简单的,和LZ所说的平铺直叙同一个意思,举个最近写的代码的例子:

首先是描述最直接,最表面的需求:

定义 类:节点服务器
  定义 方法: 启动节点服务器
    方法实现: 
    加载配置文件()
    IPQAM开始广播()
    连接上分发服务器()
    开始监听客户端连接和请求()
    每5秒检查并清除一次死掉的终端连接()
    记录系统启动日志()


然后会发现隐藏在更低一层的需求,发现需要定义加载配置文件,应该由一个专门配置系统的类来做:

定义 类:配置
   定义 方法: 加载
   方法实现:
   xxxxxxxx
   ......


然后是IPQAM的广播:

定义 类:IPQAM
   定义 方法: 广播
   方法实现:
   遍历所有频道
      频道.发送广播()
   遍历结束


然后又发现隐藏在IPQAM中的更底层的需求,需要定义一个频道要处理频道自身的逻辑:

定义 类:频道
   定义 方法: 发送广播
   方法实现:
   UDPSocket.new.connect(ip, port).send('boradcast message', 0)



只要把以上人类语言翻译成相应的代码即可。
8 楼 tuti 2010-12-18  
yuan 写道
有一种很简单实用的方法可以写出较高质量的代码(包括强可读性,绝对的DRY,足够的可扩展):假设式脚本编写法(scripting by assumption)或称一厢情愿式编程法(programming by wishful thinking)。


楼上给解释一下
7 楼 yuan 2010-12-18  
lz在另一帖中说到“平铺直叙”,我想起有一种很简单实用的方法可以写出较高质量的代码(包括强可读性,绝对的DRY,足够的可扩展):假设式脚本编写法(scripting by assumption)或称一厢情愿式编程法(programming by wishful thinking)。
6 楼 yuan 2010-12-18  
tuti 写道
list 就不应该为null

对,除非是第3方库某个本该返回集合的方法返回了个null才需要这么处理(我认为那也是这个库的作者不专业,而且即使是第3方库也可以自己修改)。如果是自己写的方法,从语义上说,这个方法的返回值如果是一个集合,那在该方法运行结果是这个集合为空的情况下,怎么也不应该返回null。1是影响可读性,2是其它每个调用该方法的地方还要处理这个null。返回null是自己给自己找麻烦。

LZ在另一帖中 写道
get底层的服务,别人未必想的那么周全,如果它的注释中,没有声明一定不返回null的话,我觉得判一下null是比较安全的做法。


如果给自己一个“集合为空的情况下不返回null而是返回一个空集合”的原则,就不会有这个问题。

而且即使遇到别人的代码在返回空集合时用null替代,这时候是把别人的代码改简单些好呢?还是把自己的代码改复杂来适应别人的代码好?

这样的话,lz在http://www.iteye.com/topic/841196中的代码最后可以变成这样:
	private List<User> getUserList2(int size) {

		List<User> userList = new ArrayList<User>();

		userList.addAll(getUserListFromSource1(size - userList.size()));
		
		if (userList.size() >= size) return userList;

		userList.addAll(getUserListFromSource2(size - userList.size()));
		
		if (userList.size() >= size) return userList;

		userList.addAll(getUserListFromSource3(size - userList.size()));

		return userList;
	}

而且这代码还有改进的余地。但是没有上下文(对getUserList的调用;还有getUserListFromSourcex的定义),我只能写成这样。
5 楼 tuti 2010-12-18  
list 就不应该为null
4 楼 aoliwen521 2010-11-30  
list.size()<1
这么些我觉得没什么可读性差的。只是少了null的判断。
3 楼 mercyblitz 2010-11-28  
大多数时候关心是集合中 有元素,没有的话,可以不考虑!
2 楼 zhang_xzhi_xjtu 2010-11-28  
IcyFenix 写道
null == a是c/c++年代遗留下来的写法,那时候IDE不会检查条件语句里面的赋值,为了避免写成if(a=null),现在这种写法在Java中是没什么必要了。

java里面这种写法比较有意义的是和常量比较的时候,if(a.equals(CONST_STRING))就没有if(CONST_STRING.equals(a))来的好。后面不会产生空指针异常。如果实在不喜欢判空,建议使用NullObject模式。

同理,下面的list,考虑防御性原则,前面没有判空的话,也经常会写if(list==null || list.isempty())



遗留的写法的原因我是知道的,所以想着大家在java世界中不要这么搞了。

if(CONST_STRING.equals(a))这个是有一定的道理。

IcyFenix 写道
同理,下面的list,考虑防御性原则,前面没有判空的话,也经常会写if(list==null || list.isempty())


这个当然你是对的。但是我的题目是可读性,所以list和null的判断就没有写出来。
我补上了对判null的想法。
1 楼 IcyFenix 2010-11-28  
null == a是c/c++年代遗留下来的写法,那时候IDE不会检查条件语句里面的赋值,为了避免写成if(a=null),现在这种写法在Java中是没什么必要了。

java里面这种写法比较有意义的是和常量比较的时候,if(a.equals(CONST_STRING))就没有if(CONST_STRING.equals(a))来的好。后面不会产生空指针异常。如果实在不喜欢判空,建议使用NullObject模式。

同理,下面的list,考虑防御性原则,前面没有判空的话,也经常会写if(list==null || list.isempty())

相关推荐

    Android_上百实例源码分析以及开源分析_集合打包4

    重构是提高代码可读性和可维护性的重要手段,而设计模式则是解决常见问题的标准化解决方案。在这些实例中,可能涉及单例模式、工厂模式、观察者模式、MVP或MVVM架构模式等,这些都是提升代码质量的关键。 六、...

    Java为改善可读性和灵活性重构代码.pdf

    Java作为一种广泛使用的编程语言,其代码重构是提升这两方面特性的关键实践。本文主要探讨了如何通过使用Java 8的新特性,如Stream API和Lambda表达式,来改善代码的可读性和执行效率。 首先,日志代码的优化是一个...

    重构改善既有代码的设计第2版.pdf

    重构的实践中,识别代码中的“坏味道”至关重要。所谓“坏味道”,是指那些指向代码质量问题的不良迹象。例如,“神秘命名”、“重复代码”、“过长函数”和“发散式变化”等,这些都是代码库中经常需要关注的重构...

    代码重构源码(包含重构前后代码)

    代码重构是一种重要的软件开发实践,旨在改进代码的结构和可读性,而不改变其外部行为。这个压缩包文件“代码重构源码(包含重构前后代码)”提供了面向对象编程领域中的一个实例,具体是对影片出租店租赁程序的重构...

    java重构pdf书籍

    在软件开发领域,重构是提高代码质量和可维护性的关键实践之一。本文将深入探讨“Java重构”的核心概念、重要性和实施方法,特别是基于《重构—改善既有代码的设计》一书的部分内容,该书由Martin Fowler著,侯捷译...

    Ruby-Ruby技巧惯用Ruby重构和最佳实践

    在Ruby社区中,惯用法(idioms)和最佳实践(best practices)是提高代码质量的关键。本文将深入探讨Ruby中的关键技巧、重构方法以及遵循的代码风格指南。 一、Ruby技巧 1. 块和迭代器:Ruby中的块(blocks)和...

    31天重构指南--代码重构(refactoring)

    无论是通过封装集合来保护内部数据结构不受外界干扰,还是通过移动方法来优化类的设计,都是重构实践中的常见策略。在实际项目开发中,开发者应该根据具体情况灵活应用这些重构技巧,不断优化代码结构,提高软件产品...

    Java并发和重构

    在Java编程领域,高并发和重构是两个至关重要的概念,特别是在构建大型项目时。高并发意味着系统能够同时处理...在实践中,不断学习和探索,将这些理论知识灵活应用到实际项目中,是成为一名优秀Java程序员的必经之路。

    C#代码重构31法

    《C#代码重构31法》是对C#编程实践中提高代码质量、可读性和可维护性的31种重构技术的总结。这些重构方法旨在优化代码结构,减少冗余,提高效率,同时也使得代码更加模块化,易于理解和测试。以下是部分重构方法的...

    重构与模式.pdf

    ### 重构与模式的核心知识点解析 #### 一、重构与模式的关系 ...通过学习本书中的理论知识和实践案例,开发者可以更好地掌握重构与设计模式的核心思想,从而在实际工作中更加高效地进行软件开发。

    重构与模式

    书中也可能包含了大量的案例分析,帮助读者理解如何在实践中应用这些理论知识。此外,作者可能还讨论了重构与模式之间的关系,如何在重构过程中发现并引入设计模式,以及如何通过设计模式避免代码退化,从而维持系统...

    31天重构速成

    通过实践这些重构技巧,开发者不仅能够编写出更加健壮、易于维护的代码,还能在团队协作中发挥更大的作用。希望本文的介绍能够帮助读者在实际工作中灵活运用这些技巧,不断优化代码结构,提高软件质量。

    代码重构设计高清版

    书中强调,重构的实践离不开良好的单元测试,测试对于保证重构过程中代码质量具有不可替代的作用。通过确保充足的测试覆盖率,可以极大地减少重构过程中引入错误的风险,使得软件的长期维护变得更加容易。 《代码...

    我的重构学习

    【重构】是软件开发中的一个重要概念,旨在改进代码的结构,提高代码的可读性和可维护性,而不改变其外部行为。在这个过程中,开发者通过一系列小型的修改逐步优化代码,而不是一次性进行大规模的改动,以降低引入...

    重构-改善既有代码的设计

    重构是软件工程领域中的一个关键实践,旨在优化已有代码,提升软件的可读性、可维护性和整体设计质量,而无需改变其外部行为。在Java等面向对象编程语言中,重构尤其显得重要,因为这些语言的复杂性和灵活性为重构...

    C#代码重构.pdf

    在现代软件开发实践中,C#编程语言凭借其强大的功能和面向对象的特性,成为了企业级应用开发的重要选择。随着项目规模的扩大和需求的日益复杂,代码重构成为了维护代码库清晰性和可维护性的关键环节。重构,按照...

Global site tag (gtag.js) - Google Analytics