人月神话
Brooks法则:
“向进度落后的项目中增加人手,只会使进度更加落后。”
“Adding mapower to a late software project makes it later.”
注明的Brooks法则,人月神话一文的核心观点。用人月这一观念来衡量项目进度带有欺骗性。因为他使得项目看上去好像人力和时间是可交换的。如果时间不够,那么增加人手就可以加快进度。但是这个衡量方式忽略了新增加人手的培训时间、队员之间的沟通时间等等因素,结果就是,盲目的增加人手只会导致项目落后。所以问题是,如何使得项目进度不落后;要想使得项目进度不落后,就要制定出合理的项目进度。所以,问题是,如何制定出合理的项目进度。
对于软件任务的进度安排,以下是我使用了很多年的经验法则:
1/3 计划
1/6 编码
1/4 构建测试和早期系统测试
1/4 系统测试,所有的构建已完成
充足的测试时间,只占1/6的编码时间。可惜很多时候我们常常以为编码时间就是全部的时间了,难怪会进度落后。
外科手术队伍
最好的和最差的表现在生产率上平均为10:1,在运行速度和空间上具有5:1的惊人差异!简言之,$20,000/年的程序员的生产率可能是¥10,000/年程序员的10倍。
得出的结论很简单:如果一个200 人的项目中,有25 个最能干和最有开发经验的项目经理,那么开除剩下的175 名程序员,让项目经理来编程开发。
所以说有经验的程序员才是最廉价的劳动力啊
Harlan Mills 的提议提供了一个崭新的、创造性的解决方案2,3。Mills 建议大型项目的每一个部分由一个团队解决,但是该队伍以类似外科手术的方式组建,而并非一拥而上。
也就是说,同每个成员截取问题某个部分的做法相反,由一个人来进行问题的分解,其他人给予他所需要的支持,以提高效率和生产力。
有时候民主和平等也许并非是最好的选择:因为首先在人在智力上、能力上就并不平等。外科手术式的团队其实是延续了早期英雄式的编程风格:主要的程序员决定了项目的大部分内容,而其他人则成为他的副手,帮 助他完成各项细节性的工作。
贵族专制、民主政治和系统设计
现在让我们来处理具有浓厚感情色彩的问题——贵族统治和民主政治。结构师难道不是新贵?他们一些智力精英,专门来告诉可怜的实现人员如何工作?是否所有的创造性活动被那些精英单独占有,实现人员仅仅是机器中的齿轮?难道不能遵循民主的理论,从所有的员工中搜集好的创意,以得到更好的产品,而不是将技术说明工作仅限定于少数人?
为了实现概念完整性,在软件体系结构设计的时候必须实行贵族专制,让少数的架构师来决定整体的架构,普通程序员毫无发言权。但是Brooks为了安慰那些可怜的普通程序员,就告诉他们:其实实现细节也是需要一 样的创造性、同样的新思路和卓越的才华。但是谁都知道,如果能够成为贵族,为何要在制造工艺上费劲心思呢?
画蛇添足
第二个系统是设计师们所设计的最危险的系统。而当他着手第三个或第四个系统时,先前的经验会相互验证,得到此类系统通用特性的判断,而且系统之间的差异会帮助他识别出经验中不够通用的部分。
一种普遍倾向是过分地设计第二个系统,向系统添加很多修饰功能和想法,它们曾在第一个系统中被小心谨慎地推迟了。
这个标题起得让人摸不清头脑,其实值得是第二系统效应(second-system effect)。认识到第二个系统存在的风险,可以让架构师保持警惕,少犯错误。
为什么巴比伦塔会失败?
- 清晰的目标?是的,尽管幼稚得近乎不可能。而且,项目早在遇到这个基本的限制之前,就已经失败了。
- 人力?非常充足。
- 材料?在美索不达米亚有着丰富的泥土和柏油沥青。
- 足够的时间?没有任何时间限制的迹象。
- 足够的技术?是的,金字塔、锥形的结构本身就是稳定的,可以很好分散压力负载。对砖石建筑技术,人们有过深刻的研究。同样,项目远在达到技术限制之间,就已经失败了。那么,既然他们具备了所有的这些条件,为什么项目还会失败呢?他们还缺乏些什么?两个方面——交流,以及交流的结果——组织。他们无法相互交谈,从而无法合作。当合作无法进行时,工作陷入了停顿。通过史书的字里行间,我们推测交流的缺乏导致了争辩、沮丧和群体猜忌。很快,部落开始分裂——大家选择了孤立,而不是互相争吵。
胸有成竹
本章只解决一个问题:一个程序员的生产效率究竟有多高?
对规模平均为3200指令的程序...大约单个的程序员所需要的编码和调试时间为178个小时,由此可以外推得到每年35800语句的生产率。而规模只有一半的程序花费时间大约仅为前者的四分之一,相应推断出的生产率几乎是每年80,000代码行1。计划、编制文档、测试、系统集成和培训的时间必须被考虑在内。因此,上述小型项目数据的外推是没有意义的。就好像把100码短跑记录外推,得出人类可以在3分钟之内跑完1英里的结论一样。
工作量和代码行数不是线性关系,而是指数型关系:
工作量 = (常数)×(指令的数量)^1.5