IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

谈谈年度最佳代码“不管你们信不信,反正我信了”

老赵点滴 2012-08-24 13:09:41 累计浏览 4,088 次
本机暂存

    最近有段十分流行的代码,是从江湖传闻“身怀八蛋”的铁道部发言人王勇平同志的一句名言:“不管你们信不信,反正我信了……这是生命的奇迹……它就是发生了”所引申出来的。这段代码虽然只是在调侃,但是围绕这段代码也产生了一些讨论(如代码风格,编程规范等等),在此顺手记录一下,就当无聊罢。

    这段代码是这样的:

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是一门糟糕的语言,主要原因就是指它的表达能力太差,导致写出来的代码体现不出问题的解决方式,让人们把目光都集中在具体每条语句上了,所谓“见木不见林”。C#等现代语言都在强调“做什么”而不是“怎么做”,语义上就有很大提高了。

    回到目前这个具体问题上,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)一定会被调用一次,但是无所谓其结果是如何,这充分符合天朝某些部门喜欢装摸作样“咨询民意”的状况。

扩展思考

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

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

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

同分类推荐文章

  1. 一个冷门的速查日历方法 (2026-05-27 16:22:00)
  2. Stack Overflow: When We Stop Asking (2026-05-20 21:51:34)
  3. Use Obsidian Sync on Desktop without Installing Obsidian (2026-03-27 00:00:00)

查看更多 开发者 文章 →

建议继续学习

  1. 提高代码可读性的注释技巧 (累计阅读 8,109)
  2. 10个最“优秀”的代码注释 (累计阅读 4,709)
  3. 如何避免重构带来的危险 (累计阅读 4,569)
  4. 代码的缩进和嵌套 (累计阅读 3,266)
  5. 10个最“牛叉”的代码注释 (累计阅读 3,049)
  6. 给代码多留一些空间 (累计阅读 2,233)
  7. PHP最佳实践之PHP标签 (累计阅读 2,211)
  8. 《web前端最佳实践》—HTML篇 (累计阅读 2,106)
  9. 我对“语言之争”的看法:别随便拉我入场 (累计阅读 1,970)