Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

《软件架构师应该知道的97件事》——Richard Monson-Haefel #10

Open
thzt opened this issue Aug 9, 2016 · 0 comments
Open

Comments

@thzt
Copy link
Owner

thzt commented Aug 9, 2016

积累一批满意的客户,选择切合实际的技术解决他们的难题,让他们乐于推荐你,才是最好的履历。
信誉远胜过时髦的编程技巧和流行的范式。
掌握最新的技术趋势,与时俱进固然重要,但不能让客户为此买单。

Simplify essential complexity, diminish accidental complexity.
简化根本复杂性,消除偶发复杂性。
根本复杂性,指的是问题与生俱来的,无法避免的困难。
偶发复杂性,是人们解决根本复杂性的过程中衍生的。
系统设计的初衷是解决根本复杂性,但是解决方案本身带来了新的问题。
许多软件框架和厂商提供的“解决方案”都表现出偶发复杂性和症状。
解决特定问题的框架很管用,但设计过度的框架增加的复杂性反而超过了它应该缓解的复杂性。
在大型软件项目中,关注根本复杂性,消除偶发复杂性,抽丝剥茧制订解决方案,才是真正的挑战。
应该尽可能选择源自实际项目的框架,警惕那些象牙塔里的产品;
分析方案中有多少代码直接用来解决业务问题,有多少只是用来实现用户与应用之间的交互;
谨慎使用软件厂商在幕后推动的方案,它们并非一无是处,但往往包含偶发复杂性;
要量体裁衣,为问题制订“合身”的解决方案。
架构师的责任在于解决问题的根本复杂性,同时避免引入偶发复杂性。

Seek the value in requested capabilities.
分析客户需求背后的意义。
顾客和最终用户提出的所谓需求,只是他们心目中可行的解决方案,并不是问题唯一的解决途径。
架构师可以通过询问客户,分析客户要求的功能和需求的真正意义,定位真正的问题,从而提出比客户的建议更好,成本更低的解决方案。
通过关注问题的真正含义,理顺需求的轻重缓急,把最优价值的需求摆在第一位。

One line of working code is worth 500 of specification.
一行可运行的代码比五百行架构说明更有价值。
架构师往往容易被抽象的架构所吸引,沉迷于设计过程。
架构师必须时刻关注目标,牢记设计只是达成目标的手段,不是目标。
我们的目标是可工作的代码,对软件项目而言,忽略这一点就是灾难。
没有天生完美的设计,所有的设计都要在实现的过程中逐步完善。

提前关注性能问题。
在项目周期的最后阶段才关注新能问题,会导致我们错失大量历史信息,这些信息包含性能变化的细节。
如果性能是架构设计的重要指标,就应该尽早展开性能测试。
当系统出现性能问题时,你只须检查最近的变化,而不用全盘考虑整个架构。

Business drives
业务目标至上。
按照通常的业务惯例,在启动一个软件项目之前,应当制定计划,明确对投资回报率的预期。
架构师必须把握这个预期,并估计该项目的商业价值,避免作出错误的技术决策,造成经费超支。
架构师必须通过沟通协调,既保护软件架构,又坚持业务目标,既允许开发人员制定微观(技术)决策,又设法避免他们参与制定业务决策。
如果技术决策脱离了业务目标和现实条件的约束,则无异于用宝贵的稀缺资源进行高风险的投机。
用业务目标驱动项目开发,才能保证软件开发团队的长远利益。

Simplicity before generality, use before reuse.
先确保方案简单可用,再考虑通用性和复用性。
通过经验提炼的简单方案,远胜不切实际的通用性。
并非所有人都需要通用性,愿意为它掏钱,具体情况要具体分析,有针对性的解决方案才有价值。

导致项目失败的原因很多,最常见的是中途临时调整进度。
当然,调整也可能指延长项目期限,或者增加项目资源,那就没什么好操心的了。
最怕的是时间不变,任务量增加;或者任务不变,截止日期提前。
一般人有一种错误的观念,认为加快进度可以降低成本,提高交付速度。
实际上,改变计划会引发产品质量问题,而解决产品质量问题的代价更高。
最后的结果是成本不降反升,通常项目就是这样失败的。
首先通过协商尽量维持原定进度,保证产品质量;如果必须加快进度,可以尝试去掉一些不重要的功能,留待后续版本发布。
显然这需要提前做好准备,包括谈判策略和说服他人的技巧。

妄想实现所有需求,只会产生脆弱的,一无是处的架构。

Use uncertainty as a driver.——Kevlin Henney
重视不确定性。
当你面对两种可能性时,应该仔细考虑设计中存在的不确定性。
不确定性可以促使你推迟决定,收集更多的信息;促使你用分隔和抽象的方式来降低设计决策对系统的影响程度。
架构属于设计范畴,但并非所有的设计都属于架构之列。
架构代表了那些形成系统的重要设计决策。
其重要性由变更决策的代价来衡量。
优良的架构能够从整体上降低设计决策对系统的影响程度,糟糕的架构则会突出它。
设计决策对系统的影响程度,用变更设计决策需要付出的代价来衡量。
了解出现两个合理选择之外还存在其他选择,比决策结果本身更有价值。
当你积极的与同事在白板前争论不同的可能性时,当你对着代码反复琢磨而无法决定采用哪种实现方式时,
当新的需求或对需求的新解释质疑现有的实现方式时,说明你碰到不容易确定的情况了。
这时要设法利用分离或封装将决策和最终依赖于决策的代码隔离开。
做不到这一点,代码就会杂乱无章,仿佛一个紧张的应聘者,试图用模棱两可,含糊其辞的方式回答没有把握的问题。
当你在不同的系统开发路线之间举棋不定时,不要急于做出决策。
推迟决策,直到掌握更详实的信息,以便做出更可靠的决策。
但也别太迟,要赶在这些信息失效前利用它们。
架构和过程相互交织,所以架构师应该在开发周期中促成那些注重实证的架构方法,并设法引出反馈。

不要轻易放过不起眼的问题。
组织团队一起来想办法管理风险。
不要轻易放过“不妥”的感觉。
多和客户交流,经常与团队沟通,看看你是不是真的了解他们的想法。
自己的盲点自己难以觉察。忠言虽然逆耳,却是你最宝贵的财富。

Reuse is about people and education, not just architect.
有这样一种观点,认为设计优良的框架,细致考虑并精巧实现的架构自然会被人们重复利用。
事实上,即便是最精美,最优雅的框架,可复用性最高的系统,也必须满足下面的条件才可能被复用。
大家知道它们存在。
大家知道如何使用它们。
大家认识到利用已有资源好过自己动手。
如果大家找不到可复用的资源,或者不知道如何使用这些资源,人的天性就会发挥作用。
他们会自己动手实现,到头来吃亏的还是架构师。

Try before choosing.
先尝试后决策。
平庸的架构师可能会收集手边的信息,斟酌酝酿一番,然后从象牙塔里颁布解决方案让开发人员实现。
架构师应该持续关注那些马上要制订的决策。
架构师只需组织协调制订决策的过程即可,不必自己做出决策。

缺乏业务领域知识的架构师不能顺利的理解业务问题,无法把握业务目标和业务需求,也就难以设计有效的架构来满足需求。
架构师的角色任务在于理解业务问题,业务目标,业务需求,并设计技术架构来满足它们。
掌握业务领域知识将有助于架构师选择合适的架构模式,更好的制订对未来的扩展计划,适应不断变化的产业趋势。
理解具体的业务目标也有助于你设计有用的架构。
作为架构师,你要始终理解公司的业务目标,并确保架构支持这些目标。

如果把编写代码看成设计行为,而不是生产行为,我们就能采用一些已经被证明有效的管理方式。
这些方法过于用于管理具有不可预测性的创新工作。
如果软件行业希望从这些方法中获益,我们必须记住,程序设计属于设计范畴,而不是生成范畴。

越复杂的架构越难成功实现,缩小项目规模通常会降低架构的复杂性,这是架构师提高成功几率最有效的途径。
抓住真正需求。
分而治之。
设置优先级。
尽快交付。

Context is king.
具体情境决定一切,根据它设计尽量简单的解决方案。
架构是在具体情境下作出的一系列决策,用以实现一组通常相互制约的需求。
由于需求常常相互制约,所以设计架构的关键不是贡献新内容,而是忽略那些不必要的需求。
设计架构的过程其实就是做出明智决策的过程。
别让团队成员被各种设计理念束缚住,鼓励大家具体情况具体分析,努力找出最简单的解决方案。

架构师安排任务时,应该时刻考虑所有开发人员的性格特点。
从这个角度来看,架构是一个指南,为不同性格的团队成员安排合适的任务,让大家在工作过程中相互学习。
如果大家有机会充分磨合,相互适应,就能轻松化解各种难题。

有多少软件架构师还把自己的工作看成单纯的技术工作?
难道我们不曾周旋于各种利益集团之间,充当和解人,中间人,甚至仲裁者的角色?
有多少人对待工作时,还是一副清高的知识分子态度,不愿正视这份工作必须和人打交道?
要想成为伟大的建筑师,优雅丰富的心灵远比聪明才智重要。
哪种架构师更容易脱颖而出?
是那些天资聪明,对技术烂熟于心的人,还是那些宽容,文雅,高尚的人?你更愿意与谁共事?
维护自己设计的系统远比“修剪爬山虎”麻烦。
你有勇气删掉有缺陷的代码吗?还是假装没看见?最近你推翻过自己的设计吗?
最后一次见到让你赞不绝口的架构是什么时候?你是否立志要让自己的程序给别人带去愉悦?
建筑师首先应该是伟大的雕塑家,或者伟大的画家,否则他不过是个建筑工人。
你的架构是否蕴含适当的艺术的成分?用组件搭建的系统,有没有借鉴绘画的造型和质感?
有没有从雕塑的姿势和平衡中汲取灵感?是否考虑了适当留白的重要性?

别忘了,真正决定程序流程的不是调用栈,而是用户需求。
向令人怀念的调用栈架构告别吧,忘掉那些程序员绝对程序流程的日子,准备好应付随时出现的乱序事件,不断根据具体情境调整策略。
别再抱怨现实世界带来了麻烦,不妨从中寻找解决问题的灵感。

保护好开发人员,不要让他们卷入到不那么重要的工作中。
无论使用的是何种过程,要确保它们的设计目的是消除障碍,而不是增加障碍。

记录软件架构决策理由的文档,长期有用,又无须为之付出过多维护精力,具有很高的投资回报价值。
定义软件架构,就是要在质量属性,成本,时间以及其他各种因素之间,做出正确的权衡。
此份文档应能向你自己,经理人员,开发人员及软件的其他利益相关者,清楚阐明选择某种解决方案,而非另外一种的原因,包括其中做出的权衡。
无论使用何种形式和格式,此文档都应回答以下基本问题:“我们做了什么决策?”“为什么这样决策?”
“我们还考虑过哪些解决方案?为什么没有采用?”
它逼着你明确说出理由,有助于确保基础是扎实稳固的。
如果相关条件发生变化,需要对决策重新评估,它可以作为一个起点。

Assumpation is the mother of all screw-ups.
臆断是把事情搞砸的根源。
软件架构的最佳实践表明,应该记录下每个决策背后的理由,当这一决策包括权衡时尤须如此。
在更为正式的方法中,记录下每个决策的上下文是很常见的做法,这些上下文包含了促成最终决策的各项“因素”。
这种做法颇有价值,因为列出这些因素有助于强调架构师所持的假设,这些假设会影响到软件设计中的重要决策。
事实和假设是构建软件的两大支柱,务必确保软件的基石坚实可靠。

如果发现自己试图把最喜欢的模式硬套在不适用的问题空间上,那么你也许是模式病患者。
不要让你对模式的喜欢变成了迷恋,进而引入超出实际所需的过于复杂的解决方案。
设计模式不是魔法,在解决方案中使用它并不能确保获得好的设计,它们只是对常见问题的可重用的解决方案。
人们记录发现的模式,是为了避免后来重新发明车轮。
当问题出现时,我们能识别出来,并恰当的应用设计模式,这才是我们的任务。
应当保持对系统的洞察力,提供切实有效的商业解决方案,使用模式解决适用的问题才是最重要的。

应用程序的支持和维护都不应该是事后才考虑的事情。
由于应用程序超过80%的生命周期都是在维护上,在设计时就应该多多关注支持和维护的问题。

CAP定理,在分布式系统中通常期望的3个特性,一致性,可用性和分区容错性是无法同时获得的。
相反我们应该问,为什么必须要持有这些特性?这样做可以获得什么好处?何时才期望拥有这些特性?如何才能打破系统成规以达成更佳的效果?
永远不要放弃质疑,因为架构设计的教条往往从根基上削弱了交付能力。

Make sure the simple stuff is simple.
确保简单问题有简单解。
软件架构师解决了很多非常困难的问题,但也会去解决一些相对容易的问题。
对于简单的问题,不要使用复杂的解决方案,这个建议听上去显而易见,但要遵循却并不容易。
架构师展示才华的机会多的是,只要有真正的难题出现,总有这样的机会。
在往前做出超越系统实际需求的架构决策时,不妨自问,照此实现之后,如果再退回去会多么困难。

作为架构师,主要目标应该是创建可行,可维护的解决方案,当然,也一定要能够解决当前的问题。
其中,要知道解决方案中什么是可行的,就要求架构师拥有相关知识,能够实际参与到解决方案的开发活动中去。
因此我建议,如果是你做的系统设计,你也应该能够编程实现自己给出的设计。

我们对项目所做的每一个决策——无论是与技术,过程还是与人相关——都可以看做一种投资形式。
投资是和成本联系在一起的,成本并非单纯只有货币一种形式。
之所以进行投资,是相信它们最终能带来回报。
老板发员工薪水,是期望此项投资将会对他们的事业产生积极的影响。
开发团队决定遵循某种专门的开发方法学,是期望它能够给团队带来更高的生产力。
选择投入一个月的时间重新设计应用程序的物理架构,是相信这将有利于长期运维。
回报率,也成为投资回报率(ROI,Return On Investment),是衡量投资是否成功的指标之一。
虽然不必用经济收益来衡量一切事物,但投资总应该产生增值。
将架构决策视为投资,并将相关的回报率也一并考虑在内。
在判断每个决策选项是否务实或恰当时,这种方法很有用。

一切软件系统都是遗留系统。
即使系统十分前沿,采用了最新的技术开发而成,但对接手它的下一个人而言,它也会是遗留系统。
在今天,软件很快便会过时,这已经成为软件的天然属性。
如果系统能够作为产品存活下来,哪怕只有数月时间,都必须承认,负责维护工作的开发人员肯定要对软件进行缺陷修复,这是不可避免的。
假设有另外不同的团队打开了代码库,他们很容易便可了解到当前在做什么,这是优秀架构的基础。
无需对架构进行过度的简化或为之准备面面俱到的记录文档,好的设计会以多种方式说明自身。
依赖关系十分丑陋的架构,其行为往往看起来就像是笼中的困兽,到处受限。

If there is only one solution, get a second opinion.
起码要有两个可选的解决方案。
对于某个问题,如果只考虑了一个解决方案,那你就有麻烦了。
如果对手头的问题只有一个解决方案,这意味着将没有进行折衷权衡的余地。
如果事实确实如此,别费力气,赶紧让更有经验的架构师助你一臂之力。

Understand the impact of change.
理解变化的影响。
优秀的架构师能够深刻理解变化带来的影响,这种影响不仅限于彼此隔离的软件模块之间,而且包括人与人之间,以及系统与系统之间。
管理变化并非架构师的职责,但架构师要确保变化是可控的。
架构师必须评估变化对项目范围,时间和预算各个方面产生的影响,并准备好花较多时间在那些受影响最大的区域。

Shortcuts now are paid back with interest later.
现在走捷径,将来付利息。
在项目开发初期走捷径,可能会以日后付出高昂的维护费用为代价。
除了避免在开发初期走捷径,发现有不当的设计决策时就要尽快修正,这点也很重要。
设计不当的特征可能会成为后续特征的基础,将来需要花费很高的成本来更正。
作为架构师,一定要坚持成本还很低廉时就动手,搁置越久,为之付出的利息也将越高。

If you design it, you should be able to code it.
架构师要以自己的编程能力为依托。
不要在设计里使用自己没有亲自实现过的模式,不要使用自己没有用之写过代码的框架,不要使用自己没有亲自配置过的服务器。

Stable problems get high-quality solutions.
稳定的问题才能产生高质量的解决方案。
现实世界中的编程,并不是要去解决别人给你的问题。
最好的架构师不是要去解决难题,而是要围绕难题开展工作。
架构师要能够将四处弥漫的软件问题圈起来,并画出其中的各种边界,确保问题有稳定的,完整的认识。
如果问题是稳定的,那么问题解决之后,就永远不会再来烦恼你。

Don't be clever.
弃聪明,求质朴。
不要追求聪明,尽量用最浅显易懂的质朴方法,恰如其分的进行设计。
小聪明会诱导我们在软件开发中使用奇技淫巧。

你的客户并不是你的客户,客户的客户才是你的客户。
如果你的客户的客户赢了,你的客户也就赢了,这意味着,你也赢了。
如果发现你的客户疏忽了他们的客户的需求,你要指出来,并说明原因。
如果你的客户有意无意的忽视他们的客户所看重的重要事项——这种情况常有发生——那么,请考虑放弃这个项目。
明知是糟糕的主意,但你如果竟然也同意接手,这无异于在谋杀客户的客户。
需求收集会议不是项目实现讨论会议,只要牢牢关注你的客户的客户的需求即可。
这样你才能产出客户真正需要的东西,而不只是他们声称自己所需要的东西。
我们也不配称得上真正关爱我们的客户,如果不能更为关爱他们的客户。

设计是一个不断发现的过程。
设计是在不断变化的世界中持续进行探索试验的过程,只有接受这点,我们才能明白,设计过程也必须保持灵活性和连续性。
事物发展总会出人意料。

Choose frameworks that play well with others.
选择彼此间可协调工作的框架。
软件框架是系统的基础,在选择时,不仅要考虑每个框架自身的质量和特性,也要关注共同构成系统的各个框架之间是否能和谐共处。
另外还要关注,随着系统不断演化,是否能方便的向其中加入新的软件框架。
即,必须选择彼此之间没有重叠,而且开放,简洁,精专的框架。
每个框架或者第三方库,如果既能专注解决某个独立的逻辑域或关注面,又不会侵入其他必需框架的领域或关注面,那是最好不过了。
系统应该由多个相互独立的框架组成,其中每个框架都精专与各自的领域,但同时又非常简洁,包容和灵活。
尽量不要使用“无所不能”型的框架,它们依靠的是囊括一切,独霸天下的理念,这样会大大增加框架间重叠的概率。

着重强调项目的商业价值。

Don't be a problem solver.
不要急于求解。
有时候,没有解决方案才是最好的解决方案。
有许多软件问题根本就不需要解决。
它们之所以看似问题,是因为我们只关注它们的表面症状。
由于架构师往往习惯于迅速进入问题解决模式,我们常常忘记,或者根本就不知道,改如何去审视问题本身。
我们应该学会像长焦镜头一样,不断的拉近放远,以确保正确的锁定问题,而不是只一味的接受别人给出的问题。
在需求面前,我们不应该成为被动的储存罐,像糖果盒一样时刻准备着掏出各色各样的聪明点子。
不要立即着手去解决摆在面前的问题,而要看看自己是否可以改变问题。
问问自己,如果没有这个问题,系统架构会是怎样的?
有时业务问题确实需要得到解决,但有时,或许并非那么迫在眉睫。
还是先想想,如果根本不存在这个问题,这个世界又将会怎样。

我们是工具的制造者,我们制造的系统,一定要能够帮助人们——通常是其他人——做事,否则就失去存在的意义,我们也将无法从中获得报酬。
人们使用工具来达到目标,工具只不过是达到目的的一种手段。
好的工具会让用户感到很“上手”,具有“轻巧便利”的特性。

找到并留住富有激情的问题解决者。
我们要找的,是那种具备解决问题的能力和激情的开发人员。
工作中使用的工具肯定会改变,真正所需的,是那种无论技术如何变化,都善于攻克各种难题的人才。
即便能背出某个API的全部方法,也不能说明此人具备解决问题的才能和激情。
好的开发人员对工作充满激情。

业务和软件都是活生生,会变化的实体。
业务需求可能会因新近收购的业务伙伴和营销战略而迅速变化。
应该领悟到我们构建的产品是柔韧的,并且围绕产品的需求很可能会发生变化。
对软件而言,更多的需要以“对工作进行计划,不断调整计划”的方式处理。

没有永不过时的解决方案。
Today's solution is tomorrow's problem.
今天的解决方案会成为明天的问题。
今天做出的选择,在未来很大程度上会是错误的。
如果今天做出的任何选择,在未来会是糟糕的选择,那就不要操心将来要怎样的东西——只要选择能满足当前需求的最佳解决方案就行了。
“分析瘫痪”是今天架构师们碰到的问题之一,此问题最大的归因,是试图去猜测对未来而言最好的技术。
为当前选择一项好技术已属困难,要选择在未来也切合可用的好技术只会徒劳无功。
仔细查看目前业务所需为何,以及当前技术市场提供的东西。
从中选择能够满足当前需求的最好解决方案,因为别的东西,不仅对明天是错误的选择,而且,对今天就已是错误的选择。

For the end user, the interface is the system.
对最终用户而言,界面就是系统。
如果产品的用户交互体验质量让人无法忍受,那么无论产品在技术上如何先进或具有开创性,都会造成让人无法忍受的印象。
用户界面是架构的重要组成部分,但往往也是被忽视的部分。
在早期阶段就让用户界面专家参与其中并贯穿整个产品开发阶段,能确保用户界面和产品浑然一体,使最终产品整洁优美。
当产品还在beta阶段时,架构师应仔细观察由真实的最终用户完成的用户交互测试,并将他们的反馈纳入最终产品中。
随着时间变迁,技术会发生变革,产品特性也会不断增加,产品的用法也会因此经常发生变化。
架构师应确保,随着架构变化而变的用户界面也要能够反映用户的期望。
用户交互应是整个产品架构的目标之一。

Great software is not built, it is grown.
优秀软件不是构建出来的,而是培育出来的。
环境和需求的变化不可避免,你和你的系统都要学会适应变化。
设计尽可能小的系统,帮助成功交付,并推动它向宏伟的远景目标不断演化。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant