说明:本博文最早发布在本人的新浪博客上。
《软件架构师应该知道的97件事》是一本协作方式写出来的书,英文原文免费发布在O’Reilly的维基上,《97 Things Every Software Architect Should Know – The Book》,感觉很不错,说的在理,都是该做的事情。我尤为喜爱的部分摘录如下:
- 草率提交任务是不负责任的行为(Commit-and-run is a crime. by Niclas Nilsson)
草率提交任务会破坏正常的工作流程,是不负责任的行为。这是开发人员节省时间的常用伎俩,但最终浪费的是他人的时间,性质恶劣。
沉下心来改善系统的生产效率,缩短流程,避免各行其是,才能缩短开发时间。采取一切可行的措施,例如运用模拟方法、降低依赖性、细致划分系统模块,等等。总之要杜绝一切草率提交任务的念头。
- 程序设计是一种设计(Programming is an act of design by Einar Landre)
杰克里夫斯(Jack Reeves)在《什么是软件设计?》这篇文章里提到,在软件工程里,与传统行业的设计文档具有相同地位的只有源代码。软件的生产则是自动化的,由编译器、构建工具和测试代码共同完成。
如果把编写代码看成是设计行为,而不是生产行为,我们就能采用一些已经被证明有效的管理方式……我所指的是敏捷的产品管理方法和精益生产方法,比如SCRUM,它们关注如何为客户实现最大的投资收益。
- 控制项目规模(Scope is the enemy of success by Dave Quick)
殊不知规模越大,项目失败的可能性越大,这一点常让人始料不及。规模扩大一倍,失败的可能性往往会增加十倍。为什么呢?请看两条前人的经验:(1)凭直觉判断,只要花两倍的时间或资源,就能完成两倍的工作任务。但是历史告诉我们直觉不可靠,这里不存在简单的线性关系;(2)估算与准确的科学计算相差甚远,所以产品特性实现起来常常比预期的要困难。
那么有哪些策略可以帮助我们缩小和控制项目的规模呢?(1)抓住真正的需求;(2)分而治之;(3)设置优先级;(4)尽快交付。
敏捷方法的倡导者提倡开发“最简单有用的东西”。越复杂的架构越难成功实现。缩小项目规模通常会降低架构的复杂性,这是架构师提高成功几率最有效的途径。
- 软件架构的道德责任(Software architecture has ethical consequences by Michael Nygard)
软件架构师的每项决策(例如设置必填项和规定流程),都限制了用户可以做什么,不能做什么。这比制定法律容易得多。即使用户嫌这些“必填项”和“规定流程”麻烦,也找不到法院受理他们的诉讼。
虽然设计必填项从表面看并无不同之处,但实际上是架构师在强迫用户接受自己的意图。必填项迫使用户准备更多的信息,否则无法开始工作。用户不得不把资料逐个记录在记事贴上,知道所有的数据收集齐全。这个过程中常常会丢失数据,耽搁工作,让人非常沮丧。
损人利己是不道德的行为,哪怕程度很轻。成功的软件产品会影响数以百万计的用户,而用户不得不无奈地接受架构师的每项决策,所以永远不要忽略了架构师对用户的影响,这是我们勇于承担责任、减轻用户负担的动力。
- 挑战假设,尤其是你自己的(Challenge assumptions – especially your own by Timothy High)
软件架构的最佳实践表明,应该记录下每个决策背后的理由(参考《记录决策理由》,Record your rationale),当这一决策包含权衡(性能 vs 可维护性,成本 vs 上市时间等)时尤须如此。在更为正式的方法中,记录下每个决策的上下文是很常见的做法,这些上下文包含了促成最终决策的各项“因素”。这些因素,可能是功能性或非功能性需求,但也可能只是决策者认为重要的“事实”(或道听途说…),如技术约束、现有技能政治环境因素等。
很多时候,这些假设往往是基于“历史原因”、主观判断、开发人员的视野、因循守旧(FUDs),甚至“走廊里听来的一些小道消息”。
事实(fact)和假设(assumption)是构建软件的两大支柱。务必确保软件的基石坚实可靠。
- 先考虑原则、公理和类比,在考虑个人意见和口味(Prefer principles, axioms and analogies to opinion and taste by Michael Harmer)
个人意见和口味上的分歧,常常会演变为政治性的争论,其中就会出现动用权威来赢取争论的可能。然而,只要底层原则十分清楚,分歧便可为深入的理性探讨开辟道路,同时又规避了与个人有关的问题。可能根本无需牵扯到架构,便可解决分歧。
在架构实现及整个过程中,原则和公理也确保了架构上的一致性。一致性通常会成为问题,尤其在跨越多种技术并将长期存在的大型系统中。清楚的架构原则,能够使那些不熟悉某项特别技术或组件的人,明白其中的缘由,更透彻地理解他们本不熟悉的技术。
- 一切软件系统都是遗留系统(Your system is legacy, design for it. by Dave Anderson)
即使系统十分前沿,采用了最新的技术开发而成,但对接收它的下一个人而言,它也会是遗留系统。必须应对这种情况!在今天,软件很快便会过时,这已经成为软件的天然属性……这引出如下几个问题:(1)清晰性;(2)可测性;(3)正确性;(4)可跟踪。
假设有另外不同的团队打开了代码库,他们很容易便可了解到当前在做什么,这是优秀架构的基础。
在生产环境中的系统行为也会说明其设计,举例而言,依赖关系十分丑陋的架构,其行为往往看起来就像是笼中的困兽,到处受限。替那些要进行缺陷调试的(通常都是较为初级的)开发人员着想一下吧。
- 命名要恰如其分(A rose by any other name will end up as a cabbage by Sam Gardiner )
而事实上在此时就应该明白,这其中一定有问题:如果都不知道一个东西应该叫什么,那你肯定不知道它究竟是什么。如果你不知道它究竟是什么,那么你也肯定不能坐下来为它编写代码。
当然,名称无非只是一种指代。一旦相关人都知道,在这里名字只是一个名字,那么便失去了可以赖之前进的设计隐喻……所谓设计,就是要去实现各种意图,例如,快速、廉价、灵活,而名字便是用于承载和传达这些意图的。
如果无法给出合适的命名,那么也就无法继续编程。如果发现自己需要多次更改命名,那么最好停下来,知道弄清楚要做的究竟是什么。
【kaverjody】这是我最喜欢的一篇,无法确定名称,就好像是古时候说“师出无名”,不伦不类的实现、代码只会是成为一个四不像,为万人耻笑而已。名字这么个小小的事物却代表着其背后对它自身使命、任务的澄清,也解释了它在整个系统中所起到的作用。
- 客户的客户才是你的客户!(Your Customer is Not Your Customer by Eben Hewitt )
没错,你的客户确实不是你的客户。你的客户的客户,才是你的客户。如果你的客户的客户赢了,你的客户也就赢了。这就意味着,你也赢了。
需求收集会议不是项目实现讨论会议。除非所涉问题非常明确或大家都已理解,不要让客户使用与具体实现相关的术语。……那么该如何在这类会议上坚持这样的原则呢?只要牢牢关注于你的客户的客户的需求即可。
我们也不配称得上真正关爱我们的客户,如果不能更为关爱他们的客户。
- 不要急于求解(Don’t Be a Problem Solver by Eben Hewitt)
架构师和开发人员因此学会了迅速进入问题解决模式。但是有时候,没有解决方案才是最好的解决方案。有许多软件问题根本就不需要解决。它们之所以看似问题,是因为我们只关注它们的表面症状。
我们应该学会像长焦镜头一样,不断地拉近放远,以确保正确的锁定问题,而不是只一味地接受别人给出的问题。
不要立即着手去解决摆在面前的问题,而要看看自己是否可以改变问题。问问自己,如果没有这个问题,系统架构会是怎样的?这样的自问自答,可能最终帮你找到更加优雅可行的解决方案。
我们必须戒除“问题解决迷恋症”。
【kaverjody】我还记得以前的一位外国同事曾经和我说,他工作中感受到中国同事的一个普遍问题就是,太快就跳到了solution(解决方案),但却没有去仔细地审视问题本身:这是不是真正的问题?真正的问题是什么?问题的根由在何处?有几种可选的解决方案?等等。而方向错误所带来的危害往往更大。
- 没有永不过时的解决方案(You can’t future-proof solutions by Richard Monson-Haefel)
今天的解决方案会成为明天的问题。
根本不可能存在”永不过时(future-proofing)“的系统。不管现在做出什么样的架构决策,这种选择最终会过时。现在用的很酷的编程语言,最终将变成明天的COBOL。今天的分布式框架,将会变成明天的DCOM。
如果今天做出的任何选择,在未来会是糟糕的选择,那就不要操心将来要怎样的东西——只要选择能满足当前需求的最佳解决方案就行了。
仔细查看目前业务所需为何,以及当前技术市场提供的东西。从中选择能够满足当前需求的最好解决方案,因为别的东西,不仅对明天是错误的选择,而且,对今天就已是错误的选择。
- 优秀软件不是构建出来的,而是培育起来的(Great software is not built, it is grown by Bill de hora)
除了易于招致额外的复杂性和惯性,前期便要设计庞大的系统,意味着项目会变得更为大型,而大型项目更可能会失败,更可能无法验证,更可能脆弱不堪,更易产生不必要和无用的产物,成本可能更是无比高昂,而且,更易招致不利的政治因素。
确保软件系统能够演化和具备适应性的最好办法,是从一开始就做到这样。引导系统进行演化,意味着要从一个小型但可用的系统开始,这个系统是预期架构的一个可用的子集,亦即最简单的可行实现。
设计尽可能小的系统,帮助成功交付,并推动它向宏伟的远景目标不断演化。……注意,不要把这种演化方式和削减需求、规范混乱和生产废品这样的做法混淆在一起。