软件工程、代码注释以及其他

自从1970年NATO会议以后,软件工程这个词就正式进入了软件开发领域,并且占据了越来越重要的地位。不可否认,软件工程确实为软件开发带来了一些作用,但是软件工程的缺陷也是很明显的。其中涉及到好几个方面的核心问题,现在暂时无法解决。
第一个问题是人的问题。
人不是机器,虽然有时候经过比较严格的训练在某些时间段可以表现得跟机器差不多,但毕竟不是真正的机器,这就是说,人的输入和输出并不是恒稳的。这是软件工程没有办法解决的硬伤。
第二个问题是软件度量问题。
这个问题到现在为止,可以说根本没有一个实质性的解决方案。关于软件的复杂度,软件开发的工作量,开发中的软件的完成度,软件的价值等等方面,从来没有一个可供哪怕仅仅是用来参考的模型。我知道有很多复杂性模型,但是他们都要求都软件很熟悉。这个要求就会转化为强制软件开发过程中必须有分析阶段和设计阶段,这是代价高昂的过程,后面我还会进一步提到。软件开发的工作量一般的认为是跟复杂度正相关的。但是,工作量还涉及到很多别的方面,要评估它是一个系统工程。完成度显见的也是与工作量和复杂性相关的,同时也与开发组织方式相关。现代的软件工程一般采用里程碑的方式来衡量工作完成度,我后面详细描述这方面的问题。
软件的创造性和不可重复性本质也是一个棘手的问题。
软件是迄今为止人类所能创造的最复杂的系统。这意味着,软件开发一般情况下需要一定程度的创造性,在很大程度上不是重复前人的经验,而是发现新的知识并且表达他们。就算不需要发现新的知识,我们也知道,只是的表达式很复杂的,为了让这些表达的知识真正具有价值,需要考量的因素很多,其中就牵扯到软件用户。不同的用户需要不同的知识表达,能够融入他们的知识体系中的知识表达。这就是创造性的。
现在开始描述里程碑的引入以及其固有的问题。
上面说到,为了度量软件工作的完成度,我们引入了里程碑的概念。
里程碑是这么一回事:
如果你驾车从西苑到西直门,在路途上的时候,你想知道你走了多少路程了,还差多少路程就到了,很简单,看看窗外的风景就知道了,为什么?你认识路呗。假设你要从西苑到密云水库,你不认识路,那你怎么知道已经走了多少了呢?哦,对了,路标,里程碑。就是它。看看里程碑上的里程数,并且你知道总里程数的话,那么恭喜你,你知道你走了多少了。
软件工程的里程碑也是借用这个概念,不过它不再是竖在路边标着里程的石柱,而是竖在概念世界中的某种象征物,一旦我们在现实的软件世界碰到了这种象征物,我们就知道我们已经走到某种程度了。
呵呵,我们通过上面的描述,似乎都能感觉到某些问题。是啊,这个象征物怎么出现的?项目的管理者怎么知道某种象征物一定会存在?甚至我们连我们的软件是什么(走多远)都不清楚呢?上面说到软件的创造性本质,也说到软件度量的困难,没有这些基础,我们怎么能奢望我们的里程碑是有意义的?
另外,里程碑的问题还在于它跟时间的结合上。我们上面说到,人是复杂的,输出是不恒定的,所以一旦标志物(里程碑)和时间结合起来,就意味着我们需要估计并确定人的输出。同时,上面说到的软件度量问题仍然造成障碍。
好的好的,我知道,里程碑仍然可能有意义,不是吗?我们通过长时间的分析问题,设计方案,我们对于问题已经有了相当程度地把握和直觉,所以我们可以小心翼翼的设置一些标志物了。是的,这个我是承认的。但是我们也要承认,很少有人能够真正准确的预测未来,就算问题我们已经很清楚了,我们也不能认为情况不会发生变化,事实上,在实现阶段发现问题并修正方案是很常见的情形。
所以,设定里程碑需要前期大量的投入,并且可能会随着情况的变化随时修正。
当然了,如果里程碑是完成这个极限,那么就只有一个里程碑了,跟没有是一样的,它省去了投入,也不用修正,但是不能用于指导我们的实践。
现在,你应该可以自己做决定了,是否需要和值得设定里程碑?
现在我们是不是进入死胡同了?有没有别的办法?
我觉得有,我提一个。
我们人类解决复杂问题的基本思路是两个:抽象和分而治之。
抽象是忽略掉我们暂时不想看到的,以便于我们能够从整体上把握。在软件开发的实践中,我们的实现必定要和无数的细节打交道,所以抽象不是我们的武器,那就只有分而治之了。分而治之是把一个大问题分解成几个关系相对较弱或者界限很清晰的几个小问题。对于小问题,我们还是有把握的。针对一个小问题,我们可以采用上面提到的极限时的里程碑,也就是完结。这样,我们就提出了一个可以设置好多里程碑(依赖于我们分成几个小问题了),并且能够检验我们任务的完成度的一个粗略但是相对低代价和好衡量的方法了。
其实这就是所谓的FDD,特征驱动开发。

关于代码注释。我这儿指的是写在代码中的,而不是其他别的。
先说一个我认为凌驾于任何软件开发原则之上的原则。DRY。不要重复你自己。不管是开闭原则(OCP)也罢,父子替换原则(LSP)也罢,甚至更高层次的高耦合低内聚原则也罢,统统都要向DRY让步。当然,这是我自己的观点。你完全可以不采纳。
其实,DRY是一个非常简单的原则,就是不要有重复。说的文绉绉一点,就是说要让你的决策集中化。当然,这两个说法并不是直接等价,而是推理等价的。
这个原则如果坚持的话,你会发现其实可以产生OCP LSP甚至高耦合低内聚等等原则相同的的效果。自己试验一下就知道了。
现在开始说代码注释。
代码注释是什么大家都很清楚,但代码注释应该干什么似乎没有共识。在重构的实践中,认为注释是坏气味,表示需要重构,我持有相同的观点。但是还有一些问题,那就是,究竟应不应该出现注释?任何注释都不应该出现?没有任何一种注释是必要的?甚至JavaDoc所要求的那些关于参数和返回值的基本注释?是的,它们是不必要的,它们的出现违反了DRY,你的代码应该比你的注释更清楚地说明他们的意义。而关于整体风格和习惯用法的信息,不应该出现在所有相关的 code中,而是出现在一个单独的文件中,由于它不是某些特定code相关的,而是所有code相关的,相信你也会觉得每一个code里面出现一份不爽,是的,如果这样又违反了DRY原则。那么,违反了DRY有什么后果呢?最基本的后果就是修改的重型化。由于你有重复,你必须在所有重复的地方修改,如果你有一处没有发觉,那么,不一致就发生了。代码和注释的不一致比没有注释要糟糕的多。有时候,我们确实需要注释,那我们也应该用一个工具生成他们。因为说到底它们跟代码是重复的。
哈哈,我听见有人这样子笑了。是啊,我为什么要让我的注释跟代码是重复的?我不能给出一些别的方面的跟代码无关的注释?是的。必然有点关系,但是关系要求多弱呢?如果我们read code的时候,突然出现了一段注释,而我们看的莫名其妙,我们是什么感受?作者在这儿夹这段注释的意义究竟“是什么”,为什么他要这样写?或许有一些东西我还没有理解?我还得仔细想想这究竟是什么意思?
另一个说法是注释可以给出一个摘要。对,我对摘要非常感兴趣,可我为什么要在代码中看到它们?如果我在阅读代码,我就是想知道所有的“细节”而不是摘要。所以为什么我们不把摘要放在单独的文件中?让我可以自然的顺流的读下来,而不是时时被一些细节绊倒?
还有的说法是注释给出一些关键实现的提示。这个很好,真得很好,它们是细节相关的,似乎应该放在代码中,可是,我们为什么不想想,为什么我们需要这些关键提示?为什么我们不能重构代码让代码给出这些提示?为什么我们要重复这些信息(一次是代码,一次是注释)?看看重构的书会打消你的这个想法的。
再有就是说,注释可以给出背景信息,我们知道,背景信息非常重要,可是在代码中表现不出来,所以我们用注释给出。呵呵,这个是一个非常值得反驳的例子,其实,这也是以前我对注释的作用的最基本的理解。我以前就这么做。让我们来看看为什么这有问题吧。
关于这个问题,最关键的是什么是背景信息?对于不同的人来说,所需要背景信息显然不同,你写的背景信息只对某类人或者某个人有效,那就是说,你的这些注释对大多数人来说是障碍和绊脚石,而不能提供理解的钥匙。

我再说说软件工程中流行的一些神话。
最出名的是那个关于错误发现时机的神话,它是这样说的,错误发现的越早,纠正它的代价越低,反之,发现的越晚,纠正它的代价越高。似乎能举出很多这样的例子。可它是错的。如果真的是这样,我们似乎被要求尽可能快的犯错误。这是荒谬的。
其实,对于错误发现的时机,强烈的依赖于两个因素,一个是人的因素,一个是问题的结构的因素,对于问题的结构,这个可以认为是客观的,不可改变的,可以改变的只有人自己了。对人自己来说,有两方面影响这个时机,一是自己的知识结构,一是解决问题采用的步骤。我们知道,这些问题要么是很难解决,要么是运气相关。所以很难把握。
我们再次回到错误发生后解决的代价这个问题上。
发生了错误,我们解决它,代价是什么?真的是时间相关的?这个结论无论正确与否,都不是直觉可得的。实际上,解决错误的代价是我们重新理解原来解决方案的代价。因为,我们发现了错误,那就是说,我们对问题有了新的看法和认识,我们有了新的解决方案,我们要理解原来的解决方案,然后给出改造的办法就解决了错误。这里面真正缠人的只有理解原来的解决方案。如果我们知道我们原来的解决方案,而且现在我们知道了错误,我们解决问题似乎并不需要费多少力气。既然如此,那么我们怎样加强我们的记忆,提高我们对原来解决方案的认识?重复是一个办法。这是一个不怎么消耗时间的脑力体操,你可以在很多情况下重新思考原来解决方案的整体或者某个细节。中国有句古话是:好记性不如烂笔头,如果你习惯于从纸面上获得信息,那么你就多做笔记,多复习。但是,请注意,这是与注释无关的,至少与我们上面说的那种形式的注释无关。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值