勤于思考才能善于架构

聪明的程序员使用50%-70%的时间用来思考,尝试和权衡各类设计和实现,而用30% – 50%的时间是在忙碌着编码,调试和测试。聪明的老板也会让团队这样作。而傻逼的老板,苦逼的程序员会拿出来100%-150%的时间来忙着赶进度,返工,重构,fix 大量的 bug… 因此, 越差的团队通常会越忙,并且还忙不完。程序员

在如今这个浮躁的时期,再加上敏捷咨询师们念的歪经,他们让人感受上就像是软件产品是能够在很短的时间内高质量的完成的,这令那些管理者们很兴奋,就像巴甫洛夫的条件反射实验中的狗看到了肉就像流口水那样兴奋。他们使用 TDD,快速迭代,不断重构,持续集成直至持续部署的方法在进行软件开发。架构

软件开发真是这样的吗?难道不须要花时间去思考吗?对此,有些观点在 Todd 的《“品质在于构建过程”吗?》以及《Bob 大叔和 Jim Coplien 对 TDD 的论战》中谈到过了。我只想一想表达下面的观点:异步

  • 软件的精髓在于设计,设计是一件很费大脑的事件。对于软件来讲,设计没有完美的,它老是一件须要取舍须要权衡的事,好比:时间换空间,空间换时间,TCP 或 UDP,同步仍是异步,数据冗余还不冗余等等。那怕是一个小小的 observers 模式是 pull 方式仍是 push 方式都须要仔细讨论。这些的东西须要时间和作前期尝试。模块化

  • TDD、快速原型和迭代可能会对软件和团队产生负面影响。在一开始,你须要花很大的精力来让你的软件从无到有(作过软件的人都知道,从零开始写代码是很痛苦的事),可是由于你没有想好,先作再说,因此,后期你会面临更多的质量问题而让你须要花更多的时间精力。固然,那些咨询师会让你用持续集成和持续部署这样的方法。但我想告诉你,这并不解决你软件设计的缺陷。举个例子——TDD、迭代、原型只关注功能性需求,其不会关注非功能性需求,好比性能问题,高可用性问题,系统维护问题(模块的耦合问题),等等。而这些问题每每均可以让你的软件设计从新来过。性能

  • 重构是恶梦,重构应该越少越好。当你维护一个复杂的系统时你会知道重构是一件多么恐怖的事情。若是一开始没有想好,你要面临的不仅仅是 re-design, re-architect,还要面对时间和人力成本的增长,最难的是你还要面对的是团队士气由于不断的 rework 而逐渐低落并产生厌倦和懈怠情绪。测试

因此,若是你能有多一些时间去和客户讨论一下需求和将来可能的变化,去调查一下实现的技术难点和细节,去和其余有经验的人讨论并推敲一下架构和设计,去思考设计上的缺陷,那么,你的 coding 会变得很是地直,直到你一眼就看到尽头,你的测试案例也会写得很是地好,你会几乎不须要重构,因而,你会在将来少写不少代码,从而你的软件开发会愈来愈轻松,直到技术开始换代。优化

我如今在作的项目,花了几乎4个月的时间来作设计,在这个过程当中,咱们反复思考、讨论和权衡若干种实现方法,并尽量地穷举全部的场景和细节以及将来可能的变化(那怕是那些简单的模块),有个模块被重写了至少三次,每次都是写到一半就被推翻重写,咱们整个团队不断地在和其它团队讨论,并在对系统不断地认识中对系统进行简化和优化,并力求达到完美。如今看来,没有贸然使用 Scrum 是明智的。编码

这就好像咱们修路造桥同样,咱们须要花大量的时间勘测地形地质,分析数据,思考可能出现的各类问题(各类天然灾害),评估不一样的设计方案,而不是先尽快建好再说。因此,多一些时间,不是让你多作几回迭代,多完成几个模块,而是可让你少写一些代码,更快的交付一个更好的产品。设计

我相信你会有不少疑问,下面是我以为你可能会有下面的一些观点,让我一条一条来回复:调试

  • 首当其冲的必定会是项目的 deadline,或是那种你没有活语权的项目。好比作那种“甲乙方合同式的项目”,我把这种项目统一认为是“外包项目”,在这种项目性质下,你很难有话语权。对此,我以为,1)做为乙方的你仍是应该和甲方在项目计划上争取一下,晓之以情,动之以理。2)若是不行,只能在时间、需求范围和质量上作一个权衡。另外,在这种状况下你要找一个方法,把你的压力和痛苦分担给用户和领导。(找到这个方法的前提须要你找到用户和领导他们惧怕什么,嘿嘿)

  • 过分设计和纸上谈兵。有人说会不会设计太多,形成过分设计,或是在设计上花太多的时间。这有可能。我上一家公司的一个项目团队就花了1年多的时间来不停不停的开会和作设计,结果 release 的时候还有1000多个 bug。这个问题的缘由是,这个团队的设计是在纸上谈兵,开会是开神仙会,讨论的设计都是浮云。因此,设计并非讨论和思考,还须要去尝试,我认为当你的设计完成的时候,你的骨干核心代码都基本完成了。

  • 个人团队成员水平太差,不会思考。首先,先恭喜你找到一堆码农,固然,这不怪你,这是中国教育和大环境的问题,让人不会思考。对于这样的状况,我有两个建议,1)量力而行,使多大的碗就吃多少饭。2)鼓励思考,那怕那些想法很不靠谱,由于若是不开始,那么将永远不会思考。

  • 必需使用快速迭代。不少公司都在强行上敏捷,他们但愿产品越快 release 越好,而没有充分的时间思考和讨论。对于这种项目,个人建议是,1)找有丰富经验的人来作。2)迭代过程当中力求架构和程序逻辑的简单,简单,再简单,力求代码间的高内聚,低耦合。否则,重构的时候你就好玩了。

  • 创业团队必须要快。作得快就是作得好吗?不少时候,不是谁快谁就能笑到最后的。这样的例子太多了。第一个作出来的人并不必定就会占领市场,其颇有可能会成为先驱。

  • 有钱的公司才会让团队用更多的时间去思考。错了,大家没有见过有钱的公司,有钱的公司能够招一堆干不成活的人,能够把事搞乱了从新来过,甚至能够把作失败的项目换个名字再从新立项。这些真正的有钱的公司只求快,只求人多,不怕作错决定。像咱们这些没钱的人,干什么事都是当心翼翼地,生怕作错决定。

因此,构建一个优秀的系统,我以为须要如下几点:

  1. 构建一个好系统的愿景。若是相关人员(经理,小组负责人,程序员)只是想混饭吃,就注定没法构建优秀的系统。

  2. 理解业务需求。虽然不可能像业务人员同样熟悉全部细节,但总体上应该超过业务人员。若是可能,要让全部程序员都真正地理解业务。正如乔布斯,他基本上不会去询问客户的需求,由于他对“需求”的理解远远超过了普通大众。惟有如此,才能建造出杰出的系统。只有真正理解了需求之后,才能在系统设计中加入将来可能须要的接口和模块(而不是过分设计),才能在开发过程当中“抵制”客户的不合理需求改动要求,才能避免种种业务陷阱,开发出客户喜好的功能。

  3. 尽可能利用已有的主流软件平台,减小开发。在软件开发过程当中没有“银弹”。即便对优秀的程序员来讲,要减小BUG,也必须作大量的测试和BUG修订。这意味着惊人的时间和成本。成熟的商业软件系统虽然价格高昂,但其质量也远远高于通常公司里IT部门开发出来的东西。本身开发的系统,复杂性一旦到达某个级别,每每会事实上不可维护。这不只仅意味着直接的维护成本,更会对公司的业务形成严重破坏和阻碍。应该在成熟的系统里,经过少许二次开发来实现须要的功能。

  4. 分阶段实施。不要试图实现全部的功能,不要试图构造完美系统。业务需求中,总有一部分相当重要。实现了这一部分,就能为业务人员节省超过80%的时间。通常都应该迅速构造这样一个1.0版本,并让业务人员尽早在上面工做。等系统稳定之后,再去构造2.0版本。在系统的构造过程当中出现的绝大部分新需求或者需求改动,都应该放入下一个版本。

  5. 代码: "轻耦合", "模块化", "易读"。代码模块相互要独立,每一个模块功能必须单一,并且一样的功能不该该在不一样的模块中重复实现。除了上面列出的这几条,易读性就是最重要的。在99%的场合下,性能一类的要素都不须要考虑。合理的系统架构自己就已经解决了性能问题。合理的程序代码(包括SQL语句)都足够快。代码中嵌入的注释应该不多----优秀的代码自己就能解释逻辑。注释通常应该集中在模块的开头部分,阐述业务逻辑,帮助程序员理解业务需求。在一个应用系统中,为了把局部性能提升10000倍而牺牲代码可读性,通常是不可接受的。(除了一些极其罕见的特例)

  6. 代码: 垃圾进,垃圾出。通常来讲,对任何一个模块,都不该该去检测传入参数是否合法,更不该该试图去处理非法数据。惟一须要保证的是,合法的传入数据将产生合法的传出数据。这也是为了防止"过分设计",为了不垃圾数据,必须在源头上卡住。避免垃圾数据进入系统。

  7. 代码: 只有异常,才抛出异常。能够预见的错误,都不该该致使异常(exception)

相关文章
相关标签/搜索