`

[转载]谈谈2011年度最佳代码

 
阅读更多

 

原文: http://blog.zhaojie.me/2011/08/from-the-code-of-no-matter-you-believe-it-or-not.html

作者:赵劼

 

这段代码是这样的:

 

try
{
    if (you.believe(it) == true || you.believe(it) == false)
    {
        I.believe(it);
    }
}
catch (Exception ex)
{
    throw new Exception("It's a miracle!");
}
finally
{
    it.justHappened();
}

 代码与原文的对应关系不言自明,从命名风格上看,我们默认其为Java代码。话题主要是围绕在if条件的写法上。

书写风格

先来看看它的书写风格问题。我说这段代码不是老鸟写的,因为老鸟不会把一个布尔表达式跟true和false直接判断,而会写成:

 

if (you.believe(it) || !you.believe(it))

 于是有朋友提出,把布尔表达式跟true或false相比较来的更清晰一些,我表示这话并没有什么道理,因为这种读代码的方式是把视角停留在“数据”层面上:一个布尔表达式返回了布尔型的“数据”,于是把它和另外一个“数据”进行比较。如今的编程都在不断强调“语义”,“语义”的清晰才是真的清晰。我说Java是一门糟糕的语言,主要原因就是指它的表达能力太差,导致写出来的代码体现不出问题的解决方式,让人们把目光都集中在具体每条语句上了,所谓“见木不见林”。javascript,ruby,python等现代语言都在强调“做什么”而不是“怎么做”,语义上就有很大提高了。

回到目前这个具体问题上,if里面的语义是“you.believe(it)”的返回结果,而不是它的值与另外一个布尔常量的比较结果。其实这个观点我从初中搞信息学竞赛时就被老师不断强调,今天我同样咨询了同事,他也赞同我的观点。如果您还继续坚持这种写法不太清晰的话,我只能说“这只是不适应而已,要让自己适应这类写法”,很多人还觉得LINQ不清晰呢,小学生还觉得高中数学的解法不清晰呢。

还有朋友认为,作为编码规范,应该要求这么写,例如:

 

if (10 == i)

 就是说,把常量写在比较操作的左边,并认为“这样更有普遍意义”。其实这也没有必要,这个习惯是从C语言时代遗传下来的“陋习”。在C语言里,如果把常量写在比较右侧,并且一不小心把“比较”操作符(两个等号)写成“赋值”操作符(一个等号),也可以编译通过,但是结果却大不相同,这给错误排查也会带来许多麻烦。但是,在如今的语言里已经比C语言做的安全多了,所以没必要制定这种规范。把一种语言的标准带入另一种语言不叫做“有普遍意义”,只是多余。

代码含义

然后要谈的便是代码与那句话的“映射”关系了,再来仔细读一下这个if子句:

 

if (you.believe(it) || !you.believe(it))
{
    I.believe(it);
}

 从“需求”上来理解,我认为代码应该保证if内部的代码一定会执行。那么现在这个需求肯定会满足吗?不一定,因为you.believe方法可能是有副作用的:如果它第一次调用返回false,而第二次调用时返回true,则if内部的代码就会整段略过,这显然不是铁道部王发言人的意图。因此,有同学提议代码应该是这样的:

 

 

if (true || you.believe(it))

 这么做的确可以忽略you.believe(it)的结果,因为它已经被短路了根本不会执行。可能它也能满足需求,但我想更合理的做法可能应该是:

 

 

if (you.believe(it) || true)

 这段代码与之前的区别就在于you.believe(it)一定会被调用一次,但是无所谓其结果是如何,这充分符合天朝某些部门喜欢装摸作样“咨询民意”的状况。

 

扩展思考

最后再来一道扩展思考题吧:有人把“你爱,或者不爱我,爱就在那里,不增不减”写成了一段java代码:

 

if (you.Love(me) || !you.Love(me))
{
    love++;
    love--;
}

 有人说,这段代码的if条件本身应该被编译器优化掉,因此会直接执行if内部的代码。还有人说,if内部的代码也会被编译器优化掉。您怎么看,为什么呢?

 

分享到:
评论
35 楼 laiguolong 2012-09-03  
看来程序本身也是一脚可以踏两船的么!!
34 楼 javaboy8282 2012-07-19  
程序员难得开心!不错!自娱自乐!
33 楼 nodejs 2012-06-09  
呵呵。太有特色了。
32 楼 步青龙 2012-02-03  
有新意,不错。。。。。
31 楼 Kim_T 2011-12-01  
牛人阿......年度最佳代码非你莫属
30 楼 JeffreyZhao 2011-08-11  
whb1984 写道
引用
我说Java是一门糟糕的语言,主要原因就是指它的表达能力太差,导致写出来的代码体现不出问题的解决方式,让人们把目光都集中在具体每条语句上了,所谓“见木不见林”。C#等现代语言都在强调“做什么”而不是“怎么做”,语义上就有很大提高了。


这段话什么意思? 楼主能否深入讲解下?

表达能力差,就是跟C#,Scala,Ruby,Python等现代语言相比咯,实现相同的功能需要大量代码,可写性和可读性都差一截。

http://www.infoq.com/cn/articles/guardian_scala
29 楼 richard_2010 2011-08-11  
bitlanghen 写道
最后的love代码没有被优化,贴汇编代码
  0:	new	#2; //class You
   3:	dup
   4:	invokespecial	#3; //Method You."<init>":()V
   7:	astore_1
   8:	new	#4; //class Me
   11:	dup
   12:	invokespecial	#5; //Method Me."<init>":()V
   15:	astore_2
   16:	aload_1
   17:	aload_2
   18:	invokeinterface	#6,  2; //InterfaceMethod Person.love:(LPerson;)Z
   23:	ifne	36
   26:	aload_1
   27:	aload_2
   28:	invokeinterface	#6,  2; //InterfaceMethod Person.love:(LPerson;)Z
   33:	ifne	44
   36:	getstatic	#7; //Field java/lang/System.out:Ljava/io/PrintStream;
   39:	ldc	#8; //String love
   41:	invokevirtual	#9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   44:	return

18和28都有方法的调用,Me和You都实现了Person接口,接口含有love方法


字节码 != 汇编代码
28 楼 isupercci 2011-08-10  
不管你信或者不信,我反正是信了,如此而已,会心一笑就行了
27 楼 bitlanghen 2011-08-10  
GoodWell 写道
真能扯啊  一句领导的话引起了你们的年度最佳代码   可笑的是有人解释的有理有据的 真他妈的无语了  这就是我们程序员?

认真你就“叔”了
26 楼 GoodWell 2011-08-10  
真能扯啊  一句领导的话引起了你们的年度最佳代码   可笑的是有人解释的有理有据的 真他妈的无语了  这就是我们程序员?
25 楼 justjavac 2011-08-10  
bitlanghen 写道
最后代码的解答参加博客
if (you.Love(me) || !you.Love(me))
{
    love++;
    love--;
}

http://bitlanghen.iteye.com/blog/1144459

看过了,写的不错,最好加上博文链接,方便访问:http://bitlanghen.iteye.com/blog/1144459
24 楼 stormtoy 2011-08-10  
if (you.believe(it) || true) 


天朝逻辑
23 楼 bitlanghen 2011-08-10  
最后代码的解答参加博客
if (you.Love(me) || !you.Love(me))
{
    love++;
    love--;
}

http://bitlanghen.iteye.com/blog/1144459
22 楼 Jekey 2011-08-10  
  
21 楼 bitlanghen 2011-08-10  
最后的love代码没有被优化,贴汇编代码
  0:	new	#2; //class You
   3:	dup
   4:	invokespecial	#3; //Method You."<init>":()V
   7:	astore_1
   8:	new	#4; //class Me
   11:	dup
   12:	invokespecial	#5; //Method Me."<init>":()V
   15:	astore_2
   16:	aload_1
   17:	aload_2
   18:	invokeinterface	#6,  2; //InterfaceMethod Person.love:(LPerson;)Z
   23:	ifne	36
   26:	aload_1
   27:	aload_2
   28:	invokeinterface	#6,  2; //InterfaceMethod Person.love:(LPerson;)Z
   33:	ifne	44
   36:	getstatic	#7; //Field java/lang/System.out:Ljava/io/PrintStream;
   39:	ldc	#8; //String love
   41:	invokevirtual	#9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   44:	return

18和28都有方法的调用,Me和You都实现了Person接口,接口含有love方法
20 楼 abc123nqr 2011-08-10  
寓意深远,长见识了。希望还能看到更经典的
19 楼 beck1986 2011-08-09  
Zhuangbility!
我很好奇,是什么业务场景需要判断你一个方法执行两次的结果。
我想说,出现这种情况是你设计有问题。
并且,这种逻辑完全可以用其他更好的方式展现。
18 楼 jamsir 2011-08-09  
 
if (10 == i)

这个例子不怎么样,不直观,如果用
if (35 == i)
这样才经典嘛
17 楼 szmq2 2011-08-09  
我可不可以理解为java高端玩家的装逼游戏
16 楼 justjavac 2011-08-09  
guoapeng 写道

这个应该用代理模式
if (you.believe(it) == true || you.believe(it) == false)  
{  
  new RailwayMinistryProxy(I).believe(it);  



 

相关推荐

Global site tag (gtag.js) - Google Analytics