架构师的97种习惯
草率提交任务是不负责任的行为
以维护流程通畅为重,以浪费他人时间为耻。要做到这一点,务必在系统内晚上的自动测试功能,纠正开发人员的行为。
沉下心来改善系统的生产效率,缩短流程,避免各行其是,才能缩短开发时间。采取一切可行的措施,例如运用模拟方法、降低依赖性、细致划分系统模块,等等。总之要杜绝一切草率提交任务的年头。
业务目标至上
在商业化的背景下开发企业应用,架构师必须成为业务部门和技术部门之间沟通的桥梁,周旋调解,兼顾双方的利益,同时用业务目标来驱动项目开发。业务目标和实际的开发条件应该成为架构师主持制定决策的参照系统。
按照通常的业务惯例,在启动一个软件项目之前,应当制定计划,明确对投资回报率的预期。架构师必须把握这个预期,并估计该项目的商业价值,避免作出错误的技术决策,造成经费超支。每当要权衡取舍时,无论是与业务部门讨论是否应该实现某项功能,还是与开发团队讨论技术上的设计与实现,都应该把高投资回报率当作目标。举例来说,架构师必须谨慎地站在业务团队一边,拒绝开发团队选用价格不菲的软件和售后服务成本过高的技术。
用业务目标驱动项目开发,才能包装软件开发团队的长远利益。
先确保解决方案简单可用,再考虑通用性和复用性
普遍存在一个问题,它们的设计一味强调通用性而不考虑具体应用,导致出现许多令人困惑的可选项和不确定因素,这些功能常常不是被闲置,就是被误用,甚至毫无价值。多数开发者开发的是专用系统,无限制的通用性对™的帮助不大。通过经验提炼的简单方案,远胜过不切实际的通用性。
如果存在多个可实施方案难以取舍,“先简单后通用”原则可以成为最终的评判标准。挑选基于具体需求的简单方案,放弃鼓吹通用性的复杂方案。
提炼通用性可以使我们更加接近问题的本质,通过分析已有案例可以获得清晰、简洁、有依据的规律和方法。
虽然很多架构师重视通用性,但这样做是有前提条件的。并非所有人都需要通用性,愿意为它掏钱,具体情况要具体分析,有针对性的解决方案才有价值。
架构师应该亲力亲为
称职的架构师应该通过示范领导团队。他能胜任团队的所有工作,从网络布线到配置构建流程,从编写单元测试到担任测试工作。对技术缺乏全面理解的架构师,充其量只是一个项目经理。团队成员通常具备深厚的专业知识,很难想像不懂技术的架构师如何赢得大家的信任。众所周知,架构师是业务团队与技术团队直接的接口人,他必须理解各种技术问题,无锡频繁求助他人,才能代表技术团队发言。同样,架构师还要懂得业务知识才能督促技术团队满足业务需求。
架构师就像航班的主驾驶员,看起来不是很忙碌,但他经验丰富,持续地见识着情况,一旦发现异常随时采取行动。项目经理(副驾驶员)负责日常的管理工作,将架构师从烦琐的杂务和人事管理中解脱出来。架构师对项目的交付和质量负有最终责任,没有威信很难展开工作,威信与项目的成败密切相关。
称职的架构师应该至少熟练掌握一种专业工具(例如一种IDE),它们应该身先士卒。按道理说,软件架构师应该会用IED,数据库架构师应该会用ER工具,信息架构师应该会用XML建模工具。而一位技术/企业架构师,起码应该熟练运用哥哥层次的工具,从使用wireshark检测网络流量,到利用XML Spy给复杂的财务信息建模--无论简单还是复杂的都该掌握。
避免进度调整失误
有一种错误的观念,认为加快进度可以降低成本,提供交付速度。为了缩短交付时间,开发人员常常被要求加班,甚至放弃“不太重要的计划任务“(例如单元测试);就算交付时间不变,也可能被要求增加额外的功能。架构师应该不惜一切代价拒绝这类要求,提醒那些提出要求的人,改变计划会带来以下问题:
仓促决定的进度会导致拙劣的设计、蹩脚的文档,可能引发质量问题,导致用户拒绝验收;
仓促完成的代码,会直接导致最终产品的bug数量增加;
紧张的测试进度会导致测试不充分,直接增加测试中可能出现的问题;
以上几项都会引发产品质量问题,而解决产品质量问题的代价更高。
最后的结果是成本不降反升,通常项目就是这样失败的。
作为架构师,你难免会遇到类似的情况,为了确保项目顺利进行,应该迅速采取行动表明立场。首先通过协商尽量维持原定进度,保证产品质量;如果必须加快进度,可以尝试去掉一些不重要的功能,留待后续版本发布。需要谈判策略和说服他人的技巧。
取舍的艺术
架构师应该明白鱼和熊掌不可兼得的道理。世上不存在十全十美的设计--既具有高性能,又具有高可用性;既高度安全,又高度抽象。有一个真实的历史事件,软件架构师应该烂熟于心,在与客户或同事沟通时能派上用场。这就是瓦萨号战舰的故事。
软件架构师应该从这个故事中汲取教训,避免在工作中重蹈覆辙。妄想实现所有需求(像瓦萨号一样),只会产生脆弱的、一无是处的架构。
不要轻易放过不起眼的问题
下面方法有助于克服这些消极因素:
组织团队一起来想办法管理风险。例如用跟踪bug的方法来跟踪风险。让大家都参与识别风险,然后进行跟踪,知道风险解除。为风险划定等级,每当风险状态发生变化,或者有新情况发生时,重新评估风险的等级。这样做可以避免主观因素的影响,同时有助于提醒团队定期重新评估风险。
如果你的观点不被大家接受,应该设法寻找更容易让他们理解的表达方式。鼓励大家重视反对意见,寻找更理性的讨论方式。
不要轻易放过“不妥”的感觉。如果还没有足够的证据证明“不妥”,请设法寻找最简单的方法来证明。
多和客户交流,经常与团队沟通,看看你是不是真的了解他们的想法。用户需求记录优先级列表之类的工具虽然可以帮助你完成工作,但是无法替代定期与客户沟通的作用,你更需要的是开发的思想。
自己的盲点自己难以察觉。忠言虽然逆耳,却是你最宝贵的财富。
让大家学会复用
1.大家知道它们存在
在公司内推广可复用资源的办法有很多。规模较大的团队可以通过Wiki页面和RSS订阅来更新信息,或者利用E-mail通知大家版本库的更新情况。
2.大家知道如何使用它们
掌握如何利用已有的资源需要一定的技巧和培训。当然,某些天才的开发人员和架构师能够和代码、设计产生“共鸣”,它们的理解能力和理解速度令人印象深刻,甚至可怕。
3.大家认识到利用已有资源好过自己动手
一般人倾向于自己解决问题,不愿意寻求别人的帮助。它们觉得向别人请教问题是一种浅薄,甚至无知的表现。
使用“一千英尺高”的视图
在架构图里,系统是由若干个小方框组成的,方框之间的连线代表着各种含义:依赖关系、数据流、共享资源(例如总线)等。这种图好比从飞机上俯瞰地面风景,我们称为“三万英尺高”的视图。另一种典型的视图是源代码,好比站在地面上看大地,两种视图都无法充分展现软件的质量,前者太抽象,而后者细节太多,以致我们看不清整个架构。很显然,需要一个介于两者之间的视图--“一千英尺高”的视图。
“一千英尺高”的视图提供的信息来自恰当的层次,囊括了大量数据和多种度量标准,例如方法数、类扇出数和圈复杂度。具体的视图与特定的质量属性密切想过,例如可视化的依赖关系图、在类的级别上显示多种度量标准的柱状图,以及复杂的、关联多个输入值的复合标准视图。
类扇出数:类扇出数原来是半导体电路中的概念,用于表示输出逻辑门可驱动同类型输入逻辑门的数量。在软件领域用来描述类之间的耦合度的一种代码度量,其数值表示一个类依赖的其他类的个数。
圈复杂度:又称为条件复杂度,它通过测量源代码中的线性无关路径数来衡量诚信的复杂度。
纯粹靠手工绘制这些视图,并且保持它们与软件同步是不现实的,我们可以借助工具直接根据源代码创建视图。虽然有专门绘制视图的商业工具包,但是利用提取数据的小工具,加上通用的绘图工具包,也可以非常容易地绘制出想要的视图。
checkstyle是一款检测Java代码规范的软件
InfoViz是一款数据表转换成可视图形的工具
GraphViz是一款现实结构化信息的图形工具
先尝试后决策
创建一个应用需要作出许多决策。有些决策涉及挑选框架和函数库,而另一些则需要选择特定的设计模式。
架构师应该持续关注那些马上要制订的决策。假设团队中有多位开发人员,并且代码所有权属于整个开发队伍,架构师可以在决策时间点到来之前,要求几个开发人员商量出解决方案,尝试一段时间。当决策时间点临近时,召开会议比较不同解决方案的优点和弊端。通过尝试对解决方案已经有了共识。架构师只须组织协调制订决策的过程即可,不必自己作出决策。避免造成误工和损失。
掌握业务领域知识
高水平的软件架构师不仅要懂技术,还要掌握问题空间对应的业务领域知识。缺乏业务领域知识的架构师不能顺利地理解业务问题,无法把握业务目标和业务需求,也就难以设计有效的架构来满足需求。
架构师的角色任务在于理解业务问题、业务目标、业务需求,并设计技术架构满足它们。掌握业务领域知识将有助于架构师选择合适的架构模式,更好地制订针对未来的扩展计划,适应不断变化的产业趋势。举例来说,有些业务领域(保险)本身的特点很适合采用面向服务的架构方法,而其他业务领域(金融)更适合采用基于工作流的架构方法。掌握领域知识,可以帮助我们挑选出最能满足客户具体需求的架构模式。
理解具体的业务目标也有助于你设计有用的架构。架构需要包括若干抽象层,用来降低合并业务组件的难度。如果客户计划通过大规模的在线产品展示来增加市场份额,那么持续高可用性就是关键的质量属性。
我认为成功的架构师不仅拥有丰富的、通过实践积累的技术知识,同时也对特定的业务领域知识了如指掌。它们能够自如地运用企业高管和用户熟悉的行业术语与他们沟通。这反过来又增强了软件架构师对自己工作的信心。
程序设计是一种设计
程序设计是学习的过程。将程序设计--或者更准确地说,软件开发--看作发现和学习的过程,而不是生产和建造的过程。这种观点从根本上促进了软件实践方法的发展。
让开发人员自己做主
多数架构师都是从开发人员干起的。架构师在决定如何构建系统的工作中肩负着新的责任,也拥有更大的权力。刚上任的架构师会发现很难沿用以往的工作方式开展新工作,总是迫切地觉得自己还需要大量的练习才能胜任管理开发人员的工作,让大家实现设计。应该给予团队成员足够的自主权,让他们发挥自己的创意和能力,这对你和团队来说都是件好事。要善于倾听各种抱怨并设法加以改进。编写测试代码的人遇到了麻烦?请改进借口降低依赖性。你知道哪里需要抽象,哪里不需要吗?请理清问题所属的领域。你知道构建系统的正确顺序吗?请制定项目计划。开发人员在使用你设计的API时,是不是总犯同样的错误?请修改设计方便同事理解。大家真的理解你的设计吗?请沟通来表达清楚。你知道哪里需要实现可伸缩性,哪里不需要吗?请和客户一道学习他们的业务模型。
如果你想出色地完成架构师的工作,是不可能有空闲去干预开发人员的。虽然你应该密切注意团队是否在按计划实现系统,但是没必要站在背后监视大家。当你发现同事遇到麻烦时,可以主动给出建议。但更可取的做法是创造良好的氛围,让大家主动想你征求意见。这件事如果做好了,不但能确保架构成功实现,而且能让团队成员把智慧和创意发挥到极限。
时间改变一切
选择值得投入精力的工作
这种要求对软件架构师来说有些棘手。问题和任务总是给定的,我们没有选择的余地,不是吗?并非这么简单。首先,我们常常误认为自己无法左右交给我们的任务。其实我们可以,只不过这需要我们从舒适的技术领域里迈出来。漂亮的解决方案搭配正确的任务,才能经受时间的考验。
简单原则
人们反复念叨KISS(keep it simple,stupid)原则,把它挂在嘴边,却没有身体力行地去遵守。大家不遵守是因为觉得没必要。当我们回顾一年以前甚至更早的项目时,几乎都会惊诧自己当初的做法。如果有机会再做一次,我们会以更简单的方法完成。这就是时间的作用,时间让我们的行为变得可笑。越早醒悟越好,别再自以为是,用时间的放大镜仔细研究简单原则的真正涵义吧。
设立软件架构专业为时尚早
有人急于讲软件架构的设计工作专业化,与传统的建筑学专业平起平坐。起因似乎是某些软件架构师不满足于同事和老板的肯定,希望自己的成就获得更正式的认可。要知道建筑学专业直到19世纪末才确立,在此之前建筑这个行当已经存在了几千年。
控制项目规模
项目规模越大,项目失败的可能性越大,这一点让人始料不及。规模扩大一倍,失败的可能性往往会增加10倍。
为什么?看两条千人的经验:
1.凭直觉判断,只要花两倍的时间或资源,就能完成两倍的工作任务。但这里不存在简单的线性关系。例如,比较四个人组成的团队和两个人组成的团队,前者花在沟通上的时间肯定超过后者的两倍。
2.估算与准确的科学计算相差甚远,所以产品特性实现起来常常比预期的要困难。
有哪些策略可以帮助我们缩小和控制项目的规模呢?
抓住真正的需求。
分而治之。将大项目分解成独立的小项目。比起由相互依赖的子系统组成的大项目,几个相互独立的小项目更容易管理。
设置优先级。业务环境瞬息万变,大型项目在完工前,需求会改变多次。理清需求优先级,优先实现最关键的需求。
尽快交付。首先实现最重要的需求,尽快获得客户的反馈,越快越好。
敏捷方法倡导者开发“最简单有用的东西”。越复杂的架构越难成功实现。缩小项目规模通常会降低架构的复杂性,这是架构师提高成功机率最有效途径。
架构师不是演员,是管家
炫耀和作秀是市场营销的重要手段,可以吸引顾客,却与指挥开发项目背道而驰。架构师必须扎实地掌握技术和业务领域的知识,以严谨的领导风格赢得团队的尊重。
架构师的职责和管家类似,承担着管理他人资产的责任。所以架构师应该尽可能为客户的利益着想,不能存有私心。
架构师要满足不同领域的客户需求,而这些领域的专业知识通常是架构师所不具备的。为了完成项目,架构师必须计算可用的时间和人力,综合考虑成本和复杂性等因素,设计出折中的解决方案。这里的时间和人力是公司托付给架构师管理的资源,作为“管家”的架构师决不能暗藏私心。卖弄时髦的软件框架和流程的技术词汇,只会把系统变得更负责,给公司造成损失。架构师的工作和投资代理很相似,记住,客户之所以允许别人动用自己的资金,是为了获得满意的投资回报。
软件架构的道德责任
软件世界的道德范畴边界并不清晰。
软件架构师的每项决策(例如设置必填项和规定流程),都限制了用户可以做什么,不能做什么。这比制定法律容易得多。即使用户嫌这些“必填项”和“规定流程”麻烦,也找不到法院受理他们的诉讼。
我们可以从倍增效应的角度来看待软件的影响。回忆一下最近网络病毒爆发的情形,或者科幻大片上映的盛况。那些发表在媒体上的分析和评论,每次都用耸人听闻的数字指责它们(病毒和大片)让大家无法安心工作,造成巨大的社会损失。
假设架构师要实现一项新功能。采用简单的设计一天能完成,采用复杂的设计需要大概一周时间,你会怎样选择?如果简单的设计需要用户填写四个必填项,而复杂的设计可以巧妙地处理用户不完整的输入数据,你会怎样选择?
打个比分,店铺外要挂一块新招牌,把它安装在约一人高的地方最省事,免得搭梯子和脚手架,反正不会把路堵死,路人可以弯腰通过,或者绕道。可你是否想过,你节省的时间是浪费他人时间为代价的。从长远来看,路人为此浪费的时间,将远远超过你省下的时间。
损人利己是不道德的行为,哪怕程度很轻。成功的软件产品会影响数以百计的用户,而用户不得不无奈地接受架构师的每项决策,所以永远不要忽略了架构师对用户的影响,这是我们勇于承担责任、减轻用户负担的动力。
摩天大厦不可伸缩
如果把软件工程比作土木工程,那么传统的“大爆炸”式软件部署方式就好比把备齐的建筑材料一股脑儿扔上天,指望它们瞬间拼成大厦一样可笑。
相反,无论是开发新项目,还是替换已有的系统,都应该逐个部署系统组件。这样做有两个优点。
首先,隐藏在代码中的技术风险是部署软件时无法回避的问题,每个组件都有可能出问题,一次只部署一个组件,可以将风险分散到哥哥时间段,每次砌好“一块砖”。
其次,这种方法迫使我们设计清晰的组件间接口。在旧系统上部署新组件,相当于将新组件回归集成到旧系统里,如果新系统部署成功,那么所有新组件旧同时适用于两套系统:旧系统和替换后的新系统。组件是否可重用必须通过实践检验,采用分段式部署方法可以有效检验组件的可重用性。实践证明,这种方法还能提高系统的一致性,降低系统的耦合度。
“大爆炸式”部署:是指用新系统彻底替换旧系统,新旧系统之间不存在过度阶段的部署方式。对复杂系统来说,这种一刀切式做法风险比较高。
回归集成是版本控制系统中的术语,指将分支版本(尤其是其中修改后内容,例如新开发的功能)合并到主版本库。
表面上看,“尽早发布”的做法和“递增式部署”似乎相互矛盾,但两者其实可以相辅相成。尽早发布单独的组件,意味着每个组件都可以独立的迭代。这迫使你提前解决诸如划分协议版本、维持部署过程中的持续可用性等棘手的问题。
尽早部署独立的组件既可增加商业利润,又可以改善架构品质,这样实用的技巧实在不多。
学习软件行业的行话
每个专业都有行话,同行之间讲行话方便交流。律师经常使用人身保护权、预先审查之类的术语;木匠口头离不开平接接头、搭接接头、乳胶;软件架构师则经常提到ROA、两步视图、层超类型。
为了提高效率,软件行业有一套可行的办法,供不同平台的架构师相互交流,其中包括使用架构模式和设计模式。架构师想要提高工作水平,必须掌握基本的架构模式和设计模式,学会识别不同的模式,并借助它们和同行及开发人员进行交流。
架构和设计模式可以分成四大类:企业架构模式、应用架构模式、集成模式、设计模式。每类模式对应着整体架构的不同层次和范围,例如企业架构模式解决高层的架构问题,而设计模式则研究架构中每个组件的构造方法。
企业架构模式定义架构的全局框架结构。常用的模式包括事件驱动型架构(EDA)、面向服务的架构(SOA)、面向资源的架构(ROA),还有流水线型(pipeline)架构。
应用架构模式指出了全局架构下的子系统及局部应用的设计方法。常用的模式包括大家熟悉的J2EE设计模式(包括会话外观(session Facade)、传送对象等)以及《企业应用架构模式》中提到的应用架构模式。
集成模式研究怎样在系统的组件、应用和子系统之间传递信息,共享功能,它是设计和交流重要手段。集成模式包括文件共享、远程方法调用,以及不同的消息传递模式。
“四人帮”中描述的基本设计模式,是每位架构师必须掌握的知识。虽然这些模式讨论是较底层的设计内容,离架构师的工作比较远,但是它们是架构师和开发人员相互交流的标准行话,可以提高沟通效率。
除了以上四类模式外,架构师还应该了解并堤防各种反模式。反模式指的是影响软件开发结果的常见错误,这个词是安德鲁-凯尼格发明的。常见的反模式包括需求分析麻痹症、委员会设计、蘑菇管理、死亡征途等。学习反模式可以避免许多容易疏忽的问题。
用清晰、简洁、高效的方式与同行进行沟通,是软件架构师应该具备的能力。前人总结了许多现成的模式,架构师只有学习和理解它们,才能同时提高工作水平和沟通能力。