万年看客 发表于 2024-4-13 07:43

303-Dylan Beattie:怎样成为一名架构师?

https://www.youtube.com/watch?v=3LtQWxhqjqI&t=294s

大约五六年之前,我任职的公司雇了几个顾问进行公司结构重组。其中有一位对我进行面试:“你是否认为自己更擅长担任系统架构师?”所以我收到了这封电子邮件:“迪伦,本邮件旨在确认你的工作角色转变。你现在是系统结构师了,工作责任包括设计架构,搭建架构,维护架构以及系统架构化。祝你工作顺利。”于是我回到工位心想:“我现在是架构师了,没什么感觉不一样的。 Visual Studio的加载速度依然不很快。”然后我就踏上了这条道路。既然我要做这份工作,那我就要好好做。我要理解架构究竟是什么,做得好的话是什么样子,架构师在团队里的角色是什么。

我开始深入研究这个词的来源。软件这一行当中的许多术语都是从其他地方偷来的,比方说Python与MICE,乍一看还以为要养宠物蛇。软件总线叫做公交车/Software Bus,指令执行要靠流水线/Pipeline,启动软件叫做发射/launch,软件故障叫做崩溃/crash。这些英语单词原本都有各自的含义,而我们则要用来指代完全不同的东西。语言是理解人们处理问题方式的非常强大的工具。如果你自称研发人员,请举手。如果你自称黑客,请举手。码农?架构师?前端?后端?工程师?工程师尤其是一个很有争议的单词。在很多国家你都不能随便自称工程师。在加拿大,你要是没有工程师执照就不能自称工程师。在新西兰,如果你有软件工程学学历就是工程师,但是软件开发或者计算机科学的学历却不管用。我住在英国,前几天我家里的有线电视坏了,他们派来一名工程师处理问题。我并不认为这个人有工程学历。

我们对于工程这个词往往抱有先入之见。我的第一份工作是为一家建筑公司效力,他们有架构师也有工程师。我开始分析这些角色是怎么来的。这两者的区别在我看来很清楚。请看画面左边是个烤肉炉,大概由设计这个烤肉炉的人亲手架设或者请几个朋友动手;画面右边是布鲁克林大桥,设计布鲁克林大桥的人并没有自己搭建这座大桥。我认为这点区别很有趣。架构师要设计你自己不打算写的软件;你要设计前端、界面与结构,但是你不负责编写代码。在建筑架构这方面,我们兴建了各种美丽的建筑,吸引游客从各地远道而来慕名观看。软件架构呢?我们是幕后人员。你恐怕不会这么说:“请看这段代码多么美丽。从侧面来看看,再拍张照片。”或许软件架构与其他人对架构的理解并不一样。而且只有软件与建筑物才有架构师。没有飞机架构师、赛车架构师或者下水道架构师。

我们再深挖一点。第一个使用“软件工程学”这个词的人是画面上这位女士。有人认识她吗?你们应该认识。她是玛格丽特.汉密尔顿,阿波罗11号项目的首席工程师,也是第一个谈到软件工程学项目与系统视角的人。她主张软件设计的首要要求是与所有其他系统组成部分协同工作,这个系统的任务则是将尼尔.阿姆斯特朗和巴兹.奥尔德林送上月球。她率先将软件当成了工程学科,不能闭门造车,而是要与其他流程协同进行。

第一个将“架构”一词引入计算器系统术语的人是弗雷德.布鲁克斯。他写了一本《人月神话》,你们当中肯定有人读过这本书。此人是一位非常有影响力的工程师兼科学家。1962年,他正在为 IBM 开发一个名为“Stretch”的系统。在此之前他这样说过:“计算机架构就像其他架构一样,关键在于决定结构用户的需求,并且通过设计在经济与技术的限制之内尽可能有效地满足这些需求。”这是架构一词最早被用在计算机科技领域。在二十世纪六七八十年代,计算机架构几乎永远指得是硬件,因为硬件很昂贵很难更改。如果你想修改代码,写点新代码发布出去就行了。而修改硬件则意味着根本性的决定。布鲁克斯在IBM项目当中做出的决定之一在于将一个字节设定为8比特而不是6比特。从那以后所有的计算机沿用的8比特约定都可以追溯到这个决策。想象一下,假如我们在构建计算机系统期间想要更改这一决定意味着什么?扔掉处理器,扔掉主板,扔掉总线,扔掉我们为了制造主板和处理器而建造的工厂,我们必须重新开始。这样的决定非常昂贵,很难更改。相比之下,软件总是便宜的多,软件占据构建系统总成本的百分比总是要低得多。

二十世纪九十年代发生的两件事改变了我们的思考方式。首先,业务软件打入了主流。从来没用过计算机的公司现在突然有了计算机,还请人用 Visual Basic为他们设计软件。花店、小型旅馆与洗车房纷纷开始雇人为他们写软件,从而自动打印发票。然后过了几周他们突然发现:“这个软件并不能满足我们的需求,需要修改——怎么这么贵?!”突然间,修改软件系统的成本成为了投资的一大显著部分,于是我们开始考虑修改软件需要多大成本。然后万维网出现了。在此之前所有的软件都只能在一台计算机上使用,输出基本靠打印机。我们不发邮件,我们不用应用,不用API,更不会上传。然后万维网来了,突然我们不再构建仅仅在单独一间办公室的一个米色盒子里运行的软件,而是要构建可以在世界各地成千上万台机器上运行的软件客户端、服务器、网关以及所有组件。对于如今有些公司来说,修改软件的成本几乎等于全部运营预算。他们的工资单上有几个清洁工与人资专员的名字,除此之外所有其他名字都是负责每天修改代码的员工。对于这些公司来说,假如修改架构很便宜,他们就能盈利;如果修改架构很昂贵,他们就有麻烦。所以我们现在都认为架构是难以改变的东西,其他的一切都只是编码而已。

最早正式对待架构的著作是Mary Shaw与David Garland于1995年出版的《软件架构》一书。我对这本书最喜欢的一点在于它试图将系统设计的大量口口相传的知识正式化。世界各地的人们对如何构建更大的系统、更快的系统乃至模块化的系统都有各种好主意,但是没有人将这些好主意整合起来总结成书,指导日后的工作。我想看看弗雷德.布鲁克斯的定义,因为我很喜欢这个定义。我将其分解成三部分。首先,“决定用户的需求,并且通过设计在经济与技术的限制之内满足这些需求。”对我来说,在我成为一名架构师的旅程当中的最大启示之一在于认识到谁是用户。我们通常认为用户就是网线另一头正在忙着填表、拖放、复制粘贴的人们。那么架构师的用户是谁?他们是团队当中的研发人员。你的工作是满足那些将要构建和交付你正在开发的系统的人的需求,这不仅仅包括你眼下团队当中的成员,还包括你今后将要雇用的员工,还有三四年后将要从事你的开源项目的人。因此你的角色是考虑如何为我们还没见过的人提供服务,构建我们还没编写的软件,销售我们还没造出来的产品,让我们还没联系上的客户感到满意——很容易,对吧?

我们大概需要一个计划。计划这个词在软件工程学领域很不好过,因为我们有所谓的《敏捷宣言》。每人读了这本书都觉得真精彩。法国哲学家笛卡尔不搞哲学的时候就是一个敏捷顾问。有一天他说:“迅捷管理表示我们应当应对变化而不是遵循计划。”客户说:“好吧,我们本来就没计划。”笛卡尔惊呼道:“你要是没有计划,那又怎么能够不遵循计划呢?”信马由缰并不是可行的选项。我们可以说“这是我们的计划,但是环境改变了,原本的计划不再准确。”也可以说“我们根本没有计划,咱们一边做一边看。”这两者不是一回事。《敏捷宣言》的作者们一次次注意到,团队刻意做错事情,因为这是计划的要求。《宣言》要解决的正是这个问题。“我们正在发现更好的软件开发方法……我们要重视响应变化而不是遵循计划……我们看重右边的东西,但是我们更看重左边的东西。”我们需要计划,但是计划不见得准确。计划是活的,作为架构师你要清楚你们打算做什么,以及这些目标怎样组合在一起。

我还想提到《敏捷宣言》的另一条原则:“最好的架构、要求与设计来自自组织的团队。”假如你已经有了合作无间的一队人,他们已经有了自己的工作方式,那么你就该后退一步,不要干涉,顺其自然。错误的做法是随便雇一拨人,告诉他们“你们自己组织起来”。一个月之后你再回来,发现项目纹丝没动,你雇的人全都自行组织到马路对面喝酒去了。高效团队不用你多嘴就能自行启动积极的反馈循环,但是如果你的团队来找你说:“我们需要一些帮助,我们不知道如何解决这个问题,我们不知道如何在这个问题上进行合作。”那么作为一名架构师,你需要给出比“你们自己组织一下”更好的答案。你要给他们提供支持。

咱们再来谈谈限制。画面上是某家公司的软件开发规则:不用新员工,不用 JavaScript,不用开源,不用微软,不用 cookies。我相信这是 Oracle 公司的工程原则。我们才不想在这种地方工作,这里太糟糕了。但是无论你想做什么都会有限制,总会有你不能做的事情。我们还没能实现物体传送。如果有人问你:“我们能做一台运送大虾的传送器吗?”我们的回答只能是:“你想多了。”然后这人又问你:“那我们可以在不使用线缆的情况下实时进行高清视频通话吗?”很长一段时间你的答案都会是“不行,不行”,直到有一天你松了口风:“要不然你试试?”很长时间以来所有人都相信触摸屏手机没有前途,因为这段时期力所有人见过的触摸屏就是机场里那些不好用的大牌子。但是与此同时苹果公司有一群人正在评估测试不同材质的玻璃触屏与多点触屏技术。其他人全都认为触屏手机不可能的时候,只有他们说:“不对。”苹果推出触屏手机一年之后,所有人都想要触屏手机,谷歌与安卓全都推出了自己的触屏手机。作为一名架构师,你要注意到正在发生的一切变化,从而及时告知你的团队:“我们以前认为不可能的那件事情现在不妨试一试。”

这份工作的困难之处在于要将这些限制传达给研发人员。你的研发人员从研发大会上回来之后一个个都打了鸡血:“JavaScript 框架将会解决我们所有的问题!”这时你必须站出来说“不行,我们必须支持IE浏览器,这是我们工作的限制之一。我们赚得就是这个钱。我们的客户还在用IE8。”你还必须想办法将这些限制传达给客户:“我知道你们想这么做,但是这与我们要设计的系统限制不兼容。”确定用户需求,满足这些需求,在经济与科技限制之内。实际上软件架构师的工作挺简单的,总共三件事:做决策,传达决策,强化决策。谢谢大家,再见——

——我再多讲一点吧。怎样确定用户需求?有人对你说:“我们想要建立这样一个系统,我们想要将登录系统解耦,这样就可以使用同一套身份验证来支持多种微服务。”你的任务就是做到这一点。在你做到之前,你必须理解五点。首先是你有什么。很多时候,在组织与软件团队当中都存在两个版本的事实,其一是人们以为自己有什么——因为他们花了很多钱叫人设计高效交易处理系统,其二是他们具体有什么——好几万行不管用的Ruby代码。你要理解两边的区别。我认为做到这一点的最佳方式是去观察系统之间的边界,你需要去理解这些系统之间的交互(traffic)。不用太担心代码,不用太担心设计文档。当人们告诉你某些东西的作用时不要全信,他们的说法固然有用,但是未必一定准确。画面上是一张最简单的系统架构图:网站——HTTP——互联网。作为一名架构师,你不在乎网站的开发语言是PHP、.NET、Perl 还是 Ruby 或者其他什么,至于互联网更是其他人的问题。但是中间的HTTP很值得你多问几个问题:它能处理多少事务?有没有配备HTTPS?证书什么时候过期?它在处理GET、PUT还是POST请求?我要是设置一个代理会怎么样?我们可以缓冲存储多少内容?我们有没有对经过的流量正确使用Etag?只需针对这个HTTP设置网络跟踪并且观察半个小时,就会让你极大地了解该网站的实际信息,远比花费时间阅读代码更加有效。流量是真实的,流量是软件系统的命脉。“我不关心这个东西的设计功能是什么——我只关心它能干什么。”这是阿波罗13号任务总指挥Gene Kranz的名言。你需要了解系统的实际功能而不是设计文档当中的内容。有时这会令人失望,好比说我们的高性能身份验证系统每分钟只能处理六个用户;有时候你会惊喜地发现 AWS里有一个完整的 Redis 集群,我都不知道我们有这个,太棒了。我们可以使用它来加速各种事情。我们可以给网络服务器加装Varnish,加速效果立竿见影。实际了解系统意味着惊喜,也意味着失望,但是花时间做这件事总归非常值得。

也有人会说:“我们要处理一个绿地项目,一切都要从头开始,没什么好了解的。”但是根本不存在真正的绿地项目,因为总会存在一两个小系统或许Excel格式的销售数据,其中有些可以帮上你的忙,另一些则出于复杂原因你不能用。上一次构建绿地系统的失败废墟里总会留下有用的东西。总有人尝试过,总会留下到处乱窜的代码。政治因素也要考虑,之前兴许有人选择使用Microsoft SQL Server而被解雇,所以现在没有人敢碰Microsoft SQL Server,因为上一个这样做的人被解雇了。预先知道前情概要之后,再提到这种事你就知道该怎么说了。此外还要小心兔子洞。有些要求看起来非常非常简单,其实则不然。你告诉你的团队:“你们只需将 Redis 与 nginx 集成一下就行。”三个月后他们告诉你:“老板,这和文档力说的不一样啊。”这些问题都会出现,只有意识到问题的存在,你才能合理地决定解决问题的途径。

接下来要确定你需要什么。大多数利益相关方都会说:“网站需要快速,网站需要安全。”你说:“太棒了,多谢指示。”然后你告诉团队:“老板发话了,网站要越快越好。”团队说:“那么我们就构建我们自己的 HTTP 加速器好了。”两周后老板问你:“项目完成了吗?”你说:“不不,团队正在开发一款HTTP加速器,在传入的网络流上使用逐位模式匹配,足够让我们的网站速度跻身史上前十名。”老板倒吸一口凉气:“倒也不必这么快。”那么到底需要多快?要在商务语境里讨论。作为架构师,你必须成为沟通技术与实际之间的渠道。网站的速度要多快才算快?90百分位的反应速度低于500毫秒足够快吗? 有些利益相关方认为这足够快,另一些利益相关方则会问:“90百分位是什么意思?”“意思是如果有十个人看我们的网站,其中有一个人要等一会儿才能打开。”“等多久?”“不知道​​一秒?五秒?”“五秒太长了,这可不行。”这样的对话才有指导意义。你说:“一定要低于五秒的话成本可就要增加了。”他们说:“我们可以怎么办?”你说:“我们可以去掉横幅广告的 JavaScript。”他们说:“这可不行。”你说:“快速或者便宜,两者不可兼得。”同理,他们说“网站需要安全”,那么你就要问“安全到什么程度?你担心什么样的威胁模式?”常见的威胁模式分三种,分别是俄国僵尸网络,愤怒的前合伙人以及摩萨德。俄国僵尸网络会敲你的门三秒钟,敲不开的话就去敲另一家,他们从海盗湾下载了一大张密码表;愤怒的前合伙人大概能够拿到与账户绑定的手机,双因素身份验证对他们可能不起作用;至于摩萨德早就潜入了你的网站,建议你该吃吃该喝喝,没事别去招惹他们。

然后是你能建造什么。如果你决定“我们要发行这种软件”,那么你在你的工作周期内——无论是冲刺、迭代还是站会——可以多么可靠地达成目标?这可以归结为我所说的四P模式——人/people,样式/pattern,组件/package,流程/process。首先是人。你的团队有哪些人?你能雇佣什么人?哪些人会对你的项目感兴趣?你可以接触到哪些人并且拉他们入伙?谁擅长Angular框架?谁擅长F#?谁擅长React?谁擅长前端?谁擅长后端?要了解所有这一切,将这些信息与你的工作对齐。技术路线选择的基础是你的现有人员以及你可以雇用的人员。样式是现代软件在概念层面的基本构件。某些样式非常适合使用某些语言的某些人,有些则不那么合适。我最近用Ruby on Rails做了很多工作,Ruby on Rails与 MVC 样式的耦合非常紧密,以至于有一天我旁听了一段十分钟的谈话,话题是“服务对象”,然后我才意识到他们讨论的是我才意识到他们在讨论的是类,以及类所包含的数据和行为。Ruby on Rails与特定的MVVC耦合得如此紧密,以至于除此之外的东西都有了专有的名字。而在.net中,一切都是类,而如果有些类具有这样的功能,那多半是用了Controller模式。理解样式和你正在做出的技术选择之间的关系事关重大,特别是你可能会发现自己要与自己的开发语言、开发框架以及你应该使用哪些样式的意见作对。如今所有开发语言都存在于组件、库和模块组成的生态系统当中。你可能需要进行透明PNG编码,进行加密,或者流式传输视频。在绝大多数开发语言当中,你的需求早就被别人解决了。要理解你选择的生态系统的广度:获取某个组件的难度如何?这些组件是否得到了积极维护?假如某个组件消失了怎么办?这些组件分叉的可能性有多大?至于流程则着重于可重复性。如果周一早上你说“到周五我们要发布”,那么在大多数情况下到了周五你就应该能够发布。流程在于你的团队怎么合作,你们是否理解系统的缺陷与功能。

再然后是你能买到什么。我本人的软件研发规则当中有一条:能用万事达卡就不要用PowerShell。你的团队要构建你能卖出去的东西,能够为你的组织创造价值的东西。不要创建你自己的云系统,亚马逊已经做过了,试图在云基础设施领域与亚马逊竞争是浪费时间。他们已经解决了这个问题,你应该专心解决你自己的问题。话说到这里,不妨谈谈Google Analytics。我正在开发的系统之一具有自己的跟踪和分析引擎,因为我们将这些分析作为产品的一部分。有人说你为什么不直接使用Google Analytics?我说因为我们不想依赖谷歌来提供我们实际提供给客户的东西。使用我们自己的产品意味着我们拥有价值流。如果只想看看有多少人点击了电子邮件,直接使用Google Analytics完全没有问题。购买与自行开发之间的阴阳平衡必须小心掌握。

最后是你可以抛弃什么。如果你公司有一个邮件系统,请举手。如果有两个系统发送邮件请举手。三个呢?四个五个呢?有一次我做过审计,我们想要重新命名外发电子邮件,从而适应新的公司配色方案。我在代码中发现,开发人员在 15 个不同位置编写了代码来创建电子邮件消息模板,填充 HTML并且发送。第一个这样做的人肯定是我,因为我刚上手的时候什么都不存在;第二个是一名开发人员,他不知道我已经完成了这个模版;第三个人发现之前已经有两个人这么干过了,看来这么做就是这里的工作要求;第四个人是外包人员——结果就是将公司发送的电子邮件改成紫色成了**烦。我们将电子邮件的颜色变成了软件架构问题,因为之前我们的架构叠床架屋。所以我们将所有电子邮件合并到一个传出中继服务器。在邮件发送之前,这台服务器会在边界对其加以定制。你应当寻找此类重复,因为它们意味着有机会简化系统并且收回一些技术债务,从而降低日后更改系统的成本。

理解了这五件事之后,你就要决定接下来该怎么办。这是容易的部分,因为你经历了所有这一切,你和团队取得了充分理解,了解了情况,参加了行业会议,跟上了行业动态,那么解决方案大概会自行浮现,你会想出好主意,你会觉得“我们应该这么做”。然后是有趣的部分:你会决定这款软件看起来什么样。在你的脑海里呈现出了水晶一样美丽的结构,数据流经系统,各种界面,数据结构,登录器,服务器列表和云等等。然后你告诉团队成员:“来看看这款软件怎么运用。”你画了图表给他们看,他们的反应是:“这啥玩意儿啊?”我这里想说的是示意图的问题。在建筑工程学当中,你请人盖房,对方要先画图。你看了图纸之后表示:“好吧,我相信你知道自己在干什么。”然后他们会给你更多的图纸——端面图、侧视图、平面图、示意图,迟早还会拿出越发保真的效果图。最后他们会盖好这座房子,而你会说:“就像我想象的一样。你们干的漂亮。”我们身边全都是绘图,我们小时候学的第一件事就是在纸上乱画,然后父母把我们的画贴在冰箱,鼓励我们越画越好,直到我们不好意思为止。我们学会阅读之后,还会在图像与单词之间连线。我们是视觉导向的动物,我们身边全都是示意图、照片与插图,我们本能知道怎样阅读示意图。不幸的是,在软件领域情况未必如此。

画面上是一张软件架构图,谁能帮我按照这张图设计软件?这是一幅正式示意图,学校里的教材上画得就是这种图,我在大学里还学过这样的图,这就是所谓的DeMarco与Yourdon结构化分析图——谁能告诉我这张图上画得是什么东西?我们首先添加一下图例。左右上角的上下横线图标不是正则表达式,而是数据库或文件系统,我们不知道哪边是哪个;夹在中间的椭圆形是子例程。数据从左右上角出发,流经一个又一个椭圆,然后在右下角输入输出。

我们写得更详细一些。首先我们要为各个图标的内置代号标明内容——不用费心去谷歌搜索,这些内容网上肯定没有。 左上角的Excelsior 是一个充满客户详细信息的续集服务器。为什么它被称为 Excelsior?因为构建它的人将Excel当成了基础——爱咋滴咋滴,命名可难了。中间椭圆里的Mercutio是什么?一个填充电子邮件模板的.NET 服务。下方椭圆里的Norman是发送电子邮件的.NET 应用程序——为什么要叫Norman?这里玩得是剧作家诺曼.梅勒的梗。左上角的JK6 GB87是营销部门保存电子邮件模板的服务器的资产编号——顺便说一句,所有这些命名都是我开发过的软件的组成部分——至于右下角的Mandrill则是电子邮件平台MailChimp 的SMTP中继服务。现在你大概就理解了需要什么样的人来构建这个系统。我们仍然受到DeMarco与Yourdon分析图的限制,这意味着我们能够概念化的只有数据库、子例程、数据流、输出之类的泛泛内容。

我们不妨设计一套我们自己的的图例。只要随便用一下Clipart与微软Office模板,然后再谷歌一下,就能找到一大堆可用图例。现在连接Mercutio与Norman之间的方块红线就是我从某个RabbitMQ文档里找出来的。现在我们可以说 Excelsior与Mercutio之间的绿线意味着ADO.NET,Mercutio上面标注的小齿轮意味着Windows服务器,JK6 GB87与Mercutio之间的蓝色连线意味着SMB文件共享,等等。更进一步,我们还可以给流量边界也添加注释。比方说Excelsior与Mercutio之间的绿线就可以补充一句“经由Mercutio进行的Windows认证”,GB87与Mercutio之间的蓝色连线可以标注一句“仅限.txt与.html文件格式”,连接Mercutio与Norman之间的RabbitMQ方块红线可以标注一句“由CloudAMQP支持的软件运营服务”,Norman与Mandrill之间的紫线可以标注一句“由SMTP993号端口的TLS启用。”这样一来如果发不出邮件,你就知道要么是你用错了端口,要么是你没有得到安全协议认证。凭借这张注释版架构图上的信息,我们可以展开有意义的对话:应当怎样着手构建这个系统?需要多久?需要测试多少实例才能运行?

画面左边这张原本的DeMarco与Yourdon分析图就像从教科书里抽出来的,简洁漂亮,一看就出自专业人员之手,读图的人看不懂也不敢问,因为害怕别人说他傻。右边这张我们自己亲手注释的图看着很混乱,但是却包含大量有用信息,可以用来开展对话。我发现在各种软件开发当中的最大挑战在于书中的例子都太干净了。谁也没告诉你这些东西在真正做起来之后会有多么混乱。画面上是我在五年前参与的一个外包项目的一部分系统架构示意图。每一种流量都用不同颜色标注,甚至还专门用一种颜色标注了基于VB Cursor的程序库。单看流量走向完全搞不懂这是在干啥。我们起码知道架构的一头是Visual Basic,另一头是SQL服务器,但是要想理解两头之间的机制,那就只能自求多福了。不仅图表结构一团乱麻,而且很多注释也很没溜。“数据库每五分钟同步一次并更新用户名与密码。如有必要立刻更新,按下大红按钮。”在外人眼中写这段注释的人大概正在放飞自我:“已经这么乱了,再乱点又能如何?”这才是试图将理念转化为现实的示意图的样子,而不是教科书上只为了好看的样子货。

关于图表我再说最后一点。画面上是两张软件架构图, 其中一张代表了六边形架构,请问是哪一张?我给个线索:不是上面画着六边形的那张。很多时候你会听到诸如六边形架构、N层端口和适配器分层接口之类的词。如果你听说过“六边形架构”,并且查看这些图表,你会合乎逻辑地认为带有六边形的就是六边形架构。可是我们之所以使用“六边形架构”这个名称,是因为有关此类端口和适配器的第一版论文使用了六边形这个词,这个名称就此流传了下来。它与六边形无关,六边形架构中不一定有六个东西,这只是一个名称而已。左边这张图有数据端口和适配器,这就是六边形架构;右边的六角形是个蜂窝,里面粘贴了与软件无关的剪贴画,都是我编的。永远不要害怕问清楚,永远不要害怕这么说:“很抱歉,我还是不明白。你能再讲一下图表上的那个东西是什么吗?这里的这条线是什么?这些东西是什么?那个黄色的东西是一个SQL Server的数据库吗?”只要有人率先把话说开,在场的其他人也会纷纷开口询问:“是的,我也不明白。我们可以再解释一下吗?” 反过来说,这样的对话也为架构师提供了参考背景:“看来下次做展示的时候我需要提前讲透这些方面,以便我们可以直接切入正题。”

再来说说强化决策。你已经提出了你的设计,你了解限制,你知道你现在想要交付什么。现在你想帮助团队构建正确的产品。我最初将这一步称为强制决策,但是我不太喜欢将架构师与警察划上等号,因为你的任务毕竟是支持团队的工作。强化决策可以归结为两种类型,首先是验证/validation,其次是验收/verification。验证看得是我们是否建造了正确的软件,验收看得是我们的建造是否正确。前者很难,你能做的无非是十年后回来看看这家公司是否仍在营业,以及那里的软件是否还在正常运作。验证没有捷径可走。验收则不然:我们的建造是否正确?我们正在创建的东西是否匹配并反映了我们讨论的架构、设计与理念?对于建筑架构师来说,你可以拿起图表,对着建筑,并排看过去:“行吧,我看着没问题。”当然,建筑物的验收还要考虑其他层面,例如工程应力图和承重图等等。但是我们从小就学会了这项技能,看一眼图画再看一眼实物就知道画得像不像。我们也应当这样对待软件。

回头看看刚才咱们那张Excelsior图表。团队构建了代码,它已经完成了,已经发布了,我们想看看成品软件是否与图表一致。Microsoft Azure 配备了Dashboard,让我们看看——非常漂亮,但是看起来并不像图表。也许Teamcity 看起来更好懂一些—— 仍然很漂亮,但是同样不像图表,一点用都没有。别费事了,直接看代码吧——还是啥都看不出来。不管怎么看我都看不出软件与设计之间的对应关系。你如何判断已经构建的软件是否符合设计、架构与概念?当年我第一次做这项工作时犯了一个典型的错误,那就是亲自审查所有代码。团队可以放手构建他们想要的东西,作为架构师我将审查他们的代码,确保正确。这么做真的真的很糟糕,我建议你千万别尝试。首先这么做非得累死你不可,晚上加班将会成为常态。“这 15 个拉取请求是否还在接受审查?但是如果我不审查这些,明天谁都没法干活。”所以你难免变得马虎:“行吧,看上去没大毛病。”这样做的另一个问题在于限制了你的团队做出你不理解的事情的能力。“我查看了你的C#代码,但是我没看懂它是什么。” 你的首席工程师说:“哥们,我的团队用得是Scala。”

说到审查代码的第三个问题,不妨看看这段代码:

public class customerRepo {
public customerRepo(IdentityMap<customer> map) {this.map = map;
}
public customer Getcustomer(int customerId){return map.FindById( customerId);
}
}

我们已经召开了关于架构和设计的会议,我们已经说过我们将使用带有身份映射的存储库模式,每个人的反应都是“哦,存储库身份映射,明白了架构师先生,非常感谢你。”然后他们给了你这段代码,你能从这段代码中看出什么?你可以看出开发人员知道存储库和身份映射这两个词很重要,他们应该使用这些名称。这些名称并不能告诉你代码是什么,只能告诉你有人将它们称为什么。你要阅读代码并试图提炼它的作用。一个优秀团队虽然命名未必不一致,但却了解模式和类之间的关系。反过来说,读代码有点像步入雷区。好比说你晚上在城里闲逛,投宿地点的招牌写着“豪华酒店”,然后你早上醒来才发现招牌下面是一座老旧危楼。也许遵循标签并不是理解软件构建的最好方式。

那么我们能做些什么来温和地引导我们的团队走上正确的道路,怎样成功地帮助他们找到正确的实施方式?你能做的最强大的事情之一就是利用所谓的康威规则:团队构建的系统最终将与构建该系统的团队的沟通与组织结构相匹配。因此如果你的软件被分成多个组件,那么你需要一支紧密团队构建一个组件,另一支紧密团队构建另一个组件,第三支团队构建第三个组件,并使它们与技术选择保持一致。前端人员应该负责前端,这听起来像是说废话,但有些时候人们就是会犯错误。“前端团队,你们负责Angular、React或者JavaScript,你们这边负责F#,你们这边负责计算、后端和报价。”你甚至可以利用地理来实现团队分组:Angular团队在伦敦,F#团队在白俄罗斯Android团队在波尔图。地理距离拉开之后,团队分组的界限会自然浮现,因为协作真的非常便宜,而与另一个时区的团队合作修改软件真的非常花费。这就是你作为架构师的地方参与软件构造的方式。

你有一个前端团队,前端团队正在构建插入 API 服务器的代码,那么一开始就要告诉他们:“我们要伪造一些 API 响应,好让你们开始工作。”另一边你再告诉其他后端开发团队:“我将帮助你们构建API 的测试套件文档,然后你可以去构建满足这些要求的客户端。”如何向团队传达你的设计?你创建数据,你创建测试,然后你让他们去构建实际的代码。然后你可以将这两部分相互嵌合。作为一个架构师,你要在这里查看系统中发生的情况并查看流量。你是否看到了你期望看到的数据结构?延迟、吞吐量和流量是否符合你的期望?经常被提起的问题之一是架构师是否应该仍然亲手编码?是的,绝对的。因为如果你停止编码,你就会丧失在码农眼中的信誉。但是不要在你正在开发的系统里编码。你有一个改进架构的好主意,那么迟早你会屈服于诱惑:“我懒得更新图表,懒得开会安排别人去实施,我自己动手好了。”一开始你的团队会大感意外:“你到底做了什么?”你说:“你们看现在架构好多了。”第一次出这种事,他们会说“挺好挺好”,第二次他们就会直接把工作推给你,这一来你就成了瓶颈。“你这么喜欢修改,那你就自己修改好了。”但是另一方面,你又必须保持控制权,写代码的手不能停,一旦停下来你的技艺就会钝化,就会跟不上软件构建的最新进度。亲手写代码是与团队建立可信度和良好工作关系的好方法。我发现架构师写代码的最好方式是构建监控系统。你可以在团队中挑选几个人,吩咐他们:“我想了解你们的API正在做什么,我想在办公室墙上的大屏幕上显示流量。咱们几个一起来构建这个东西。”这样你既可以作为程序员充分了解该系统的工作原理,同时又不必对你正在构建的面向客户的系统当中实际投入的任何东西负责。你亲手构建的东西只会在墙上运行,不过这足以让你产生主人翁意识:“你们看,我的代码也正在运行。”其次,这样做还让你有机会与人们合作,向他们学习,分享建议和智慧。大多数架构师在开始专门从事架构之前都是非常优秀的开发人员。你的经验与技能很有价值,但是依然要避免成为瓶颈。

很多时候情,特别是当你决定要使用现成的服务,或者将软件的某些部分托管在某处,或者与支付提供商集成的时候,作为业务决策这些都很有意义,因为这样做很有效。但对于团队中的开发人员来说,这种体验通常很糟糕,因为他们往往要应对讨厌的api, 签名的xml,加密签名以及奇怪的沙箱之类的东西。开发人员的眼里没有商业价值。几年前我遇到过一个真实的案例。我们将一大堆东西从内部系统移植到 Microsoft Dynamics。Dynamics 作为 开发工具有一些有趣的功能,但是也有很多方面难以处理,团队感到有点受压迫。然后有一天开会的时候我说:“你们还记不记得去年每个星期一早上都得有人花两个小时从数据库中提取邮件列表,以便营销团队可以发送每周简讯?”他们都说:“是啊。”我又问道:“你们有没有注意到我们不再这样做了?”他们都说:“诶,是啊。”当业务问题得到解决时,开发人员很少看到解决方案。作为架构师,你的工作就是替他们去看:“还记得我们曾经不得不做过哪些恶心人的事吗?如今我们用不着再这么干了。这就是为什么。”传达这些决策正在创造的价值,与团队中的其他开发人员配对,构建Dashboard,构建监控系统,查看网络流量,不要让自己成为瓶颈,所有这些都是你可以用来构建高功能团队的协作模式,从而允许响应变化的行为得以发生,而不是一味遵循计划。你当然有计划,但是你并没有与计划绑定。如果计划出了错,你就得制定一个更好的计划。

有一幅经典的 xkcd 漫画,题目是“如何编写好的代码”。我们做事求快还是求对?如果你做得快,软件能运行吗?不,不,不,勉强能运行,但是代码好像糊成一堆的意大利面,不如重新开始。如果你做得对,代码写得很好,那就完了吗?没完,因为客户要求已经改变了。你知道如何获得好的代码?当优秀的开发人员查看代码,表示“这东西还能改进”,而且确实实现承诺的时候,好的代码就会发生。我们在此类活动中讨论的几乎所有内容都是关于如何构建更好的系统——框架、单元测试、集成测试、架构等等。架构师的努力方向是鼓舞开发人员的信心,让他们可以尝试他们的改进设想。架构是修改起来代价昂贵的东西。如果架构师的工作做得好,改变的代价就更便宜。有人可以打开一段代码,然后表示:“我想我可以重构它,让它运行得更好。良好的架构让人们能够做到这一点,让整个团队多年来一直做到这一点。就像我说的那样,验证很难。你得等上五年才能看到你架构的软件是否运行正常。如果不太正常,不妨轻轻地导引一点点。但是归根结底,架构师的存在是为了让优秀的开发人员能够查看一段代码,改进并且交付,同时很清楚他们这样做的时候没有破坏别的什么东西。谢谢。

Wiksy 发表于 2024-4-13 16:46

可惜一直都在小团队,大部分时间是自己搭框架自己用。
页: [1]
查看完整版本: 303-Dylan Beattie:怎样成为一名架构师?