软件架构师应该知道的97件事
架构师的行为准则(一)
最近看了一本书《软件架构师应该知道的97件事》,本来并没对它抱有太多期望和兴趣,毕竟这种讲大道理的书不可能带来什么实际收获,但看的过程中被里面中肯实在的建议给吸引,对于我这种在走向架构师这条路上常常迷失方向的人,实在是雪中送炭。读完后,决定选择其中对我有触动的条目,加上实际工作中的感悟,形成一套自认为正确的架构师行为准则,以此来矫正自己的行为。
客户需求高于一切
不要为了自己的项目经历上添加光彩而去一味追求时髦而光鲜的方案,而是应该扎根客户需求,脚踏实地地为客户着想,这样才能更体现技术的价值,不至于迷失方向。架构师首先不要把自己当做技术人员,而是业务人员,把实现业务需求作为至上的目标,学会拒绝成本高,性价比不高的技术。
简化根本复杂性
常常为了解决某一局部复杂性引入了更为复杂的框架或产品,使得复杂性不减反增。往往正确的方式是做减法而不是加法,把最根本的复杂源找到,把根铲除。
关键问题可能不是出在技术上
总结失败的项目常常会纠结于选择了错误的技术。其实技术并没有错,而是在使用技术上或是在执行过程中人为的偏差导致。而架构师解决这种人为的问题比较好的方式是沟通,通过有效地沟通把技术贯彻下去
以沟通为中心,坚持简明清晰和开明的风格
架构师不要坐在象牙塔里,命令开发人员实施你的设计和决策,而是应该尽量简化你的设计,透彻地与他们沟通,并且关键在于开明地接受他们的建议并勇于推翻自己的决策
架构决定性能
最好提升性能的方法不是痛苦地做一次次对即将上线的产品做性能测试和提升,而是在架构设计的时候就把性能作为重要因素,从架构底层考虑分布式、缓存、系统交互划分等影响性能的重点。提前关注性能,是解决性能问题代价最小的方式
分析客户要求背后的真实需求
合同上或UC上只是客户的要求,而并非100%是客户真实的需求,架构师的重要责任就是挖掘隐藏在要求背后的真实需求,这个不但可以最大化满足客户,也往往可以帮助我们避开技术壁垒,当真正抓住客户需求的时候,我们也许能用更为简单的替代方案满足客户
沟通是架构师达成目标的核心技能
常用的沟通技能和准则有以下几点:
•不要把沟通当做对抗
•不要带有情绪与人沟通
•表达自己方案之前倾听他人观点
•站立发言是扩大沟通影响力的一种好方式
•学习业务或技术领域中的行话,降低沟通成本
不要为预防故障引入更多的故障
架构师常常会为识别出的可能故障点加入监控措施,但往往会忽略做些监控措施也是会有故障的,不要试图让你的系统天衣无缝,这往往是使系统更为复杂和脆弱的来源。先承认是系统总会有缺陷的,只是把这些缺陷设定为容易察觉和维护的点
量化非功能性需求
往往功能性需求容易量化,因为这些是看得见和摸得着的,但像性能好、可扩展性好、高可用性等这些非功能性需求却不好量化,但作为架构师要有意识地去定义和量化这些需求,只有这样才能更好地和其他部门更好沟通,谋求更多资源,也便于系统更有效地验收
一行代码比500行架构说明更有说服力
架构师往往喜欢待在象牙塔里,堆砌大量架构文档,然后希望其他开发人员能乖乖地去实施。这样做的效果往往是不好的,一方面很难有这样的牛人能洞察所有的细节,在文档里就预测性地解决了所有问题,另一方面也不利于架构师与开发人员的沟通。比较好的做法是架构师参与具体实施,在实施中验证和改进架构设计,与大家达成一片也便于加深彼此配合的默契程度。
不存在放之四海皆准的解决方案
不存在最好的架构,只有最合适的架构。不会有一种架构方案,在任何项目里都适用。虽然我们承认模式的重要性,但在实际项目里要有选择性吸收,根本上要本项目和实际困境出发,不要被既有的模式和经验先入为主,因为没有一种已有方案能完全不修改地适用于你。
架构设计要平衡兼顾多方需求
架构师从某种角度来讲就是一剂胶水,把业务部门的需求、项目进度的需求、测试的需求和开发工程师本身的需求有效地捏合在一起,平衡与兼顾以至达到皆大欢喜。其他职能的人都只是focus在某一局部,需要架构师这样的人来通盘考虑,因此他的工作是最杂的,绝不是简简单单地拿出一份架构文档就OK了,需要考虑系统安全、易用性、可测性、商业价值、长期规划、发布管理和部署方式,使得各个部门人的需求得到响应
架构师的行为准则(二)
先确保解决方案简单可用,再考虑通用性和复用性
系统的复杂性往往是架构师基于通用性和复用性的设计而引入的,很多具体问题往往不需要通用性和复用性的解决方案。如果存在多个可实施方案难以取舍,先简单后通用原则可以成为最终的评判标准。架构师提供具体解决方案时,无需排斥通用和灵活,但是如果过早脱离具体情况,只会迷失在无限的可能性里,被复杂的配置选项、超负荷的参数列表、冗长罗嗦的接口,以及存在缺陷的抽象所淹没。先简单满足需求,当重复需求再次发生时,通过重构来达到复用是一种不错的方式
架构师应该亲力亲为
架构师干久了往往会脱离技术本身,迷茫在抽象之中,这是很危险可怕的。架构师要取得其他同事的信任,应该比业务人员更懂业务,比开发人员更懂具体的编码,比测试人员更懂如何有效地测试,就像航班的主驾驶员,虽然不需要亲自操作,但经验丰富,持续地监视着情况,一旦发现异常随时采取行动。架构师应该项目的交付和质量负有最终的责任。架构师应该尽可能地参与项目,不能把技术决策和方向上的难题拆分出扔给别人,需要采取更务实的办法,比如亲自动手研究或和其他成员讨论。
持续集成是架构师的重要任务
普通的开发人员会focus在各自负责的小模块,只会对单个模块负责,而架构师需要对整个系统负责,持续集成是一种对整个系统进行有效控制的好方法,架构师有责任让它运行起来。
避免进度调整失误
虽然保障进度是PM的职责,但变更要发生的时候,作为对技术最有发言权的架构师应该站出来,把变更的必要性和风险进行仔细分析,最大限度地支持PM的决策。
取舍的艺术
我们做系统,特别是互联网系统,绝不是做一个变形金刚,而是做一个有缺陷但却满足了现阶段商业需求的系统,因此架构师需要有取舍的艺术,你的架构是能用有限的资源满足最迫切的需求,舍掉那些看是光鲜却无太多用处的东西
打造数据库堡垒
在上层的程序设计中,架构师一般都会推崇先简单实现,然后在逐步重构的敏捷方式,但对于较为稳定的后端数据库,我们需要采取更为谨慎的态度,因为数据库是整个系统的基石,无论是业务设计还是技术设计都得保持它的稳定性,这是整个系统稳定的基础。我们往往会发现这么一个现象,当程序第一版上线后,数据库里表只会增加不会删除,也不会删除多余的字段,每次数据库变更都会引起所有人的紧张,也会使得本已混乱的数据库设计更为混乱。
重视不确定性
优良的架构能够从整体上降低设计决策的重要性,糟糕的架构则会使得常常突出选择的重要性。如果出现两个合理地选择,架构师应该停下来,设法找出介于两者之间的、具有更低重要性的决策,了解两者之外还存在其他选择,比决策结果本身更有价值
不要轻易放过不起眼的问题
项目的失败或线上故障往往是由于项目过程中的不起眼问题所引起,比如一些特殊的边界情况,而这些问题绝不能指望开发主力们去发现和解决,因为他们的注意力都会focus在主要矛盾上,作为时刻监控项目的架构师应该担当起发现这些“小bug”的义务。
让大家学会复用
架构师有义务提高开发人员可复用地解决问题的意识,比如以上几种措施:
•让大家把自己能复用的代码及时共享给他人
•加强复用代码的易用性,避免误用
•让大家认识到已有资源好过自己动手
架构文档的抽象程度要适中
架构师写架构文档常常很纠结,写得太高层次的话就太空洞,无切实的指导意义;写得太具体的话,比如指明到类的各种UML图,就会很约束开发人员。文档要写到什么程度,关键在于满足他人的需求,比如业务部门想从文档中得知系统各功能的实施可行性,因此你的文档要能体现各主要功能是如何满足的。测试人员想知道系统内部如何流转和如何对系统进行测试,因此你的文档要体现系统主要模块的运行流程和系统可测试性。开发人员需要知道系统各自模块的划分和之间的交互规范,因此你的文档要体现模块化设计。PM需要知道这个项目有哪些风险点,因此你的文档要体现风险点识别和如何规避。DBA和运维人员需要知道系统的数据量和性能情况,因此需要指明系统如何应对大数据量的情况。关键一点,架构师不是为了设计而设计,是要想清楚别人为什么要看你的文档,怎样满足别人的需求
先尝试后决策
设计中有很多需要决策的点,很多架构师喜欢在象牙塔里凭借经验做决策,感觉这就是架构师需要干的。其实,这样的做法往往会让你很被动,不如延迟决策,把需要决策的点抛出来,让大家去尝试,在实践比较中,其实无须决策,正确的选择自然就出来了,这样也更能拉近你和大家的距离,提高大家的积极性和你的权威性
掌握业务领域知识
架构师的角色任务在于理解业务问题、业务目标、业务需求、并设计技术架构来满足它们。掌握业务领域知识将有利于架构师选择合适的架构模式,更好地制定针对未来的扩展计划。
coding是属于设计范畴
很多人常常把软件开发类比于传统行业,把coding比作是生产过程,因此很多一线开发人员称作自己为代码工人,很多架构师也是这么认为,只是把开发人员当作实现自己设计的生产工具而已。其实coding相对于传统行业应该属于设计范畴,真正生产过程实际上是由工具来完成的编译、构建和发布过程。架构师更应该把coding当作设计来看,从纸上的设计到coding后的代码还有很多设计点可挖,同样的输出的背后也许来源于完全不同的coding,其软件成品的价值也是完全不同的。
架构师的行为准则(三)
让开发人员自己做主
架构师虽然需要为系统的设计负责,但无须包揽所有的设计工作,应该给予团队成员足够的自主权,让他们发挥自己的创意和能力,你的工作是确保大家的工作能很好的组合在一起,帮助他人解决棘手困难。当你发现同事遇到麻烦时,可以主动给出建议,但更可取的做法是创造良好的氛围,让大家主动向你征求意见。
控制项目规模
架构师要试图避免做那种“超大型”系统,因为这种系统往往难以控制,控制项目规模的办法通常有:
•抓住真正需求
•分而治之
•设置优先级
•尽快交付原则
架构师不是演员,而是管家
有些架构师误解了证明自己价值的含义,以为是炫耀技术才华,甚至是刁难开发团队,把自己放在高高在上的位子,试图让别人来崇拜你。其实架构师的职责和管家类似,承担着管理技术资产的责任,要深入了解系统里各个细节,要精打细算,而不是浮在表面做无实文章。
关注性能
高性能往往和代码优美性常常没法兼容,有些架构师往往不在乎性能上的点滴损耗,为了代码更重用或更优美,不惜多查一次数据库,多与外系统交互一次,这种做法会让后期的性能提升很被动,性能压力会逼迫你打破原有的设计,为提升性能把代码搞得支离破碎。架构师需要珍惜任何一点的性能损耗。
对复杂性要有前瞻意识
在实际的运行环境中,往往简单的系统都有可能变得非常复杂,简单的远程接口可能调不通、稳固的数据库可能down掉、消息顺序可能会错乱、服务器可能会无缘无故地down机,不要假设这些情况不会发生,架构师应该对复杂的情况有前瞻意识,要在假设类似于前面的状态存在的情况下设计软件。
关注边界和接口
任何系统或模块的边界和接口都是与外交互的门面,有交互就暗藏着误解和不恰当的划分,保持接口的顺畅交互是架构师的重要职责。往往bug发生在模块与模块之间、系统与系统之间,项目的失败也往往因为系统间交互问题,因此架构师需要给予足够的关注
助力开发人员
架构师的完美设计需要开发人员是实现,因此有业务想办法提升开发团队的战斗力,常有以下方式:
•寻找或开发工作需要的工具,并附上使用技巧
•做定期的分享或提高团队学习气氛,保持团队技术上的先进性
•参与开发团队的招聘工作
•给予开发人员更多的决策空间,帮助其成长
•保护好开发人员,让他们尽可能地免于杂事之中
•直接参与开发,分担压力
记录决策的理由
架构师常常需要权衡和决策,但决策过后却没有把决策的过程和理由记录下来,其实这是在浪费很大的一笔财富。
质疑假设
架构师往往需要假设一种情境,然后在这种情境下给出方案和做出决策,很多人包括自己从来都是纠结于这个方案的优劣,并不断改进,但却忽视了这种假设的情境是否成立,而这个可能是万恶之源。
关注系统的支持和维护
架构师通常是由开发人员成长而来,因此天然地把注意力放在功能开发上,常常忽视系统的支持和维护方面,给支持人员和维护人员造成不便。架构师需要清晰知道一个系统生命周期80%在于维护上面,而系统的价值需要支持人员去不断传递给客户,他们的需求需要得到重视。有以下几点需要注意:
•清晰性
•可测性
•正确性
•可跟踪性
不要急于求解
很多架构师都有解决难题的欲望,一遇到问题,就立马陷入解决问题的泥潭中。而更可取的是审视问题本身,看是否可以改变问题,或是干脆绕开问题,很多时候技术上的难题在通过业务上的优化是可以避免的。我们不要立足点设为解决特定问题,而是应该立足于客户需求
优秀软件是培育出来的
很多架构师需要在软件的第一版本就一鸣惊人,拿出完美的作品,其实真正受欢迎的系统是在不断发布中演化而来,对于互联网软件更是如此。架构师需要做的是打好系统的基础,使其容易修改和扩展,倾听用户的反馈,不断地在无数次改进中培育我们的软件
架构师的行为准则(四)
原则大于个人口味
很多架构师都有着丰富的经验和个人风格,以至于在平常工作中常以个人口味作为决策的依据,对于普通的开发人员也许是可行的,我们鼓励大家有个人特色,但架构师更应该依据原则办事,需要维护和遵守一套大家公认的原则,以此作为判断是非的工具
从“可行走骨架”开始
敏捷管理崇尚尽早集成,在架构设计这一块,这个原则也行之有效。架构师在开始阶段无需陷入某些难题或细节里,应该尽快地把各个核心模块串接起来,并能发动开发人员使其简单地运转起来,骨架一旦就绪,再进入健身环节。这样做的好处,一方面可以尽早消除大家之间的误解,也可以带来正朝着正确方向前进的信心
数据是核心
数据为王是大家深知的道理,只要这个系统拥有有价值的数据,那么这个系统就有生命力。架构设计中,数据无小事,任何数据只要是存在于系统中,就需要给予足够的重视,也许是个废弃的字段,但它也许会有一天被人错误的引用到,或是时不时地遭到别人的询问是干嘛用的。
根据投资回报率进行决策
很多架构师认为计算和分配资源是PM要做的事情,与自己无关,自己要做的是设计最优的系统。其实,这个最优不光是技术上的最优,往往在实际项目中大家所关注的是投资回报率最优,老板想用最少的投资获取符合需求的产品, PM想用最少的人力发布项目,开发人员想用少的代码完成功能等等,作为架构师应该把投入产出比作为决策的一个重要因素
起码有两个可选解决方案
一个经验丰富的架构师会对一些关键的问题给出多个解决方案,并能分析其优缺点,并最后一般取舍之后做出选择,这是一种令人信服的说明问题和解决问题的方式。
不能不了解硬件
软件架构师常常无法正确考虑硬件因素,有多种原因,但大多和缺乏硬件的了解脱离不了干系。最好的解决办法是加强与基础设施架构师合作,共同对架构和设计进行评估
架构无小事
很多系统建设初期的琐碎事情在架构师看来是些小事情,比如单元测试、多余的库依赖、版本号的升级、开发人员不合理的代码风格等等,这些事情不给于重视尽早解决,会在将来的某天去解决会需要数倍的成本,有效率的架构师会尽早解决这些“小事”
警惕新技术,不轻易抛弃老技术
很多架构师包括大部分的开发人员都有新技术的追求倾向,但暗藏在每个新玩意后面的是风险和缺陷,在引入每项新技术之前,需要给予足够的评估,不要只看到它power的一面,更应该熟知其潜在的危害。而对于已接收过现实检验的老技术不要轻易抛弃,可能它存在些缺陷是某些新技术可以取代的,但我们应该更珍惜对它的了解和成熟,更可取的态度是试图去优化它而不是抛弃
拉伸关键维度,发现设计中的不足
架构师或多或少喜欢在理想的情况下设计产品,一旦异常情况发生或数据量超出了当初业务方提出的假设时,架构就漏洞百出。因此设计初期可以适当拉伸关键维度,把运行环境设想得更复杂一点,把需应付的数据量预想更多一些,这样可以发现设计中更多不足
稳定的问题才能产生高质量的解决方案
最好的架构师不是要去解决难题,而是要围绕难题开展工作,要能够将四处弥漫的软件问题圈起来,并画出其中的各种边界,确保对问题有稳定的、完整认识。如果问题是稳定的,那么解决后就永远不会再来麻烦你
对决策负责
有些架构师做出决策后,把事情交给其他开发人员去实施,认为之后的事情与自己无关了,其实做出设计上决策只是解决问题生命周期的最开始阶段,真正对决策负责可以参考做以下方式:
•充分认识决策过程。可以采取记录和沟通的方式
•定期复审架构决策
•贯彻架构决策,全程跟进实施过程
•给把决策的权利委托给团队中的专家
偿还技术债务
系统里或多或少会存在一些已识别的缺陷,比如单元测试覆盖率低、可测性差、性能不达标、代码坏味道多等等,架构师常常会视为眼中钉,想一夜之间把它们都消灭掉,其实更应该把它们作为债务,有计划地可控地去偿还,要把握好偿还的时机,这样我们的成本和收益比才会更好
结束语
以上这些行为准则不是拿来背诵的,而是应该融入到日常的工作中,有句话说得好,成功是一种习惯,只有习惯了这些成功实践,才算是真正的成功