高德信息业务DDD实战 - 聊聊用领域重构胶水代码
慧丰 阿里开发者 2023-07-27 09:02 发表于浙江
(资料图片仅供参考)
阿里妹导读
本文主要记录了高德信息业务DDD实战中如何用领域重构胶水代码。
一、背景
团队简介:高德信息业务us团队主要承接聚合下游服务(搜索、推荐、广告、离线、商服、营销等)面向端、车机等上游,持续、稳定的提供多行业、多品类、多场景的结构化数据服务。
目前高德信息业务门户有 美食、酒店、旅游、休娱、房产、商超、火客飞、周边游等行业或场景的portal页。由于每个业务的发展周期和节奏大不相同,每个细分行业下portal页的维护迭代不论是从产品、开发都是隔离的,自身团队的定位在没有严格统一的把控下比较容易产生胶水代码。这个现状对于信息业务的大目标-支撑好359行 来说是尤其困难的。
这种隔离方式导致各业务之间存在信息茧房,也就是面条式的产品逻辑和代码,唯一的交集是代码库,各组开发同学在没有portal页顶层设计输入的情况下,难有业务全局观,不同portal页各自开发,相同模块在没有统一设计和管理的情况下面临两种问题:
方案链路不一致,多种链路交替,各自维护; 存在重复逻辑,散落在不同应用中,代码各自为战,重复实现;在方案不统一、重复建设的情况下,us的portal面临着更长期的问题:
系统设计的质量不高,故障率和风险加大 开发维护成本大致随着portal页的数量线性增长 无知识管理、团队之间协作困难,容易产生信息孤岛和理解不一致 容易产生系统之间边界不清晰,加大维护成本二、目标
通过统一的、规范的、合理的系统设计做到增强复用、降本提效,提高稳定性
对明确的固定场景,有统一的、稳定的实现方案 提高设计质量和可维护性,降低故障率和风险 减少重复工作,降低开发维护成本 提高知识管理,促进团队协作,避免信息孤岛和误解 使不同团队、系统之间的边界清晰,减少内耗要达到这个目标,首先要找到业务持续演进的过程中,哪些是经常变的,哪些是相对稳定的。
结合信息业务的实际情况,不难发现行业是一个可变的因素,但是场景相对来说比较固定,也就是说同样一个场景,需要同时支撑多个行业,每个行业在同一时间点,会有行业专属的发展状态、定制逻辑。
当场景相对固定后,面对相同的场景,业务系统更期待的是相对稳定、统一的技术方案和链路。举个例子:portal的金刚位,业务站在金刚位自身去考虑,应该主要包括运营配置、算法推荐、广告植入这些重要功能,并且将这些特性和功能提供给每个产品或运营负责的行业阵地中去,当某个行业需要该组件新的特性时,可以统一考虑设计,从而可以将该功能延展到其他行业使用。同时当流程和链路统一后,协议也就很容易做到了通用和一致。
多行业多形态的业务迭代下,产品的设计基于行业,能力的沉淀考虑不同行业间的共性和差异,进而做到不同场景的复用。业务创新、能力沉淀、场景复用可以形成有效紧密的闭环。
三、设计
0、什么是GBF
GBF(Gaode Business Framework)是高德信息业务提供的一套用于业务身份+场景策略的一套业务框架,框架自身借鉴了TMF的理念,结合领域建设(DDD)的思想,为产品业务和技术开发之间提供一套完善的、高效的、跨行业、多场景的轻量级框架。
1、为什么要用GBF
GBF使用了 领域 的概念:在研究某个问题时,将复杂问题划分为若干个相互独立的子问题,以便更好地组织、分析和解决问题。领域划分的作用在US的体现主要有以下几点:
提高问题分析的精度: 使用划定好的领域,能够快速的将需求点定位到某个具体的问题域,从而将某一类问题归类管理,简化复杂性的同时也能够让领域内部的逻辑能更聚焦 促进知识共享和演进: 使用领域构建系统后,某个具体的领域交给专人维护,培养领域专家,做好领域模型表达促进技术和产品之间的交流和合作,促进知识共享,高效支持业务分析。 提高复用性,降低开发成本: 可以将相似的功能模块归为同一领域,使得不同业务能力可以共享同一领域的逻辑,提高代码的复用性。不同的开发小组可以同时并行开发各自的领域,避免小组之间的冲突和耦合问题,提高开发效率 提高稳定性: 划分领域可以将系统分解成多个部分,使得每个部分的功能更加独立,发生问题时不会对整个系统产生影响,提高整体的稳定性。拿个具体的例子来看: 各行业portal页的金刚位。目前us的portal页金刚位不同场景、行业均有不同的实现方式,如果涉及到不同应用相似逻辑容易有cv代码的情况
景区、周边游之前配置在了diamond,后来切到了bff-other(一个提供轻量逻辑的服务,包含运营配置) 休娱portal页取的merger-sp(一个引擎代理,屏蔽不同引擎间的差异) 房产portal取的house-sp(另一个商品搜索引擎) 其他场景例如附近页取的bast(一个推荐引擎),结合diamond配置有干预逻辑通过现状我们看到每个行业或场景的金刚位实现方案都是不一样的,不同的小组开发、不同的链路方案,意味着迭代维护成本居高不下,虽然目前的新方案在一个应用中统一对金刚位进行了收拢,但是只对输出进行了统一,底层的逻辑差异还在,且不同逻辑的实现无统一标准管理,不方便复用。
基于领域的系统建设,金刚位是一个具体的问题,适合放在一个地方解决实现。也正是基于 领域建设 这个抓手,将金刚位这个功能点统一组织、分析,拆解金刚位需要提供哪些能力,进而逻辑分类、链路归一,然后沉淀出金刚位统一的标准链路方案。
链路方案归一后,就可以统一输入和输出
bizId 身份id,代表不同行业(hotel、scenic、house、unkonw)。scenario 场景id,例如 portal(落地页)、nearyby(附近页)、search(搜索)。// 位置参数:依据推荐位id选择提供必要位置参数user_loc 用户定位(坐标信息)geoobj 图面信息(x1,y1;x2,y2)portal页场景一般不会有这个参数。cityAdcode 城市code// 透传公参diu、adiu、uid、gsid、csid、usid、div、superid、stepid、tid 、testid ajxVersion 版控traceAppId 应用idtracePageId 页面idtraceModuleId 模块id
{ "code": 1, "message":"success", "data": { "items":[ { "icon":"http://", //icon地址 "icon_height": 128, "icon_width": 56, "title":"海洋馆", //展示标题文案 "tool_tips": "元", //icon右上角的气泡 "log_info": {}, //上报埋点信息,需要算法产生的无业务语义只用来统计指标的埋点在这里存放,如果业务字段中已存在的这里不再冗余 "schema": "uri://" //跳转schema uri://path?city=${adcode}&lat=${y}&lon=${x} 入参us传,querysug替换占位符生成schema } ] }}
至此我们看到了us对金刚位的实现包括统一的链路、输入输出、逻辑管理,接近理想态的实现,无论是从复用性、开发成本、需求方案对接成本能够有明显的提升,稳定性建设也可针对某一具体的领域或功能点开展。
2、使用GBF概念设计
下面我们来看下,基于GBF的领域驱动设计理念去支撑业务开发,需要有哪些步骤
目前在各个域内的逻辑相对复杂度不高,为避免过度设计,按照指导原则进行聚合设计出来8个领域,支持在后续领域复杂度提升支持进行域的拆分。领域建设的指导原则大致分下面几类:
1. 用例分析中出现的业务实体、业务规则可以进入域模型的候选集;
用例分析中出现的一个或者多个对象,可以进入域模型的候选集。对应种类:业务实体、业务规则;
正例:运营规则描述了在商品、内容上的加工与干预逻辑,可以作为分域的参考实体。对照可参考淘系的限购域;
反例:搜索、推广对应的实体为doc,业务应用体现在商品、poi的id列表及标签。doc实体自身没有业务属性,属于系统内功能实现层的模型。引擎召回的标签属性归属于poi或者商品主体,故doc不能作为域模型的参考实体;
2. 领域建立的前提条件是明确稳定的实体与稳定的行为;
反例:面向场景、行业设计领域,由于场景、行业的不可枚举(发散、不收敛),会导致域的不稳定。比如酒店域、旅游域;
3. 如果多个实体间是归属关系,需要合并成同一个域;
归属关系定义:在没有父实体存在的前提下,子实体无明确业务语义。
正例:营销时有活动规则、优惠规则,运营时有干预规则。脱离营销活动、运营的限定下,规则自身没有明确的业务语义。规则需要分别归属至对应的父实体;
4. 如果多个实体间为引用关系则各自成域;
引用关系定义:多个实体同时在多个用例中出现。任意实体的业务语义不依赖其他实体的补充。
正例:商铺会挂接在poi上,在大部分业务场景下会同时出现。挂接关系属于引用关系的一种;
反例:参见归属关系正例;
5. 分域时需要参考组织结构关系;
优惠和活动是否合为一个域?是。业务行为逻辑耦合度较高,例如:秒杀活动使用优惠券的方式支持。同时在信息工程视角,优惠与活动都属于营销中心;
团队以前抽象和复用的角度主要关注点在链路上,缺少领域的管理,容易导致当链路发生变化时,各领域间的调用和依赖关系发生调整,协议也容易发生变化(系统模块间解耦不够清晰),不同应用之间出现逻辑相似度高但无法复用的代码。拿POI卡这个例子看,当抽象管理的维度添加领域对象后,可以归纳出如上图的结构关系,借此可以明确各领域的数据结构表达和管理规范每个领域之间的行为。当POI的核心领域和业务领域明确后,标准业务能力层的Process可以直接引用,两者之间只剩下引用关系,不再有任何的复杂加工逻辑。Process对应着不同的场景,自此POI的领域模型和方法对标准能力和场景解耦。
gbf应用分层
gbf对象分层
结构
流程
3、使用GBF开发
使用GBF实现一个简单逻辑,以us的金刚位调用querysug下游为例
1、在repository包里定义fetcher的输入reqParam、输出 PO,在repo impl中创建声明式fetcher
@FetcherClient(name = "sug-fetcher")public interface SugFetcher { @FetcherMethod(name = "quicklink") QuerySugResultgetQuickLink(@RequestParam QuickLinkReqParam reqParam);}
对接口服务的调用使用声明的方式编写代码,能够直观表达接口参数和协议的同时还可以借助业脉平台方便的批量导出文档。
2、在repository中定义repo接口,在impl中定义实现
public interface QuickLinkRepo { @Annotation(title = "获取金刚位") QuickLinkPO getQuickLink(QuickLinkReqParam reqParam);}@Servicepublic class QuickLinkRepoImpl implements QuickLinkRepo { @Resource SugFetcher sugFetcher; @Override public QuickLinkPO getQuickLink(QuickLinkReqParam reqParam) { return ((reqParam)) .map(QuerySugResult::getData) .orElse(null); }}
多这一层的目的是为了简单处理fetcher返回的结果,例如poi的merge逻辑、特殊情况下对fetcher实现缓存等操作。
3、定义金刚位的DO和入参 (这里入参没有特殊参数直接使用了基类),定义金刚位的DomainService接口,和对应的实现类。
@DomainService(name = "运营领域金刚位服务", domain = )public interface IQuickLinkDomainService { QuickLinkDO getQuickLink(BaseRequest baseRequest);}@Servicepublic class QuickLinkDomainService implements IQuickLinkDomainService { @Resource QuickLinkRepo QuickLinkRepo; @Resource IQuickLinkAbility quickLinkAbility; @Override public QuickLinkDO getQuickLink(BaseRequest baseRequest) { //构建请求参数 final QuickLinkReqParam quickLinkReqParam = (baseRequest); //请求金刚位服务 final QuickLinkPO quickLinkPO = (quickLinkReqParam); //根据返回结果构建金刚位DO(标准DO)可作为DTO输出 final quickLinkDO quickLinkDO = (quickLinkPO); return quickLinkDO; }}
抽象领域方法内的行为,生成金刚位的三部曲:构建请求参数、请求金刚位服务、构建金刚位DO返回结果。
这块是需要注意的地方,为什么要做接口的抽象?因为要做行为的管理,行为管理的意义分多个方面去看:一方面在于统一输入输出,将流程的代码逻辑放到实现类里,DomainService里的领域方法就可以比较清晰的表达出来;
另一方面接口抽象后就可以有不同的实现方式,这就和设计模式里的策略模式一样,GBF使用了bizId(业务身份,代表行业) scenario(场景id)作为策略的key,对应不同的行业就可以有不同的实现类,从而做到实现差异化的同时又能够统一输入和输出。尽管很多时候现存的差异化从长期来看没有存在的意义,作为短中期的实现这是比较理想的方案。
4、定义ability、实现action
@DomainAbility(name = "金刚位ability", domain = )public interface IQuickLinkAbility { @ActionExtensible(name = "构建金刚位请求参数") QuickLinkReqParam buildQueryParam(BaseRequest request); @ActionExtensible(name = "构建金刚位DO") QuickLinkDO buildKQuickLinkDO(QuickLinkPO quickLinkPO);}
@Componentpublic class DefaultQuickLinkAction implements IQuickLinkAbility { @Override @Action(name = "构建金刚位请求参数") public QuickLinkReqParam buildQueryParam(BaseRequest request) { return new QuickLinkReqParam(request); } @Override @Action(name = "构建金刚位DO") public QuickLinkDO buildQuickLinkDO(QuickLinkPO quickLinkPO) { return (quickLinkPO).map(QuickLinkPO::getItems) .map(Collection::stream) .map(itemStream ->(po ->() .title(()) .icon(()) .iconHeight(()) .iconWidth(()) .logInfo(()) .toolTips(()) .schema(()) .build()).collect(())) .map(QuickLinkDO::new).orElse(null); }}
这一步的ability定义和上一步的domain方法是紧密相关的,ability定义后一般会有一个默认实现,如果不同场景和行业有差异(例如hotel)就需要在us-app-hotel这个工程里写对应的Action实现ability。GBF底层是通过包名的方式()结合的配置(biz-id映射的package)去路由到对应的Action实现,场景这块则是根据@Scenario注解来作区分,这也是GBF基于业务身份和场景做策略的实现方式。
5、实现NodeService
@ProcessNode(name = "QuickLinkService")public class QuickLinkNodeService extends AbstractCommonNodeService{ @Autowired IQuickLinkDomainService quickLinkDomainService; @Override public QuickLinkDO doInvoke(BaseRequest request) { return (request); }}
Node的定位可参照GBF的相关资料,这里逻辑比较简单,也会存在逻辑复杂的场景,例如走merger链路的feed流,走营销获取活动信息盘货信息再走merger找回的运营位。
6、Process注册Node
//在ProcessConfig中声明NodeBaseNodeConfigBuilder quickLinkNode = new NodeConfigBuilder() .preJoinPoint(new JoinPoint() { @Override public BaseRequest join(PortalParam request) { return request; } }).nodeBeanName(());//processConfig注册Node @Bean public ProcessConfig portalProcess() { return new ProcessConfigBuilder() .request() .response() .nodes(userNode) .nodes(filterTabNode) .nodes(feedNode) .nodes(bannerNode) .nodes(quickLinkNode) .build(); }
7、接口注册
@RestController@RequestMapping("/process")public class ProcessController { @GetMapping("/portal/{biz}") @ResponseBody public Resultportal(@PathVariable String biz, PortalParam param) { NodeServiceprocess = ((_NAME)); (biz); return process == null ? ("未找到流程") : (param); }}
至此使用GBF实现一个简单完整的流程就完成了。
四、总结
基于领域建设的思想,使用GBF构建业务能力能够给US带来以下几点优势:
帮助us沉淀各领域的业务,标准化流程链路,明确业务逻辑; 需求拆解后能够有对应的领域收拢,各领域间无耦合,使问题更聚焦; 领域沉淀的能力方法能够很好的复用,不同场景间的功能节点基于领域能力去构建,构建好的能力可以在其他场景(附近页、会场、泛搜等)直接复用,提高开发效率; 进一步强化能力逻辑的表达,借助业脉系统可视化流程构建专业知识库,帮助开发同学快速、直观的了解业务,进而提高技术对业务的scense,有全局观的同时又能够方便把握细节,提高产品和技术、技术和技术之间的沟通效率; 可针对某个领域或功能节点进行稳定性建设,减少不同功能节点之间的依赖,提高整体稳定性;业脉对业务流程的表达:
信息工程服务是结构化 数据+策略 的体现,在标准能力的基础上建设“主题场景能力”,不同场景、行业组成的各式各样的页面可以由进行抽象出具体的功能节点,例如 金刚位、banner、feed流、优惠、广告、营销位、评论等等,每个功能节点是不同领域之间能力的组合,同时在不同场景和行业又可以有不同的逻辑。gbf基于业务身份(行业)和场景作为路由的key,同一个接口不同实现类来支撑不同行业和场景的差异,然后在Process层对各业务功能节点进行组织编排,从而形成标准的业务能力。
标签:
推荐文章
- 高德信息业务DDD实战 - 聊聊用领域重构胶水代码
- 9月起,海口城市低保标准提至690元/月
- 江苏徐州:瞄准“医保自由”,让群众身在他乡有“医靠”
- 【平安海南建设】这家超市用“分”不用“钱”
- Meta第二季度营收同比增11% 三季度业绩展望超预期
- 门票文创热销、“冷巷”建筑无须空调 成都大运会亮点太多了!
- 深圳建全球最大室内滑雪场 前海·华发冰雪世界预计2025年11月开业
- 金融监管总局:有不法分子冒充金融监管部门等实施诈骗
- 遵义竟然上榜避暑旅游榜单了,令人吃惊 7月5日,《2023中国候
- 事关房地产,两部门发布通知
- 美国总统气候问题特使克里将访华
- 在数字化转型的道路上逐梦
- 炎炎夏日适合夜健身
- 有人报警自称要抢银行?长沙警方通报
- 税优健康险产品迎扩容改革
- 广西临桂农村商业银行独董姚卓志任职资格获准
- 神秘消失的宝藏(关于神秘消失的宝藏介绍)
- 恩佐专访(上):进国家队就和梅西合了影;当大马丁对手不好受
- 甘肃白银:致富荷花开满塘 乡村振兴产业旺
- 广东自贸试验区提升战略:推进联动发展区布局,协同打造一体化营商环境
- “杂交猴”现身婆罗洲 科学家担忧不已:我们人类可能是罪魁祸首
- 龙胜平等镇庖田村党总支赴兴安县、灌阳县开展主题党日活动
- 河北省石家庄市2023-06-28 06:23发布雷电黄色预警
- 同庆楼:预计2023年上半年净利为1.25亿元至1.69亿元
- 均胜电子:预计上半年净利润约4.75亿元
- 新时代 新征程 新伟业 创建“五星”我先行丨甜蜜的“遗憾”
- take into consideration(take into account)
- 助学贷款怎么办理?
- 助力消费、引领低碳——兴业银行信用卡特色营销活动激发市场活力
- 李家超:若日本排放核污水 香港将扩大对日海产品进口限制
- 好评如潮的Steam良心游戏有哪些 steam免费游戏排行榜2023
- 10级大风+冰雹+降雨,今明两天河南这些地方要注意→
- 监控拍下!有人一口气买了200多万元黄金!警方出动……
- 本溪主干路滨河南路改造工程全面开工
- 惠而浦: 公司会积极响应国家政策号召,努力拓展相关业务
- 《女神异闻录5:战略版》情报节目第二期:新角色春日部介绍
- 两部门延长金融支持房地产市场有关政策适用期限
- 密封科技7月11日快速上涨
- 海码头茶话会Girls Talk 丨高考后花式过暑假指南
- 好评中国丨走进深蓝·向海图强
- 船行天下
- 玉米面发糕怎么切不粘刀?
- 计算机行业周观点:2023年世界人工智能大会召开,华为正式发布盘古大模型3.0
- 金融支持房地产政策延期:房企存量贷款有望继续展期,保障项目交付
- 纽约尾盘,标普500股指期货最终上涨0.27%
- 丁晓宏:用高科技手段保护敦煌
- 电钢琴什么牌子好(钢琴什么牌子好)
- 官方:2022年谈判降价和医保报销累计为患者减负2100余亿元
- 立足羊城,辐射湾区!广州地区烧伤创伤一体化救治体系建设项目启动
- 贯石发展以559.8万将其持有的苏州冠能22.5%股权转让给电管家
- 青岛援藏组启动内地大学生进藏“送课进校园”支教
- 价格猛涨4倍!网友:快用不起了!
- 税延养老险有望并入个人养老金制度 商业养老第三支柱进一步完善
- 这个雨天,张家界高速路管员有着“多重角色”
X 关闭
最新资讯
- 伊宁县夏收夏种工作全面展开
- 《英雄联盟》LPL 夏季赛季后赛落地西安,赛程公布
- 液态提升技术再次更新迭代 由2.0升级至3.0时代精细化三维立体美学
- 《巨齿鲨2》8月4日全球上映, 巨齿鲨化身“锦鲤”跃龙门
- 睡眠困难给你的卧室进行风水治疗怎么样
- 上海谊众董事孙菁减持1万股,减持金额77.11万元
- 出现奇特景象,画面震撼!网友:平行时空之门开启了…
- 做自己的超级英雄|奇瑞“期中考”超吉利长城,冲刺新高度!
- 日剧:直击人性,日本美女上位史
- 国内11家主流应用商店及分发平台基本完成APP签名及验签工作
- 第六届中国昆明东盟宠物博览会活动日程(附时间)
- 镍铁利润空间遭挤压,部分铁厂迫于库存累计六月停产
- 南阳市卧龙区财政局:“三聚力”助推科教文化事业蓬勃发展
- 古今交融!《新千里江山图•壮美陕西》诠释“何以中国”
- 2022扬州与中山两市的GDP及两市前十的上市公司营收情况
- 泰国《京华日报》:太平船务在湖南怀化开行铁海联运专列 直达马来西亚
- 湾区故事:“北上”已成潮流,港澳青年内地谋发展正当时
- 非遗保护传承关键在人
- 赛维时代,不可能成为小号SHEIN
- 「新闻早知道」杭州或将本周入伏;随意插队加塞,交警曝光;7月20日起,儿童乘火车须携带有效身份证件
- 打通居民区商店与轨交站点,南翔印象城北侧连廊开放
- 以下正确描述平行蒙太奇的是 平行蒙太奇电影举例
- 女孩中考总分742分,报考师范专科。这样的选择是不是很荒唐?
- 俄媒:对乌军援掏空美军工企业
- 华西妇幼健康门户正式上线,一站式解决患者医疗健康服务需求
- 辣椒怎么保鲜时间久 辣椒怎么保鲜时间久点
- 探索现实主义年代剧的青春化表达《梦中的那片海》研讨会举办
- “两岸学者面对面”:畅谈闽台音乐、戏曲交融互鉴
- 小泥人冰晶画加盟创业少走弯路
- 湖北推出一系列举措 为高校毕业生充分就业“搭桥铺路”
- 蔡国庆儿子引争议,6年全科免考毕业或升重点,晒近照五官似妈
- 机构评级股出炉 预调酒龙头最受关注
- 结神符10兑换码2023(结神符10兑换码2023一览)[多图]
- 政策“礼包”精准发力 实现企业和人才的“双向奔赴”
- 支付宝踩雷!被央行开出巨额罚单,罚单超30亿
- 山阴:总投资2040万!涉及北曹山村、段寨村、席家堡村……
- 厦门市气象台继续发布高温橙色预警信号
- Threads注册量破三千万,马斯克公开指责:是在 “窃取 Twitter”
- 神田爱花(关于神田爱花介绍)
- 现在的热,只是“预热”!下周将进入“三伏天”,广西天气如何?
- INBO国际合伙人Mark DEKKER:建筑更新并非只有拆除重建,要重视设计更新
- 王启蒙: 外汇黄金下周行情交易策略分析及黄金最新开盘操作建议
- 山东释放产业集群“磁吸效应” 为经济发展增添强劲动能
- 作业帮直播课学生端电脑版下载(如何解决学生不做作业)
- deere marchi_deere marchi
- 【何以中国】文脉颂中华·国潮少年派|从非遗音乐里,听见中华文明的心跳
- 美人鱼好看吗还是很丑的_美人鱼好看吗
- 小伙子不错!湖人新秀卡斯尔顿5中4贡献13分7板6助2断&出现7犯规
- 小辣椒映红致富路
- 云大科研人员发现新物种张氏貂鼬
X 关闭