树-图架构(TGA)
前言
本文描述了一种软件架构思路,灵感来源于思维导图,这是人类普遍接受的信息组织方式。以下内容涵盖了数据库设计范式及模块依赖的设计范式。本架构仅适用于百分之91需要人工编码的业务系统,不适用于基于大模型、AI的系统。
树网的形状
对于信息的组织和处理具象化到逻辑图上面,人们更容易使用思维导图来描述。思维导图是一种树形结构,然而大部分实际业务逻辑中会包含少量复杂的耦合结构,这也是易于出bug和混乱的部分,这些思维逻辑反馈到图上是一种多对多关联的网状结构。因为大部分业务系统的还是以树形结构为主,所以称这种设计为树图架构(Tree and Graph Architecture ,简称TGA)。
下面的图片反应的是一种基于RBAC用户体系的树网架构图,以系统最为最上层节点,子节点分为RBAC用户体系,RBAC用户体系内用户和角色、菜单、部门、权限是一个多对多关系即为网状结构,出口处为用户切换部门和角色对各个功能表为一对多关系,即各个功能为RBAC用户体系的子表,树状结构。我们可以看到整个系统的主要的形状还是一个清晰的树状结构,而较为复杂的用户体系已经有RBAC这样成熟的用户体系作为一个独立的支撑模块。
数据库设计
数据库设计的前提条件是要满足BCNF范式,即每一个表职能单一,比如用户信息表就存用户信息而不能把用户信息放在用户角色关系表中,这样做的目的是为了避免逻辑混乱谬误耦合。然而对于高并发型系统或者联结系统不可避免数据的冗余,且冗余也可以避免程序员写连接查询的SQL语句,经过笔者这么多年的实践和观察,数据库连接查询极易造成业务系统的性能瓶颈,且在未严格符合BCNF数据库设计范式(主外键关联)的情况下,查询出的数据常常是不准确的,且维护SQL的成本高易出错。所以在这宁可冗余也不推荐关联查询。
既然冗余无法避免但我们可以约定以下几点即可解决冗余的弊端:
- 冗余的数据仅作为前端系统查询使用且要严格保证冗余数据的一致性。
- 逻辑业务处理要根据键值实时查询业务表不可使用冗余值。
- 冗余的字段名要加表名前缀,这样在整个系统我们只要看到字段名称就能知道是哪个表的冗余数据。
综合以上几点我们发现即使使用冗余了我们依然可以看到符合BCNF范式设计的初衷,且结构依然是清晰的树型结构,为了区分这种设计我们称之为BCNF冗余范式,英文简写BCNF-R范式。
下面是一个点对点的任务通知系统的ER图,满足BCNF-R数据库范式。这种字段加前缀的命名方式在整个系统中不会产生命名冲突,具有唯一性原则,我们可以清晰的得知这个字段冗余自哪个业务表的哪个字段。
模块设计
软件开发中循环依赖或互相耦合是非常不友好的,不仅会造成业务逻辑复杂,维护困难,也不易产品化,复用不友好。诸如此类问题的根本原因通常不在需求,大多是没有很好的归纳信息导致的,以下是列举的一些循环依赖或互相耦合的例子及解决办法。
假设我们有某百万级级大型保险系统中3个模块,用户体系模块,联盟商城模块,保单模块。起初这是依赖简单的模块,商城模块和保单模块依赖于用户体系模块,用户体系模块独立。某天某产品经理提了一个需求:凡是2025年注册并购买了保单的用户在春节期间的关键的时间点给用户派发亿点点商城现金返利福利并给其家人发送新年祝福短信,且同类福利只发送一次,系统针对新注册用户使用同系统发放其他组合福利。
到这里我们看看A同学的做法:A同学一看需求,这简单我数据学的好,一个SQL搞定用户群体的查询,于是左一个连接右一个连接在商城模块把就把用户查询出来了或许觉得我只是查用户应该把他放在用户模块,需求很快完成上到正式环境,项目经理刚想夸这位同学干活效率高,业务部门就抱怨券发的慢,已经错过了用户的热情,于是咔咔一顿加索引优化sql加服务器,最后还是慢,甚至经历了锁表,给公司造成了经济损失,让运维部研发部等多个部门蒙上深深的阴影,最后得出结论用户量太大,只能分库分表,最后程序员在这堆复杂的sql上做分库分表适配又增加了一堆复杂的逻辑,最后整个系统乱成麻,谁来了谁骂娘,此时已经积弊良多,系统只能在这帮“老专家”的手里艰难的创造业绩。
我们再来看看B同学的做法:B同学要比A同学考虑的多,B同学考虑到为了避免出现循环依赖他新起了一个模块依赖保单模块查询购买了保单的用户ID,依赖用户模块查询2025年注册的用户详细信息,依赖联盟商城模块调用派发购物券API及根据用户等级的家人信息发送祝福短信息。最后B同学结合分布式事务、缓存技术费了九牛二虎之力终于搞定了这个需求,系统稳健运行,老板还看到了B如此努力和辛苦,不禁感慨我有一个好员工,业务完成过后是财务部门对账时刻,又是一顿咔咔的编码终于把帐理的八九不离十了,最后成果也是可喜可贺。
最后我们看看C的做法:C同样懂得模块依赖合理性的重要,同时他觉得查询用户信息就是用户模块的职责,没必要耦合其他模块写复杂耦合逻辑(都是研发维护成本),我只需要在用户模块中加一个打标签的API即可,在保单模块写一个批逻辑批量给用户打已购买某保单的标签,面对百万条保单也是几分钟轻松打完了一个批,面对新保单数据也是实时打标签,在商城模块给用户打已派完某某福利的标签。最后根据用户标签我们可以轻松得出想要的用户数据。
综上比较A同学的设计是灾难性的,B同学3个关联需求迭代的平均研维成本是大概是3人天,而C同学的研维成本半人天不到。
最后总结当下的大环境,百分之70的软件研发公司没有架构这一专职或合适的人员担任这一职务,所以或多或少的遭受A困境,因为大家的起跑线环境各不相同,所以软件研发成本难以比较,且造成该困境的问题原因非专业人才不能得知,更不易让老板所理解,所以大部分老板是蒙在鼓里的,只能重金聘请架构,然后重金聘请来的架构也只是尽力的解决当下的问题或表面的问题,因为技术在表述和boss的理解上都有困难,且这一职级调动资源不是那么的容易,所以重构这一词说起来挺难的。而笔者也是看到这些领域的诸多问题,在尽力寻找一个普适的架构设计,可量化的工作流程,来降低沟通成本,于是树图架构便应运而生,然后AI的发展另我感到一丝深深的不安,AI现在已经在信息的组织能力和逻辑的严谨性上超越了人类,现在已经出现了自动化工厂和无人驾驶客车,相信不久的将来AI编程将会取代百分之99的程序员。这个时间不会太久,5年左右,届时老板们是会笑还是哭呢,反正架构师、程序员、PE、PM都得哭。当然啦,时代在发展总会有新的改变和机遇,因噎废食岂有道理之乎?
原文链接:树-图架构(TGA)
https://docs.qq.com/doc/DWGRWY3ZSVnhTRXlG