首先来一段经典的话:聪明的程序员使用50%-70%的时间用来思考,尝试和权衡各种设计和实现,而用30% – 50%的时间是在忙碌着编码,调试和测试。聪明的老板也会让团队这样做。而傻逼的老板,苦逼的程序员会拿出来100%-150%的时间来忙着赶进度,返工,重构,fix 大量的bug… 所以, 越差的团队一般会越忙,而且还忙不完。

  • 软件的精髓在于设计,设计是一件很费大脑的事件。对于软件来说,设计没有完美的,它总是一件需要取舍需要权衡的事,比如:时间换空间,空间换时间,TCP或UDP,同步还是异步,数据冗余还不冗余等等。那怕是一个小小的observers模式是pull方式还是push方式 都需要仔细讨论。这些的东西需要时间和做前期尝试。
  • TDD快速原型和迭代可能会对软件和团队产生负面影响。在一开始,你需要花很大的精力来让你的软件从无到有(做过软件的人都知道,从零开始写代码是很痛苦的事),但是因为你没有想好,先做再说,所以,后期你会面临更多的质量问题而让你需要花更多的时间精力。当然,那些咨询师会让你用持续集成和持续部署这样的方法。但我想告诉你,这并不解决你软件设计的缺陷。举个例子——TDD、迭代、原型只关注功能性需求,其不会关注非功能性需求,比如性能问题,高可用性问题,系统维护问题(模块的耦合问题),等等。而这些问题往往都可以让你的软件设计重新来过。
  • 重构是恶梦,重构应该越少越好。当你维护一个复杂的系统时你会知道重构是一件多么恐怖的事情(参看《重构代码的7个阶段》)。如果一开始没有想好,你要面临的不单单是re-design, re-architect,还要面对时间和人力成本的增加,最难的是你还要面对的是团队士气因为不断的rework而逐渐低落并产生厌倦和懈怠情绪。
  •      所以,如果你能有多一些时间去和客户讨论一下需求和未来可能的变化,去调查一下实现的技术难点和细节,去和其他有经验的人讨论并推敲一下架构和设计,去思考设计上的缺陷,那么,你的coding会变得非常地直,直到你一眼就看到尽头,你的测试案例也会写得非常地好,你会几乎不需要重构,于是,你会在未来少写很多代码,从而你的软件开发会越来越轻松,直到技术开始换代。

    • 首当其冲的一定会是项目的deadline,或是那种你没有活语权的项目。比如做那种“甲乙方合同式的项目”,我把这种项目统一认为是“外包项目”,在这种项目性质下,你很难有话语权。对此,我觉得,1)作为乙方的你还是应该和甲方在项目计划上争取一下,晓之以情,动之以理。2)如果不行,只能在时间、需求范围和质量上做一个权衡。另外,在这种情况下你要找一个方法,把你的压力和痛苦分担给用户和领导。(找到这个方法的前提需要你找到用户和领导他们害怕什么,嘿嘿)
    • 过度设计和纸上谈兵。有人说会不会设计太多,造成过度设计,或是在设计上花太多的时间。这有可能。我上一家公司的一个项目团队就花了1年多的时间来不停不停的开会和做设计,结果release的时候还有1000多个bug。这个问题的原因是,这个团队的设计是在纸上谈兵,开会是开神仙会,讨论的设计都是浮云。所以,设计并不是讨论和思考,还需要去尝试,我认为当你的设计完成的时候,你的骨干核心代码都基本完成了。
    • 我的团队成员水平太差,不会思考。首先,先恭喜你找到一堆码农,当然,这不怪你,这是中国教育和大环境的问题,让人不会思考。对于这样的情况,我有两个建议,1)量力而行,使多大的碗就吃多少饭。2)鼓励思考,那怕那些想法很不靠谱,因为如果不开始,那么将永远不会思考。
    • 必需使用快速迭代。很多公司都在强行上敏捷,他们希望产品越快release越好,而没有充分的时间思考和讨论。对于这种项目,我的建议是,1)找有丰富经验的人来做。2)迭代过程中力求架构和程序逻辑的简单,简单,再简单,力求代码间的高内聚,低耦合。不然,重构的时候你就好玩了。
    • 创业团队必需要快。做得快就是做得好吗?很多时候,不是谁快谁就能笑到最后的。这样的例子太多了。第一个做出来的人并不一定就会占领市场,其很有可能会成为先驱。
    • 有钱的公司才会让团队用更多的时间去思考。错了,你们没有见过有钱的公司,有钱的公司可以招一堆干不成活的人,可以把事搞乱了再新来过,甚至可以把做失败的项目换个名字再重新立项。这些真正的有钱的公司只求快,只求人多,不怕做错决定。像我们这些没钱的人,干什么事都是小心翼翼地,生怕做错决定。

    “品质在于构建过程”吗?(下面原文作者的观点)

         像Unix这样优秀的软件,真正的核心要素到底是什么呢?我的答案是:模型,即人心中的软件。在看得见、摸得着之前,Unix的品质就已经存在于设计者的心中了,他们不会在Unix诞生后惊讶:“哇,Unix的稳定性这么好,7×24小时运行,从来不蓝屏”。模型一定是设计者心中最美的东西,为什么我们阅读操作系统源代码会像进入迷宫一般理不清头绪,而作者自己却觉得头头是道呢?因为作者早已“胸有成竹”,我们以为他几十万行代码敲很辛苦,实际上在他自己看来是按部就班一步步向目标靠近。

    模型是软件的灵魂,存在于设计者的心中,而软件的构建过程正是心中的世界向现实世界逐渐投影。模型可以是完美的,而现实却非完美,或许有时候我们很幸运地到达了,或许有时候我们不得不向现实妥协,改变心中的世界。试图制造灯泡的爱迪生可能会一时找不到熔点极高的发光金属而止步不前,企图制造永动机的人则根本无法实现。在不完美的现实中,我们明明想的是a+b,却敲成了a-b;我们以为某个API可以很快返回,没想到却等了5秒钟,为了不阻塞用户不得不改成了异步。Review、测试等构建过程在一定程度上弥补了现实的不完美,并对模型给予了反馈,但它却无法决定软件的特质。如果设计者心中没有 Unix,即使每个实现环节都层层检验,拥有光速般的反馈,他有怎么能构建出Unix呢?Windows NT内核和Windows 3.1内核的品质差别不在于微软采用了两种不同的构建过程,而在于它们采用了不同的内核模型。灵魂与躯体的差别就在于此!虽然对于普通的软件开发通常有不少成熟的模型供选择,并不需要总是创造自己的模型,但理解模型间的差异,并在设计时选用恰当的模型仍然比采用某种构建过程更加重要。服务器架构采用 Nginx似的异步IO模型,还是采用Apache似的每个请求一个线程的模型远比开发是否采用了TDD更为重要。

         模型的产生是柔性的,主要源于灵感;过程的执行是刚性的,主要源于逻辑。苹果砸在牛顿的脑袋上能砸出万有引力模型,砸在我们脑袋上却只是“哎呦”一声;但一个苹果3元钱,两个苹果2*3=6元钱却在牛顿和我们面前是平等的。迷信灵感和迷信逻辑是两个错误的极端,孔子讲“天下国家可均也,爵禄可辞也,白刃可蹈也,中庸不可能也”,任何一项技能的高级阶段都是关于“度”的艺术。如同光具有波粒二象性,软件开发也具有艺术创作和工业生产的二象性,它包含了柔性的设计和刚性的过程。越是不成熟的前沿领域越表现出柔性特征;越是成熟的一般领域越表现出工业生产的特征。因此,一个以新产品为主的创业型公司应当更注重设计,更需要画家、诗人般的创造型人才;而业务成熟产品稳定的大公司应当更注重过程,更需要踏踏实实的生产线工人似的人才。但在当今这个瞬息万变的信息时代,即使是世界500强的大公司也越来越不稳定,越来越需要创新才能适应,所以即使大公司也不可忽视软件开发的柔性特征。同时,我们也不能迷信模型,过程同样可以成为企业的核心竞争力,比如:富士康。虚虚实实,实实虚虚,其妙无穷。老外做Nike品牌(虚),我们做代工生产(实),高额利润被老外拿走了;我们经营航空公司(虚),老外生产波音飞机(实)高价卖给我们,高额利润又被老外拿走了。靠虚取胜还是靠实取胜?这是个问题^_^

         或许我对于模型柔性的描述不太让人满意,人们多习惯于有章可循的感觉,即便不是死板的知识,起码要找个“在某某思想的指导下”才觉得心里有着落。或许还有人说,模型的确重要,那么我们能不能有一个过程、模式或套路来推导出模型呢?比如,现在非常流行的从用户需求出发的分析模式,即“分析需求,抽象出共性,共性是本质的,本质是稳定的”,这类模式的特点符合人们希望找到套路的心理,一看就明白,容易操作,有成就感。我不否认这类模式的确可以得出可用的软件设计,沿用成熟的模型也未尝不可。但我们应该明白,心中的世界远比现实的世界更广大更美妙。世界是多元的,用户需求、成熟模型等直接可见的东西只代表了某几个维度的视图,设计者心中应当有更多的维度!用户需要一个文本编辑器,是设计者心中的世界决定了他交出的作品是Vi,还是Emacs,亦或是 Notepad。亨利·福特说:“如果你问用户需要什么,他会告诉你一匹更快的马”。汽车源于福特心中的世界,这是一个比只有马的世界更多彩的世界。乔布斯是一个不重视市场调研的人,iPod,iPhone,iPad都不是发个问卷,做个市场调查看看用户需要什么的结果。Apple是乔布斯心中的世界在现实中的投影!所以,请打破“从用户需求出发”,“从模式出发”的迷信,释放你的想象力,让自己心中的世界去包容现实的世界吧!

         每个人心中都有一个属于自己的世界,牛顿运动定律是牛顿心中的世界,相对论是爱因斯坦心中的世界。哪一个才是本来的世界呢?有没有本来的世界呢?本来的世界是什么样子呢?… 老子给我们启示“道可道,非常道”,说得清,道得明,想得到的都不是永恒的真理,所以真理不可言说,对真理的探索永远没有止境……