借降本增效之名,探索开闭原则架构设计
作者:京东科技 胡灿海
引语
在我们的研发生产活动中,经常会遇到如下类似的疑惑:
业务和技术在公司组织活动中,究竟应该各扮演什么样的角色?
技术的目的是什么?
研发生产活动中,如何提高生产事故发生的下限?
如何充分提高isv或者外协人员价值最大化?
《人月神话》说优秀程序员是普通程序员研发效率10倍,如何可以提高研发效率水位线呢?
如何避免《人月神话》指出的“焦油坑”?
如何更好的对老系统进行ddd升级?
这些疑惑单独看都可以有很多的解决思路,或者从制度层面解决,或者从技术层面解决,或者业务层面解决,等等,甚至也有可能出现某些解决思路按下葫芦浮起瓢,但如果将这些问题统一起来看,是否能找到他们对应的共性,尝试从最底层的逻辑找到问题解决的切入点呢?
疫情启发
新冠疫情持续了三年时间,让咱们的生活发生了很多与之前不一样的改变,比较典型的一个现象就是我们在公共场所的椅子上会要求进行隔位相坐。经过长期的观察,发现很多场所这样的要求和提示如同虚设。我们不讨论政治和经济,单纯从实现设计的维度来思考如何让这个要求能落到实处,实实在在的帮助我们更好的进行科学防疫。以下是几个场合的隔位相坐实现方式:
我们拒绝红灯思维,认为每种实现方式在那时那情那景下都是最优选择。从这四个实现方式中,我们可以发现从效果和美观上来看,是可以认为存在一个递进的关系,极其类似我们的系统的演化过程。假设卫健委给出行政要求,公共场合必须要将隔位相坐落到实处,或许能有人挖掘出一种商业模式,即提供隔位相坐最优解决方案的能力和服务,从中赚取服务费用。毕竟不是每个目标主体都能在当时情景能实现最佳,或者需要更大成本才能实现较佳。
系统实现反思
为了得到高质量的软件产品,我们是应该把精力更多地集中在提升其中每一个人员、过程、产出物的能力和质量上,还是该把更多精力放在整体流程和架构上?—— 《凤凰架构》
系统的行为价值 和 架构价值 到底哪个更重要?——《架构整洁之道》
系统是演化发展的,根据疫情隔位相坐实现方式的启发,系统是否可以以巨人肩膀为起点开始演化发展?
对于以上反思,下面尝试从一种切面来和大家一起探讨。
统一沟通语言
有很多的方案的讨论最终达不成一致,很大程度在于双方沟通语言不统一,即双方讨论问题最基本的基石基础并不是一致的,所以怎么讨论都不可能达到一致的结论和目标,所以我们首先统一一下沟通语言。
我们知道,咱们作为一个商业公司,最底层的逻辑肯定是商业盈利,那么我们作为其中的一员,我们每个人有以下三个角色(注:以程序员岗位进行分析),每个角色的职责价值尝试做如下解析:
个人角色
曾有企业家有言:一个企业的边界取决于其创始人的认知边界,其实对个人也是如此,一个人的价值大小也是由其认知边界决定的。个人角色短期来看,对咱们解决方案讨论意义并不是那么重要。这个也不是能很快改变的。暂且忽略影响。
公司职员角色
员工的任何公司任何活动都应该朝着有利于公司市场竞争优势的方向进行的。甚至可能还关注公司第二曲线,在我们公司文化里面还倡导第三曲线;
程序员角色
我们认为技术的最终目的更应该是降本增效,具体体现为业务初创期低成本快速迭代,业务成长期快速低成本规模化,以及将以上低成本能力抽象成能力光环,从而实现助力业务快速迭代,以及释放创造力助力管理。
两个概念
回到本文主题,本文主要是尝试通过探索开闭原则架构设计来实现降低认知负载,从而达到降本增效的目的。因为在研发活动中,我们的关注点越发散,会越容易降低我们的研发效率,所以本文的目的是想通过系统遵循开闭原则架构进行设计,保证系统的职责的清晰和单一化,以收敛研发的关注,保证程序员能集中精力将事情做好。主要从加强系统纯洁度维度来尝试进行阐释。
开闭原则,耳熟能详的原则,其比较关键的特点在于,系统或者模块的只读性,以及和 职责单一原则的一体两面;如此在我们的研发活动过程中,可以将稳定的需求和 常变的需求,通过组合的方式将不同的模块进行扩展。而稳定的需求我们其实是可以进行产品化封装的。
凤凰架构的逻辑
凤凰架构的思想是参考生命系统的可靠性和稳定性,希望通过一系列不稳定的子系统来打造一个稳定可靠的大系统;而其实生命系统的可靠性也不是一蹴而就的,并且也只是一个稳定且发展的文明系统的载体;这个文明系统的演化过程非常类似咱们需求交付的过程;
通常比较主流的观点对于文明的演化理论是进化论,进化论来源于达尔文的《物种起源》的进化树,而进化论其实存在未能解释的空缺,即为什么进化树是由单细胞向多细胞进化和低等生物向高等生物进化而不是相反,以及进化与熵增定律和质能方程E=mc2冲突,即进化来源于什么?有学者提出一套演化理论即“递弱代偿”理论(不讨论其争议性,只分析客观逻辑),解释了以上空缺。即从30亿年前单细胞到软体生物到脊柱生物到人类,物种伴随的文明越发达,而物种的存在度空间会越小,因为单细胞是全能的,从吸收到排泄,以及繁殖都能实现,而人类的组织,已不再是单细胞而是多细胞高度分化成不同功能的独立的组织,而某个组织也只有某个功能,放弃了单细胞其他大部分的功能。因此随着文明的愈发达,而文明当前的载体分化程度越高以至于产生了新的物种。而分化的程度越高,诞生出来的新物种的存在度会越低,如同上图右公式图,即物种的存在度与系统的文明发达程度成递弱关系。(参考《物演通论》)
这极其类似我们需求交付过程,即单个系统不再是万能的,而是分化成不同的小型子系统,而通过每个系统继续高度的分化和升级,使得整个大系统的能力越来越丰富和强大。
而我们的系统分化的原则就应该是上述的开闭原则和单一职责原则,这才能保证每个系统能独立的分化和演进,保证了在需求迭代的过程中,整个系统可以不断的进化为新的业务物种形态,并且进化过程中依然可靠。
在一个系统内,进化的本质是替换部分组件使之成为新的物种,而不是当前物种的升级;而系统最终升级演化的趋势就是系统内所有组件都能敏捷替换,修改一下路由,很低成本替换组件,这样优化系统的成本会越来越低。
软件系统的逻辑
我们再来分析咱们软件系统的结构,主要分两部分,一部分是基础设施,一部分是业务部分;而基础设施主要是冯诺依曼体系;而在讨论开闭原则时,最典型的案例就是冯诺依曼体系;
冯诺依曼体系可以简化为cpu,存储,输入输出;正是这套扩展性非常强的体系支撑着在计算机世界的发展。cpu通过元指令和指令流的分离,数据与计算的分离,并且提供中断回调,来落地了开闭原则,保证了多么复杂的需求的实现都不再需要修改cpu了;而将变化的业务交给输入输出;上面的操作系统则将冯诺依曼体系进行了封装,提供了方便的操作方式。
试想:能否将上层的页面模式的设计思路也复用底层的基础设施的设计思路呢?在最外层再提供一层“操作系统”提供使用呢?
再反观现在行业的各种服务化,SAAS,PAAS,IAAS 其实也就是这种思路的体现和落地。
星链的逻辑
货指的是一些业务侧和中台侧的能力,中台侧能力如商品、支付、风险等,业务侧能力如账户、交易、账务等。
人包括各类角色,如消费者侧的预授信用户、运营侧的推广人员、商户侧的结算人员等。
场是人与货发生交互的场所和方式,人可能通过各类介质如金融APP、商城APP、小程序、H5等与货交互,通过各类产品与货交互,通过各类运营方式、不同流量来源来与货交互。
货是相对稳定的,一般不是面向特定人和场的,是沉淀的业务和中台能力,构建货的能力,消金内部借鉴的是领域驱动设计(DDD)和中台化的思想,这些能力沉淀下来的是相对稳定的、与场景关系不大的领域原子微服务。
而这个思想不正是开闭原则的另一种表达么?
业务垂直拓展思考
这是对不同复杂度的系统的一个简单概括总结,我们的系统可能处于高级别分布式系统的层次,那我们再思考一下我们的业务系统,我们进行垂直拓展的颗粒度能达到什么级别呢?
从通常ddd的分层的思路来看,我们可以尝试将系统将应用层,不同场景的聚合中偏客户端的模块交给 上层接入层,是否可以将接入层单独抽离成独立系统,比如交给星链来实现(如果不用星链可能会比较重),以保证了领域与接入层的相互独立。而领域层再根据子领域的情况按照开闭原则进行垂直拓展。
架构探索
通过以上分析,如果我们尝试将冯诺依曼的设计模式上移到业务系统,,让我们的系统职责和业务角色收敛关系更清晰,同时保证业务子系统做到尽可能只读,如果有新的业务我们去分化重开系统;
我们可以尝试用星链来实现业务操作系统,梳理各业务系统的职责,梳理出稳定系统,周边业务系统,以及公共功能系统,并且可以将比较稳定的业务系统进行产品化。去尝试探索一种新的商业模式。
另外,其实咱们在推行ddd的过程中,通常会比较严格的按照战略战术的模式,重建领域模型,但是在实际生产中,我们的很多老系统都背负很重的业务量,轻易重构数据结构,风险会非常大,其实我们可以尝试按照开闭原则,先试图对老系统进行分化出新的系统,将系统的api进行收敛到同一个领域内,等这第一步完成后,可以在考虑在当前领域内实现领域模型的梳理。
或许这可能是开闭原则下比较理想的架构模式,复用京东bigboss文化的宣传语:
积木式组织—探索未来式,人人是boss;
积木式系统—探索未来式, 职责要清晰;
而积木式系统,必然是比较整洁的系统了,自然当关注某一个模块的业务的时候,就只需要将认知主要集中在当前模块即可。而对于一些重复通用的功能,研发可能甚至只需要关注输入和输出即可,这样相当于通过职责的抽象将对应的能力打造成了能力光环,只要涉及到相关的研发的同事,天然就具有了这方面的能力。
扩展思考
在我们的业务系统中,常常通过异步消息来实现通信的处理,可能会存在一种方式,就是将我们的mq的监听和业务处理混合在一起,当mq的监听比较少的时候,或许系统还算整洁;但当我们的系统监听非常多的时候,这个系统似乎就成了大杂烩了,什么业务都可能会有。这样导致这个系统的职责非常的不清晰。
而业务监听本来就应只是一个系统的共用功能,是可以将其抽象为平台功能,所以按照以上开闭原则设计,我们提供监听后对应业务的处理接口,在监听之后自动调用接口即可。该系统只负责做mq监听的处理。系统角色草图如下:
写在最后
在我们生活中,发现问题的时候,大部分人只是看到了当前现象,而少数人看到了这个现象背后的原因,而只有极少数的人能全面看到这个现象的底层根源,从全局的视角寻找解决方案。而第三者应该是我们追求的一种境界,这应该是工程师文化/工匠文化的体现所在。此所谓:
众生畏果,菩萨畏因,佛畏系统