共计 8415 个字符,预计需要花费 22 分钟才能阅读完成。
简介:在上一篇《业务团队如何对立架构设计格调?》中,探讨了一种业务架构的设计规范,以期达到这些指标:用规范束缚技术细节;用技术工具而非文档推广规范;继续重构而非造新轮子;器重业务建模。但通篇表述较为形象。本篇将总结团队近来的架构演进工作,以更具体的技术细节,具体阐释该理念,作为“对立业务设计格调”的实际篇。文中详述了多个层面的设计规约和基于规约的搭建形式,并在开端答复了上一篇的诸多疑难。
作者 | 木沉
起源 | 阿里技术公众号
一 背景
在上一篇《业务团队如何对立架构设计格调?》中,探讨了一种业务架构的设计规范,以期达到这些指标:用规范束缚技术细节;用技术工具而非文档推广规范;继续重构而非造新轮子;器重业务建模。但通篇表述较为形象。本篇将总结团队近来的架构演进工作,以更具体的技术细节,具体阐释该理念,作为“对立业务设计格调”的实际篇。文中详述了多个层面的设计规约和基于规约的搭建形式,并在开端答复了上一篇的诸多疑难。
二 总览
上图以电商产品为例,展现了一套规范框架的各层设计单元。先简略理解下概念,下一章节会具体解释各层的设计规约和搭建形式:
- 产品模式层
以产品合约形容残缺的性能列表;以签订人身份来定位产品性能的实用场景;以合约分组来形容一个独立齐备的功能域,分组的汇合就是产品性能的范畴和边界。通过对合约分组进行组装,能够疾速搭建商业产品。
- 业务模型层
为了缩小不同技术同学对畛域进行建模的格调差别,咱们对业务模型的应用场景做了诸多约定,串联起仓储治理 / 业务流程 / 业务组件等根底模块。所有人更关注于业务在模型上的表白,而大大减少了对实现细节的关注。基于对畛域的剖析,能够疾速搭建业务模型。
- 业务流程层
用一套规范的业务流程框架,形容业务模型的残缺执行流程:业务组件是一套高内聚的业务性能汇合,基于组件配置将业务模型的信息适配为规范参数,交由基础设施执行具体性能;流程引擎负责创立和治理流程实例,接管指令来触发组件动作的执行,并实现状态推动 / 条件跳转和异样解决等分支管控的需要。通过对业务组件 / 基础设施的形象和积淀,能够疾速搭建业务流程。
- 数据视图层
用一套规范的数据流机制,来满足视图层的定制化需要:数据流订阅器用于采集数据,物理起源蕴含区块链跨链数据 / 业务 DB 数据 / 文件系统数据 / 离线工作数据等;数据流生产器用来加工原始数据,生成展现层数据 / 待核查数据 / 数据指标等等。订阅器确保了数据起源的稳固和低成本的疾速接入,生产器则交由技术同学自行定制业务逻辑。在不烦扰领域建模的根底上,能够疾速搭建数据视图。
三 规约详解
1 产品模式
产品合约
1)规约
产品合约以全局视角,形容残缺的业务模式,包含:服务的指标客户,依赖的业务畛域,输入的服务等等
产品合约的内容是一份动态形容文件,须要由签订身份列表来界定应用场景
2)实例
以电商产品为例,商家独自签订的产品合约被作为商家合约,形容了商品的上架要求;商家 + 平台 + 买家独特签订的产品合约,则实用于交易下单场景。
3)搭建
新增 / 批改
低代码:基于业务需要,在产品核心设计产品模板,明确合约分组和具体内容
应用:
接入时编码,一次性:在业务零碎内编写对应产品合约和签订身份的模型类,实现和产品核心的对接,包含合约的创立 / 生效,基于签订身份的合约查问等等
合约分组
1)规约
- 合约分组以部分视角,形容某个高度内聚的业务畛域所提供的性能和依赖的配置信息,包含:业务模型,业务服务,业务流程,业务组件等等
- 多个合约分组独特组成一个可交付业务的产品合约
2)实例
电商产品合约下,商品分组形容了商品上架的流程和配置,下单分组束缚了订单创立的流程和服务信息,退货分组则阐明了退货流程和买家可能享受的客户服务。
3)搭建
新增 / 批改
- 低代码:以元数据的形式定义一个合约分组,蕴含模型 / 流程 / 配置等等,每一个配置都能够用键门路 / 配置值类型和限度等形容
- 应用
硬编码:在业务零碎内定义合约分组的模型类,实现与产品合约内容交互的写入和读取,在业务代码处显式获取业务分组实例
低代码:搭建合约查问 -> 分组解析 -> 配置获取的通用框架(引入缓存防止反复查问),业务层只须要通过元数据形容,就能够获取对应分组内的配置信息
2 业务畛域
模型
1)规约
- 业务模型形容一个畛域内的外围业务实体,是惟一贯通业务流程和业务组件的业务实例
- 一个业务模型内能够关联其余模型,但应避免出现循环依赖
- 一个齐备的业务模型形容须要蕴含:数据模型,视图模型,业务模型 / 数据模型 / 视图模型的三者转换,业务模型仓储等
2)实例
退货业务,基于退货单推动业务流程,各业务组件从退货单获取必要的业务信息,执行退货 / 退款 / 告诉等业务性能;退货单关联自一个正向订单,但正向订单不可反向依赖退货单;一个退货单模型对应一张主单据表和多张退货明细表,仓储须要负责实现业务模型 <-> 数据模型的双向读写
3)搭建
- 硬编码:编写业务模型 (Model)/ 数据模型(DO)/ 数据交互(Mapper)/ 视图模型(VO)/ 转换层(Converter)/ 仓储(Repository) 等等
- 低代码:用元数据形容,主动生成 DO/VO/Mapper/Converter;基于底座提供的仓储组件,也能够通过元数据形容,主动生成业务模型仓储的实例
服务
1)规约
1、业务服务是一套以业务畛域为单位 (interface) 作聚合,凋谢给内外所有应用方的最小业务性能单元(method)
2、业务服务须要一套定义标准(annotation/aop 等),对每一个性能单元有清晰直观的元数据形容,用以实现服务发现 / 文档生成 / 权限管控 / 稳定性保障等等。元数据包含:业务域,业务动作,读 / 写,错误码范畴,返回值模型等等
3、业务服务的入参,限度为一个 sysParam 和一个 bizParam,前者为调用起源 / 幂等 ID/ 产品码 / 租户 ID 等零碎参数,后者为各业务自行定义的模型参数,倡议为可全链路透传 (rpc->api->flow->component) 的 POJO
4、业务服务以 Result 模式返回,错误码尽量管制在元数据形容的范畴内,不透露任何 exception 给调用方。返回的业务信息,倡议为 POJO 或 VO
5、业务服务不局限于调用方的物理起源,只须要在对接层减少简略的转换逻辑,做受权管控即可
6、写服务的实现,须要有事务管理机制
2)实例
public interface DemoOrderService {
/**
* 下单申请
* @param sysParam sysParam
* @param bizParam bizParam
* @return result
*/
@ApiFunction(apiType = ApiType.SUBMIT, funcBiz = "ORDER",funcAction = "APPLY",
returnType = OrderApplyResponse.class, errorCodeType = CommonErrorCodeEnum.class)
CommonResult<OrderApplyResponse> apply(ApiReqSysParam sysParam, OrderApplyInfo bizParam);
}
3)搭建
- 新增 / 批改
定义 - 低代码:基于元数据形容,主动生成 interface+method+errorcode+POJO 等等
- 实现
硬编码:简略需要 / 不可模板化 / 无奈流程化的业务需要,间接编码
低代码:对于规范的流程发动服务(申请上架 / 申请下单 / 申请退货),用模板实现合约分组加载 -> 流程配置加载 -> 流程初始化(幂等)-> 流程触发 -> 后果解决;对于规范的流程推动服务(告诉回执 / 调度推动),用模板实现流程配置加载 -> 流程触发 -> 后果解决等等。随着更多服务场景的呈现,能够有更多模板化的业务服务。
- 应用
硬编码:与所有 interface 的应用一样,组装申请 -> 调用 -> 处理结果
低代码:基于元数据形容和业务配置,将以后业务对象 / 内部参数映射为服务入参的 POJO,异样解决模板化,胜利返回的后果以同样形式映射回业务对象或内部响应
流程
1)规约
1、Flow 用于形容一个残缺的业务流程,基于单个业务模型,推动一个或多个业务子环节
2、对于单个业务模型的同一类型业务流程,能够有多个 Flow 定义,以满足不同业务模式的定制需要
3、Flow 蕴含迁转 (transition),组件 (component) 和动作 (action) 三级构造,运作原理如下:每次触发 (operate) 对应于组件的一次 action,所有 action 都胜利的 component 会完结,而所有 component 都胜利的 transition 将会触发 Flow 和业务模型的状态迁转。
4、Flow 的指标是将简单流程拆解成多个原子化的业务动作,互相解耦
5、Flow 须要联合业务服务 / 音讯 / 调度等调用入口的触发,能力实现齐备的流程推动
6、Flow 须要依赖内部调用方提供事务管理机制(通常是业务服务),须要依赖业务模型仓储来管制模型的加载和存储
2)实例
3)搭建
新增 / 批改
低代码:Flow 本身的运作由底座组件撑持,只需一次性编码;若须要定义业务流程,可基于业务组件模板和业务模型,动静生成 Flow 配置文件;加上版本控制和隔离机制,就能够避免兼容性问题
应用
硬编码:Flow 初始化场景,从以后业务畛域的合约分组中,获取须要的 Flow 配置,初始化流程并推动;Flow 推动场景,基于 modelId+modelType+operate+request,能够用模版化代码主动触发
低代码:通过对合约分组中 Flow 配置的标准化,能够将 Flow 初始化场景也以模板化的形式实现;当一个现有业务服务须要反对新定制的业务流程时,只需调整合约内的配置即可
组件
1)规约
1、业务组件是某一类业务动作的聚合,面向业务功能设计,不局限于任何一个业务模型
2、业务组件的业务动作,是原子化的最小业务单元,粒度暂无强制要求,但以解耦和复用水平为掂量根据;倡议其依赖一个到多个基础设施 / 业务服务,以模板化的形式提供规范的业务动作实现
3、对于某个业务模型,业务组件通过凋谢适配器 (详见【基础设施 - 适配】) 的形式反对受控定制,或以齐全复写的形式实现排他定制(不容许其余业务复用)
4、所有的外围业务逻辑,都应收归到业务组件层及其以下(无流程的简略业务服务除外),包含但不限于:参数校验,业务校验,重入 / 幂等管制,业务模型变更,合约分组变更,计算规定,内部服务交互等等
5、业务组件须要一套定义标准(xml/annotation 等),对其反对的业务动作和业务模型有清晰直观的元数据形容,用以搭建业务流程。元数据包含:业务动作列表和对应的触发点(operate),反对的业务模型列表
2)实例
核身组件定义类
public interface BizModelDiscountComponent<T extends BizModel> extends BizModelComponent<T> {
/**
* 占用优惠
* @param context
*/
void occupy(FlowContext context);
/**
* 退回优惠
* @param context
*/
void refund(FlowContext context);
}
核身组件元数据配置
核身组件模板化实现
适配器 Adapter 的解释,详见【模型适配】大节
public abstract class AbstractBizModelDiscountComponent< T extends BizModel> implements BizModelDiscountComponent< T> {
@Resource
private DiscountApiService discountApiService;
@Override
public void occupy(FlowContext context) {
// TODO AdapterConfigInfo 依据 context 从以后合约中获取
T bizModel = (T) context.getBizModel();
getDiscountAdapter().processOnOccupyResult(
bizModel,
discountApiService.occupy(getDiscountAdapter().toOccupyInfo(bizModel, new AdapterConfigInfo()))
);
}
@Override
public void refund(FlowContext context) {
// TODO AdapterConfigInfo 依据 context 从以后合约中获取
T bizModel = (T) context.getBizModel();
getDiscountAdapter().processOnRefundResult(
bizModel,
discountApiService.refund(getDiscountAdapter().toRefundInfo(bizModel, new AdapterConfigInfo()))
);
}
@SuppressWarnings("unchecked")
protected BizModelToDiscountAdapter< T> getDiscountAdapter(){return (BizModelToDiscountAdapter< T>) FlowInstanceFactory.instanceBizAdapter("DISCOUNT", (Class< ? extends BizModel>) TypeUtils.getRealClassOfParameterizedType(this));
}
}
3)搭建
新增 / 批改
硬编码:全新业务组件根本无奈低代码化,须要开发有足够的设计思维和大局观,衡量复用度和老本后实现初版;随着业务倒退,逐渐形象出模板化的业务组件实现;很多场景下,如果防止不了简单的定制逻辑,能够自行以策略 / 职责链 / 工厂等多种设计模式落地,这依赖于开发者的建模能力,不做强制要求
低代码:已有的业务组件利用于新业务模型的场景,如果曾经形象出合约配置 + 适配器 + 基础设施的规范模板,只需做合约配置即可(告诉 / 核身 / 存证上链等场景适宜)
应用
低代码:在 Flow 底座中实现业务组件的编排 / 发现和触发,一次性编码;实现 Flow 配置,即实现业务组件的拆卸
3 基础设施
注:此处的基础设施与 DDD 中的概念有很大差别,请勿混同
规约
基础设施是一套以高复用高内聚低变动的内部服务能力为单位 (interface) 作聚合,凋谢给业务服务 / 业务组件应用的最小性能单元 (method)
基础设施能够是对渠道能力的封装,如内部商家渠道服务 / 跨境渠道服务等;也能够是对通用技术能力的封装,如优惠服务 / 商品服务 / 客户服务等
基础设施和业务服务的差别在于:前者的外围性能通常由内部服务提供,在以后零碎内的外围职责是参数组装 / 场景辨认 / 返回解析和异样解决
基础设施的定义不依赖于内部服务,入参为自行定义的规范 POJO,返回值同样以 Result 封装,屏蔽内部服务的 exception 和业务异样,业务返回同样是规范 POJO
实例
基础设施 - 信息告诉
public interface NotifyGateway {
/**
* 告诉(邮件 / 短信 / 站内信)
* @param notifyInfo
* @return
*/
CommonResult<NotifyResponse> notify(NotifyInfo notifyInfo);
}
搭建
新增 / 批改
硬编码:基础设施的接入通常是一次性的,低代码的价值不易施展
应用
硬编码:在业务服务 / 业务组件等调用方代码中,组装入参 -> 调用 -> 解析返回
低代码:在业务组件中,基于下文将介绍的适配机制,能够实现:合约配置 + 模板化业务组件,低代码复用现有基础设施
4 模型适配
规约
- 模型适配用于连接业务模型和基础设施 / 业务服务,实现模型 -> 入参和返回 -> 模型的双向解决
- 在模板化的业务组件中,适配器和基础设施 / 业务服务的调用链曾经固化,各业务模型的组件实例只须要实现对应的适配器,即可实现业务定制
- 适配器通常与产品合约配置联合,形容业务模型 -> 基础设施 / 业务服务入参的映射关系
实例
适配器 - 业务模型 -> 网银签名
public abstract class BizModelToDiscountAdapter< U extends BizModel> implements BizModelAdapter< U> {
@Override
final public String getType(){return "DISCOUNT";}
/**
* 生成扣减申请
* @param bizModel
* @return
*/
abstract public OccupyInfo toOccupyInfo(U bizModel, AdapterConfigInfo configInfo);
/**
* 解决扣减后果
* @param bizModel
* @param result
*/
abstract public void processOnOccupyResult(U bizModel, CommonResult< OccupyResponse> result);
//...
}
订单模型 Order,须要应用优惠扣减服务时,须要实现适配器`
BizModelToDiscountAdapter:@BizAdapter
public class OrderToDiscountAdapter extends BizModelToDiscountAdapter< Order> {
@Override
public List< ConfigDef> getConfigDefs() {
return Lists.newArrayList(
ConfigEnum.DISCOUNT_TYPE,
ConfigEnum.DISCOUNT_TERM
);
}
@Override
public OccupyInfo toOccupyInfo(Order bizModel, AdapterConfigInfo configInfo) {
// 解析出客户抉择的优惠类型
return new OccupyInfo();}
@Override
public void processOnOccupyResult(Order bizModel, CommonResult< OccupyResponse> result) {// TODO 依据扣减胜利的优惠, 从新计算订单金额}
// ...
}
搭建
新增 / 批改
- 定义 - 硬编码:当业务组件和基础设施 / 业务服务呈现调用关系时首次定义,通常不再变更
- 实现 - 低代码:能够用一套灵便的合约配置形容映射关系,实现一次编码后只需配置保护;然而,这既依赖于 DSL 级别的形容能力,也须要业务模型和基础设施 / 业务服务的设计者,都具备较高的形象能力,老本较高
应用
硬编码:当业务开发形象出可模板化的业务组件时,即实现了首次接入;当基础设施 / 业务服务呈现新模式时,须要进行适配调整
四 总结
啰嗦了这么多,为防止被适度细节冲淡主题。最初以几个问题做个小结:
1 业务设计规范体现在哪里?
架构层面,从产品合约 -> 业务畛域 -> 基础设施,咱们对利用做了模块拆解,在不同层面设计了业务规约,束缚了各模块的职责;技术层面,通过多个底座组件,肯定水平上实现了平台和业务定制的隔离,限度了业务细节的无序分布。
2 业务设计只有适合没有规范,为何要强制标准?
标准的目标不是规范自身,本文提出的规范也未必适宜所有问题域。想传播的是,团队内须要有业务设计的某种共识和积淀,在每次迭代需要和每次我的项目产出的根底上,继续积攒继续重构继续优化,这对新人融入 / 个人成长和团队合作都很有帮忙。
3 如何疾速撑持业务,研发效力晋升体现在哪里?
须要明确的是,对于全新的业务需要,不会带来显著的效力晋升,甚至会为了满足设计规范,带来肯定水平的额定老本。但当多人合作,工作交接,或是现有性能局部可复用的场景下,会缩小很多不必要的沟通和保护老本。举例来说,当一个业务需要呈现时,研发人员须要做如下判断:
业务模型:是否须要新的业务模型,是否须要调整现有模型
业务服务:xxxxxxxxxxxx 业务服务,xxxxxxxxxxxx 现有服务
业务流程:xxxxxxxxxxxx 业务流程,xxxxxxxxxxxx 现有流程
业务组件:xxxxxxxxxxxx 业务组件,xxxxxxxxxxxx 现有组件
基础设施:xxxxxxxxxxxx 基础设施,xxxxxxxxxxxx 现有设施
产品合约 / 合约分组:基于上述判断,评估产品合约和合约分组的组装
带来的效力晋升有这样几点:业务畛域的每个模块相互解耦,研发过程并行化,投入人员 1 + 1 能够 =2;革新范畴更易于定位,资源评估更为精确,进度把控更加清晰;针对频繁变动且老本过高的模块,进行针对性的重构,影响范畴可控;上文中的很多处规约,都有潜在的低代码化可能,能进一步晋升搭建效率。
原文链接
本文为阿里云原创内容,未经容许不得转载。