Mobvista蔡超做客QCon+案例研习社,分享优秀架构师成长攻略

  还在为如何成为优秀架构师而苦恼吗?近日,汇量科技(Mobvista)集团副总裁兼首席工程架构师蔡超做客QCon+案例研习社线上发布会,为我们带来了答案。

  图片来源于Mobvista

  蔡超拥有17年软件开发经验,其中有超过10年在HP、Amazon等世界级公司任职软件架构师/首席架构师。先后领导开发了网络安全管理系统(TopAnalyzer)、HP(中国)移动设备管理系统、亚马逊全球的新外部直运(External Fulfillment)平台、亚马逊物流+系统、亚马逊全球客服系统以及大型弹性集群管理平台SpotMax等。基于多年实战经验,蔡超总结并分享了他在架构师成长之路上的8大窍门,为同行们带来更多思考。

  右1为汇量科技(Mobvista)集团副总裁兼首席工程架构师蔡超

  以下是蔡超的分享内容:

  到现在我工作17年了,期间不仅在HP,Amazon这样的世界级团队中担任过架构师,也在汇量科技这样快速成长的企业中担任过技术领导。基于超过十年的架构师工作经验,我将和大家分享一下这些年的成功与失败,希望能帮助大家避开那些我曾踩过的坑。

  “提出问题”难于“解决问题”

  作为技术人员我们往往习惯于给出设计方案,做一个问题的解决者,而很少做一个问题的提出者,去思考要设计什么。团队中最常见的典型矛盾是产品团队和研发团队的矛盾。作为研发团队,我们常吐槽产品团队的需求不合理,不懂技术等。

  其实我们可以尝试把自己的工作往前移一下,不仅仅是去设计架构实现产品的需求,而是去实现客户的需求,甚至发现潜在需求。

  变成在设计上提出问题的人后,你会发现提出问题同样需要深入思考,设计一个好的问题,有时候甚至比解决问题更难。

  即便是软件开发领域的大神Frederick P. Brooks Jr.(《人月神话》的作者)也会有同样的感叹,“The hardest part of design is deciding what to design.” 这句话便是出自他的《The design of design》。

  决定“不要什么”比“要什么”更难

  也许是由于人性的贪婪,对于软件系统我们同样想要更多:更多功能,更好的性能,更好的伸缩性,扩展性等等。作为软件架构师要明白软件架构设计其实是一种取舍或平衡。当大家都在往里面加东西的时候,架构师更应该来做这个说不的人。

  软件设计和定义过程中存在很多取舍,如完善功能和及早发布的取舍、伸缩性和性能的取舍等。如何做好取舍?著名的CAP原则就是一个很好的关于取舍的指导策略。为保持架构风格的一致性,在一开始架构师就应该根据系统的实际需求来定义一些取舍的原则,如:数据一致性拥有最高优先级,提前发布核心功能优于完整发布等。

  非功能性需求决定架构

  很多设计人员可能会认为架构是由要实现的功能性需求决定的,但实际上真正决定软件架构的其实是非功能性需求。因此,架构师需更加关注非功能性需求,如性能,伸缩性,扩展性和可维护性,甚至包括团队技术水平和发布时间要求等。能实现功能性需求的设计方案有很多,只有考虑了非功能性需求后才能筛选出最合适的设计。

  《面向模式的软件架构》这套书为不同的非功能性需求提供了很好的参考和指导,多年来一直是架构师们的必读经典。下图的架构模式便是来自这本书的第一卷,图中的Micro-Kernel模式,更加关注可扩展性和可用性(错误隔离)。

  “简单”并不“容易”

  很多架构师常常会提到保持简单,但有时候我们往往会混淆简单和容易。简单和容易在英语里是两个不同的词“simple”和“easy”。

  史蒂夫·乔布斯曾说过“Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it’s worth it in the end because once you get there, you can move mountains. To be truly simple, you have to go really deep.”

  真正的简单方法往往是来自于对问题和技术的更深入理解,简单可以说蕴含着一种深入的巧妙在其中。下面我来举一个例子。

  据数据显示,在一款软件系统的生命周期中,成本消耗占比最大的部分往往在于维护。因此如果能简化维护部分,对于整个项目将具有全局性的意义。

  我们曾经为移动运营商开发过一个系统设备管理系统,移动运营商期待通过该系统管理移动设备,因此,系统需实现包括设备的自动注册,固件和软件的同步等管理功能。这些功能可通过一些管理系统与移动设备间的预定义的交互协议来完成,过程中,电信专家们会根据业务场景及需求来调整和新增这些交互协议。起初我们采用了一种容易实现的方式,即团队中的软件工程师根据电信专家的说明将协议实现为对应代码。

  但很快我们便发现这样的方式不仅没有让项目更容易,反而让我们的工作变得更复杂。

  “I believe that the hardest part of software projects, the most common source of project failure, is communication with the customers and users of that software.”–Martin Fowler

  正如软件开发大师Martin Fowler所说“沟通”往往是导致软件项目失败的主要问题。这个项目最大的问题是在系统上线后的运行维护阶段,电信专家和开发工程师之间会不断就新的协议修改和增加持续沟通,而由于双方的知识和词汇存在很大区别,导致了沟通效率低、系统维护(协议的修改)变得十分艰难,协议更新上线慢等问题。同时,由于软件工程师对于电信协议的理解程度有限,很多问题往往在实际上线后才暴露出来,导致了很多交换和反复。

  针对这一问题,我们和电信专家一起设计了一种协议设计语言(并提供可视化的工具)。这种设计语言使用的是电信专家所熟悉的词汇,然后通过一个类似于编译器的程序将电信专家定义好的协议模型转换为内存中的Java结构。整个项目的运行与维护因此变得简单高效,省去了低效的沟通和不准确的人工转换。

  不难看出,一开始按电信专家的说明直接实现协议看似更为容易,但放在整个软件的生命周期中,这却并非一个简单高效的方法。

  永远不要停止编码

  架构师也是程序员,代码是软件的最终实现形态,停止编程会逐渐让你忘记作为程序员的感受,更重要的是忘记其中的“痛”,从而容易产生一些不切实际的设计。在亚马逊,高级副总裁级别的distinguish Engineer,如被称为Java之父的James Gosling等每年的编码量均不低于10万行。

  风险优先

  架构设计很重要的一点是识别可能存在的风险,尤其是非功能性需求实现的风险。因为这些风险往往没有功能性需求这么容易在初期就被发现,但修正的代价却比修正功能性需求的代价大很多,严重时甚至可能导致项目失败。

  因此,我们应该在原型或早期的迭代中确认风险,并通过合理的架构解决风险。绝对不要把风险放到最后,就算是一个项目要失败也要让它快速失败,这也是一种敏捷。

  从“问题”开始,而不是“技术”

  技术人员对新技术有着一种与身俱来的激情,总是乐于学习新技术和使用新技术。这容易导致一个通病,就是“当我们有一个锤子的时候看什么都是钉子”,因而使用一些不适合的技术去解决手边的问题,导致简单问题复杂化。

  我曾经的一个团队便发生过类似事件,原本是一个用MySQL作数据存储的简单服务,但由于当时负责该项目的人员对彼时新出的DynamoDB产生了兴趣并学习了相关知识,因此该成员决定使用DynamoDB替换MySQL。

  之后很快发现DynamoDB并不能很好地支持事务特性,在当时只有一个性能极差的客户端类库支持事务,而由于采用了客户端方式,引入了大量额外交互,导致性能差别达到7倍之多。

  这时候,这个成员就采用了当时在NoSQL领域广泛流行的最终一致技术,通过一个Pub-Sub消息队列来实现最终一致(即当某对象的值发生改变后会产生一个事件,然后关注这一改变的逻辑,就会订阅这个通知,并改变与其相关的数据,从而实现不同数据的最终一致)。

  接着由于DynamoDB无法提供SQL那样方便的查询机制,为了实现数据分析不得不又引入了EMR/MapReduceJob。

  到此,大家可以看到虽然最后实现了一样的功能,但是项目的复杂性大大增加,维护工作也由一个人变成了一个团队。

  过度繁忙使你落后

  对于IT人而言,加班是家常便饭,“996”似乎成为了公司高效的标志。但事实上没日没夜的忙碌往往会挤压我们的学习时间,导致我们失去知识更新的意识,不知不觉变得落后,最终失去跳槽的能力与勇气。

  在今天这个高速发展的时代,我在工作经历中发现过度繁忙往往会带来以下问题,首先是缺乏学习导致工作能力难以提升无法面对日益复杂的需求;其次,在技术上与业务上丧失领先优势,只能被动追赶,而被动追赶又会让我们更加忙碌,最终形成恶性循环。

  个人技术的成长就像健身,仅靠锻炼还不够,营养的补充同样重要。当你在一个领域工作一段时间以后,工作对你而言就主要是实践了,随着你对该领域的熟悉,能学习的到的技术会越来越少。所以每个技术人员都要保证充足的学习时间,否则很容易成为井底之蛙,从而陷入前面提到的恶性循环。

  最后,以伟大诗人屈原的诗句和大家共勉“路漫漫其修远兮,吾将上下而求索“希望我们大家都可以不忘初心,保持匠心!