架构设计和实施的对齐和同步问题

我的梦境 提交于 2020-08-09 14:41:09

本文是这个文档的逻辑延续:

in nek:早期架构设计问题zhuanlan.zhihu.com图标

上面这个逻辑写得高大上,但操作起来其实是有很多具体问题要解决的,没有这些操作策略,实际写作架构方案的同学会觉得不知道如何下笔。本文回答一下在实际实施中的具体问题如何解决。

首先我们要明白,一个真正的架构设计是必然涉及很多产品,部门,团队的。有不同意见也是肯定的。你非要“严谨”,这个东西就不用做了。你说你要开发某个版本,和开发经理沟通了吗?他们的人力排得过来吗?他们的开发预算能按时到位吗?就算到位了HR能按时招得到人吗?Marketing肯卖这个版本吗?你去找他们沟通,但你的方案十划没有一撇,讨论什么都是扯淡,而且你跟开发经理讨论好了,Marketing一定同意吗?你自己的态度轻如鸿毛,你叫得动谁?

架构设计是滚雪球,我们架构团队自己先滚雪球,达成一致,然后去和开发团队妥协,滚大第二个雪球,然后再用这个大雪球去碾压Marketing,然后去碾压FAE,碾压预研,碾压金主……这是做架构的常态。架构设计一开始就准备好了要去妥协的,如果你非要有洁癖,要求所有人都“一致”,你不用做了。所以,我们设计方案的时候总是站在一个“无私”的角度上来进行设计,让其他人反对你就是和自己的核心利益作对,这样你妥协的余地就大。而在做“无私”的设计的时候,逻辑限制是第一位的。大家都想要钱,但钱不能从天上掉下来的,你总得是个产品吧?软件产品是个软件,总得编程吧?编程总得用一个编译器吧?编译总会产生二进制吧?有了二进制总会在一个ABI兼容的环境上使用吧?……这些就是逻辑,谁都越不过去。你可以说我不用gcc而用llvm,我们无所谓,但前面那个逻辑还是改变不了,但你强调用gcc,我们接受后,它就变成一个限制了,这个限制会拒绝我们链接llvm的库,这可能又有人反对了。你说两个编译器都支持吧,很可能开发和测试团队就找你拼命了。架构团队的工作很多时候不是自己有什么观点,而是保证其他团队的观点冲突完了,我们的逻辑还是能做出一个能赚钱的产品来(当然,也可能是其他收益)。

所以,我们写架构设计,不要担心写错,你任何时候都是在有限信息上做决定的,只要没有明显的信息缺失,你就要猜和做判定,这是前提。但你先要保证你的逻辑是通的, 后面有人反对,你可以妥协,但妥协也不能跨越逻辑啊。这样我们就有一个越来越复杂的逻辑沙盘,在实际执行的时候,我们遇到问题,我们就知道我们向哪个方向去妥协了。

做架构设计需要有“公心”,架构团队不是独立于其他人的团队,你不能“责怪”其他团队,你就是他们,代表他们所有人做决定,如果你站在你一个小团队的角度上想问题,你就失职了。

好了,这是架构设计的其中一面。理解这一面,你至少应该可以动笔了。但只有这一面远远不够,我们需要考虑另一面:架构设计不能妥协的部分。

很多团队可以没有架构设计,他们收到需求后,就开始做PoC(Prove of Concept),写一些基本的代码,做一个几台机器的小集群,写几个前端,几个后端,看能跑通了,就开始正经收集需求,每个具体的工程师解决一组具体的问题,比如提供鉴权啦,日志啦,可靠性冗余啦,集群变大的时候就近做Cache啦等等,这种开发被具体的需求驱动,我把这种开发模式叫做“没有架构设计”,或者“放养式构架”。

这种模式就好像开一条大船没有船长,这些人肯定不会撞到看得见的礁石上,但等到闯入风险海域的时候,你看见什么都不好使了。

我们做架构设计的目的就是提前看到比较远的风险,比如你的硬件肯定是一代代做的,第一代卖出去了,第二代能否直接兼容第一代?能否让客户的机房混用你的多代设备?要做到这一点,你就会引入设计约束:新硬件后向兼容。但这个约束说来容易,在现实中其实非常困难,因为让硬件完全后向兼容,你的硬件的改进就受限了,如果修改你前面接口中一个bit,就可以提升30%的性能呢?如果要同时支持两种新旧的接口需要增加芯片30%的DIE面积呢?

所以,为了做到这个,你可能需要把你承诺“不变”和“可变”的逻辑分解出来,把“不变”的部分做成你架构约束。这是在“治未病”。这就是“有架构设计”和“没有架构设计”的区别。你完全靠需求来驱动,肯定不会考虑这种问题的,架构设计的作用就是提前考虑这种问题,在早期就开始抽象整个生命周期上的变化。所以架构设计总是从“概念空间”开始建模,因为概念空间是最难改变的,你决定每个设备分成多个虚拟设备,以虚拟设备为单位分配给虚拟机,这个东西无论你的虚拟设备是通过消息访问还是mmio访问,都很难改变。但具体这个消息是同步的还是异步的,这个东西就比较容易改变了。架构设计是通过概念空间建模,找到整个发展中最“难变”的部分,基于这个点来做约束,让这个约束得以坚持,从而收获那个未来的利益。

所以,你看,我们做架构设计都是做未来,做未来天然就会和现在的利益冲突。而且这个冲突,没有人会和你平衡。因为考察整个利益关系中,只有架构师这个职责是为未来负责的。如果你只遵循我前面的“道法自然”的思想,人家说啥你都可以妥协,那么,你这个“未来”,就没有人给你背书了。

这样,架构设计就变成“没有架构设计”了。架构师的价值就不存在了。

所以我给一个产品团队服务的时候,我首先会去确认这个产品团队的管理组织是否认为自己“有问题”,是否知道自己“强敌环伺”。如果这个组织觉得自己的开发一切都正常,“做得挺好的”。那我是不会留在那里的。如果你按部就班被需求驱动就能让你觉得安全,一切都Perfect,你不需要架构师。架构师只能给你没事找事。

换句话说,架构师是为你的现状做出改变的,你自己都认为没有必要改变,那我们就不要在这里浪费时间了。

这样,架构设计就需要一个妥协的底线。我们还是讨论前面这个例子,我们希望我们做出一个架构约束,实现未来硬件可以在用户现场混用。那我做H1硬件配合S1软件的时候,我就会给出H1_if,保证S1对H1的最小依赖。现在我做H2,我要求H2兼容H1_if,新功能做在H1_if+上,然后我开发S2支持H1, H2。这里,我增加了设计难度,但我买来了这个收益:H2可以直接取代H1使用。这个是否真的收益,其实要看市场域的,但我们假设这个有受益,我们在架构设计中坚持了这一点,买下这个未来收益。

但执行的时候这个可能很困难,假如我们没有做到,我们可以妥协,我们退一步:H2_if无法兼容H1_if,S1无法支持H2硬件,但我们可以保证S2兼容H1和H2。这样收益没有那么大,但至少用户还是可以混用H1和H2的。

好,假如你还是做不到。我们再妥协:H1必须使用S1,H2必须S2,两个解决方案还是可以混布。至少H1S1和H2S2可以互通(比如假定是一个RDMA协议,两者高层互通协议得通吧?)。

但这个也做不到呢?那你的架构设计就失败了,你连“放养式架构设计”都不如,那个没有获得H1和H2混布的好处,至少也没有浪费时间在跟着你“设计未来”,养了你这么个废物,开发额外的代码。

不少号称的架构师都是这样的废物,他们做的“抽象”,“封装”经不起被封装的接口的改变,或者那个位置根本就不发生实例的改变,他们说一些说了等于没说的概念和原则,这些概念或者原则的效果要不和放养式设计没有区别,要不就只起反作用。这些就是做了个架构的“样子”。但架构需要“收益”背书,不是一个“样子”。

要避免这个问题,就是设计功力的问题了。但作为一种实践,我的意见就是:在你的架构设计文档最前面确定好你要解决的问题,说明你的设计想要得到的核心收益是什么,你的所有设计(包括你后面的妥协),必须用这个核心收益作为底线。你可以多放几个这样的核心收益,这样你妥协的机会就大很多,搞不定一个,可以看看能否搞定其他的,等你所有这些收益都“妥协”完了,没人赶你走,你自己……看你要不要勉强了。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!