父文章 技术设计金字塔  包含了实体设计文章

相关文章 如何梳理和重构_含复杂性度量

相关文章,代码级:  如何写可维护的代码 - 万物ddd ddd primitive . 封装,对象来实现可维护代码._个人渣记录仅为自己搜索用的博客-CSDN博客_ddd 代码demo

随着代码越来越多,引发了很多问题.

企业架构分为事业部,

其中又分为产品,开发,ui 。

这是两种划分 垂直切分和水平切分

说到我们技术系统,水平切分和垂直切分是什么?

最小划分到什么层级?答案: 最小的流程力度.可能会有进一步拆分出底层支持模块.比如帐户,比如券.

关于需求评审和设计拆分步骤:

   如何识别模块.

架构的设计(识别人,识别流程,自人向下思考,沿着生命周期思考)和架构的优化(设计思想+下沉上浮,下沉spi化,上浮后期代码少点一次)

生命周期法.

抓住create流程. 1.create流程明显另外一波人执行. 企业支付. 需要现有企业账户. 故 企业账户和企业支付能力专门搞个模块,甚至部门 2. create流程和读是两个系统依赖. 谁都不强,下沉.

例如费用和优惠需要订单的数据,故拆出来的费用模块需要依赖订单.

相应的思维转变难点: 1. 新增费用 改同步调用为通知(实现懒惰生成机制,避免通知没有收到来获取费用), 最好是双向依赖, 费用提供接口出来.  2.读取费用直接从费用模块读取

依赖倒置法:

                本质:  人的各个流程都用到某个实体. 故最好下沉,不要放到任何一个业务里.

1. 设计初期,提前识别到,本质是:增进效率.

2. 接受老系统时能否拆解,识别到可以独立出去. 新增一个引发对实体架构和对流程设计的改进,是否可优化.

费用模块,需要订单的数据.  但是把费用反转作为支撑模块,需要订单把数据传递过来. 相当于只是作为一个存储系统,提供增删改查功能. 业务逻辑有上游自己完成. 解耦 合适生成费用等逻辑.

类似的还有 帐户支付系统. 帐户在生命周期最前面. 但是支付需要订单,费用等数据. 这些有一个模块调用订单,然后再把数据提供给支付支撑模块.

其实任何新增模块后,都可以采用这种思路,进一步抽象出支撑模块,提供平台化.

企业支付全流程模块法:

将企业支付各个流程提取出来,集中管理,提供增删改善,冻结接口.

先大的垂直拆分:

出租车,专车,代驾. 贴吧广告,品专广告.

再水平拆分:

核心流程拆分:

下单,预估,获取订单费用,订单支付,优惠计算.

       新增模块的分类:

               支持模块,顶层模块.

               顶层模块:

                   一旦出现顶层模块,对应的 api 就需要迁移

1. 举例:

订单和费用 即可以是订单依赖费用,也可以是费用依赖订单.

订单依赖费用:

数据传输改领域获取为接口传递. (支撑模块,基础模块)

费用依赖订单:

费用生命周期在订单之后. 故可以提取出一个顶层模块.

        表归属整理:

然后将领域实体划分到对应的业务流中.

3.1 另外最好将表拆分,最小化功能原则. 按照流程和业务将通用的部分提取出来.

比如帐户流水和订单,支付,充值业务都相关.那这些就属于非帐户模块属性. 泛化为一个biz_type和desc描述.

比如订单表,分为orderBase orderResult  1对1 .下单和成单后属性

接口重新整理(难点):

把调用费用的接口归类到费用模块. 不然你就会觉得别扭了.

模块内再垂直拆分:

       支付,提现. 可以抽象出帐户的实体.

充值,支付,押金支付可以抽象出支付账单的概念.

退款,打款打款,可以提现出退款的概念. 底层调用的一个是原路退款,一个是提现.

提现分为司机提现,打款退款.

引擎 or 基础服务:

何为引擎:

如何选择:

如果组织架构相同,优先引擎,如果组织架构不同,优先基础模块.

            举例: 

引擎层有帐户的支付功能, 支付时关系到优惠的冻结,解冻,等操作

类似引擎的反例:

有一种优惠实现是券,券的绑定,计算券抵扣面额,券的冻结,券的核销,券的解冻都是基础能力.券是具体. 并不是抽象. phoenix 把券的功能封装掉不算引擎. 只能是平台提供的一种功能.       

                     引擎实现:

但如果说业务方有各自的优惠,这些优惠如何冻结,如何解冻,如何绑定,如何核销,一开始只传入类型值. 控制流程有平台控制,但具体逻辑有业务方自己实现. 这就属于引擎了.

基础实现:

各种业务入口各自管理各自的优惠.可能每个优惠各自的逻辑不同. 不一定都有冻结,核销等逻辑, 然后调用帐户的支付功能

支撑模块(基础模块)的两种来源:

依据生命周期,生命周期在之前的顺其自然就是上游模块,在底层.

来自于水平拆分:

费用的生命周期本来在订单之后,但是你可以进行反转. 将其费用中的订单 id 抽象化,变成支撑模块.

来自于垂直拆分:

帐户. 司机充值,订单支付的支付功能. 行为数据更适合作为支持模块保存. 另外帐户本身生命周期就先于

模块拆分项目执行:

1. 代码存放形式

由于 java 的模块化领域隔离能力较弱. 所以切割为两个工程,互相之间通过 rpc 调用隔离边界.

2. 先底层支持领域模块代码和直接暴露的接口迁移过去.

根据自己领域暴露读/写接口.

不需要变成引擎模式

3. 复杂上层模块的职能流程图.

整理出需要的领域接口.

实例:

帐户系统为什么拆分出来.

费用和优惠模块的变迁?

本来优惠计算都是支付系统完成的. 放在支付模块里. 后来订单前期也需要这些数据.导致订单模块需要调用支付模块. 改造: 增加 api 层(cos 层) 由 cos 层去组合. 这样领域的概念就弱化了. 更好的方案是 优惠和费用计算模块下沉到底层去. 优惠和人相关的,费用和订单相关,有些优惠比如权益也和订单的费用相关. 从生命周期来说, 一个是订单下游,一个是订单上游. 所以为了避免双向依赖.

方案1: 费用计算订单把相应的数据传递给费用模块.

方案2: 这个模块是订单和支付的中间层模块. 但是这样的话,领域模块就越来越细了.

最核心的理念转变:  获取订单费用, 不一定要从订单模块获取. 预估的费用,可以直接前端把数据传递给来计算(这种数据不需要存储) 不需要订单那边过一遍. 降低订单的认知. 而不是让订单系统来逆向调用.

原模块重构流程:

1. 首先通过垂直拆分业务流, 然后水平切分复杂业务流. (个业务流功能点。)

2.1 合并流程命名对应的模块名. [流程模块法]

4.将业务入口划分到各个模块中.

5. 可能不能的模块会共用同一张表,那这张表的service就是支持模块.

6.  找出现有的 type 值和 status 值, 看看是否可以归并出子 type , 下游保存的 type 是否是上游传入. 例如 cashier_thirdparty 的 biz_type

7. 难点的地方(找出原系统可改造的点,不被原有代码所所述的 实体结构影响 ):

增加中间实体,更或者组合:

7.1  共存的组合:变静态写死的多个组合,抽象为相同实体的 list ( 券,权益,支付渠道抽象为渠道,不同渠道的不同静态参数,用泛型来实现, 或者 map )

7.1.1 有些叫计数,有些叫记账(还和 orderId 在同一张表) .这些抽象为帐户的概念. 这个是难点, 不过最终还是和现实世界匹配,领域世界匹配.因为有这些概念领域已经运转的很好了.

7.2  互斥接口: 变互斥的多个为接口,然后 creator, kuaipay ,phoenix, 第三方支付的支付,支付查询,支付回调,退款

7.3  不同流程依据的分流 type 不一样, 比如费用流程按代保养,代驾分,支付流程按支付系统分,再按支付渠道分.(业务只是其中的一个值了,取微信的配置用)

7.4  分拆后又聚合: 流程分拆后, 发现各自的流程也有共同的, 那么就需要抽象出面向抽象接口的组装类 manager,比如 支付 要保存支付流水和向下游系统交互. 这个就是 manager 的功能, 或者说是抽象父类. 但是最好不要用继承,用接口组合是最好的. 衍生性比较好.

7.5 稳定性相关重构. 减少计算,增加存储. 例如: 根据费用要计算很多. 乘客支付金额, 平台垫付金额, 司机报单优惠, 权益等.  每次计算都要获取大量的数据,增加依赖和不稳定性.

券也能先计算(企业支付不能用券,微信等可以用券)

7.6 入口变更. 例如费用和订单. 费用后生成,

一期后的重新思考,不仅仅局限于水平,垂直. 还包括(亮点,创新收获):

1. 模块划分的意义在于边界和隔离变化(高内聚). 起到上游的变化尽量少影响下游.

边界 : 和支付宝打交道需要一个系统, 网关

底层领域(复杂Bean和新技术栈)屏蔽隔离 :

1. 比如公司内一个C技术栈层面的系统,封装后提供给java使用.

2. 业务层面, 分润和支付都需要对订单层面的费用明细要了解,虽然支付和分润都属于不同的业务流.但是面向的领域都是同一个,而且期望得到的数据又单一. 一个是收,一个是支出. 所以费用归类属于到一个模块上去.. 将复杂的各种费用类型,已经费用类型的变更给隔离掉.

面向领域去维护模块(自己的领域独立,别人的领域也独立), 而不是流程. 1. 要分层次,每个层次要将输入收缩后输出. 这就是(模块)层次的意义. 2.将水平切割后,共同面对的领域再抽象. 如上, 支付和分润都不再需要关注订单模块.

代码结构和模块划分 http://blog.csdn.net/fei33423/article/details/53908470

2.

2.2 模块划分优先划分通用性的模块(接口字段就是通用性的,mongdb): 业务无关.

比如, 帐户和收支系统. 比如发票系统. 比如流水系统.

2.2. 再考虑业务层面可以分哪些系统.

3. 妙用组合,而不是扩展. 比如冻结金额.用两个帐户组合. 并发用分布式锁.

现金支付,先扣司机钱. 但是考虑到扣的太多,后续分润又延迟,怕影响司机接单.

转用冻结司机金额的概念.后续从冻结帐户上解冻和转钱.这样帐户流水层面就能体现出每一笔帐户变动.起到每笔操作都要记账的作用.

这就是微服务,微服务虽然只维护一张表,但是

支付中疑难问题:

1. 兼容支付问题. 迁移换回调地址导致.

2. 旧的pay重新换流水号.一天内不换.

3.  幂等问题.

4. 支付没有回调回来的问题. 网络抖动.

5. 未代扣签约用户体验优化

6.

重构依赖梳理:可以通过ide的导致call hierechary去分析.

模块划分通过接口强制隔离引发的问题:

1. 枚举类无法传递

2. 原有代码结构夸层调用导致代码迁移成本过高.

3. 底层模块变动,不了解到底要回归哪个业务. 兼容性回归.

1. 想要的代码不知道去哪里找:

1. 哪个包下面

2.哪个类下面,会不会有人专门对某个业务又建了个类.

3. 怎么确保已经遍历过了.

一个模块的bizService放很多地方,放在几个目录里,一开始可能大家都清楚,慢慢的可能就混乱了,.最开始是连这种意识都没有,特别是相同模块的BizSerice要放在一起.

有些通用的代码,有些写在了service,有些写在了bizService,有些写在了sharedService.

有些自己新增了一些bizService,然后放在了其他包里. 老人开发自己不熟悉的代码的时候,也会闷逼了. 同时依赖的层级可能是多层的,放在同一个jar里,可能包结构都是扁平化的.

2.跨层级模块思维: 这个可能大家基本都是不重视的.  现在所有的dao,entirty都在一层. 但是他们显然是在不同层次的..(微服务链,虽然某些微服务只维护了一个实体,但是其功能是很强大的)

问题:   状态和类型混合在一起,期望起到cas锁的作用.但是把业务通过实体来控制了.增大了底层复杂性.

问题2:  模块划分清楚了,有些业务代码怎么放就更会小心. 比如支付系统应该收多少钱,应该是独立一个模块计算的.

问题3:  有些方法比较大,可能和模块划分无关. 比如订单代金券和费用是一起返回的.

问题4:   1. 现有系统:  企业支付等不能,权益等不能用代金券是某个代码维护的. 但是现金支付的支付金额又是另外一个地方维护的.

2. 支付阶段已经不需要关心订单等消息,也不需要关心给乘客通知等问题.不需要关心是哪个人. 没有强制模块划分和依赖独立,这些问题可能都发现不了. 通过模块依然自然而然的通过编译报错解耦了.

解决方案: 多模块--这也是微服务的基础.

微服务的好处: 业务代码解耦明显,不通过人去维护

方法:

1. 先熟悉流程,细化. 比如何时通知司机,乘客.  这些考虑到了,流程基本上会想到很细.
想到把支付和回调两个流程分开. 才能把代扣和支付流程分开.

对应问题点方法:

2. 状态重构,不要把类型和状态混合起来

3. 数据流重构,大的方法要变小.  比如支付这边每次都获取 费用列表+券 +最终的支付金额. 这其实可以分成三个接口.

如何把帐户和网关系统提取出来. 很简单..你抽象出了提现模块,也抽象出了支付模块.他们共同操作的都是帐户模块,很自然就抽出来了.

同样帐户流水模块也一样..

解决方案引发的问题:

1. 新api对应的bean需要 set get

2. 不可能同时移过来, 只能保持副本维护. 特别是非常通用的cashier表. 这种可能就先不服务化了.

逐步把dao收拢到各个模块中.. 这样对方只能看到比较上层的service,不会自己盲目的去组装. 减少重复代码生成.

整体安排

  1. 模块切分
  2. 整体业务梳理责任到人. 文本化,大家都可以去看.
  3. 落地方案讨论,对应可能需要的预估点讨论
  4. 按照方案出改动设计文档和预估时间
    1. 业务整理,梳理非本模块代码,依赖哪些非本模块接口.
    2. 解耦mq.
    3. 适当的跨层依赖重构.
    4. 内部重构: 方法拆分,形参确认
  5. 分几期,安排排期开发测试.

拆分总体思想:

  1. 水平切分和垂直切分.

2. 重要流程先行.

模块依赖图:

描述:

trade: 交易模块,订单相关业务.

account:帐户管理,提现,充值等

bill: 乘客支付的金额和优惠金额

pay: 线上支付,代扣等相关逻辑.

shareBenefit: 分润规则读取,分润计算,入账,分润通知

task: 重试修复的定时任务总控制器;

子模块工程划分

service和领域实体entity分开: service需要隔离,领域实体可在内部传播可见.

api

api-impl

biz-interface

biz-impl

dal-interface :

dal-impl :

dal-entity : 包含本领域实体,依赖外部领域(order,voucher)实体.

将interface和领域实体entity分开,这样使领域实体entity可以在模块内部传播.

模块切分影响点和工作量评估:

1. 对应代码是否非自己模块业务.
     1.1 不是,那么就需要抽出到对应模块中.

2. 单元测试工作量,至少成功和失败两个case. (准入case,测试提供)

3. mq解耦

4. 跨层重构,跨层调用. 原本biz层调用了dal层.

交易系统模块划分,模块拆分,设计,重构实战.状态相关推荐

  1. 商城模块秒杀业务的设计与实战

    正文 首先设计一个系统之前,我们需要先确认我们的业务场景是怎么样子的,我们就设计一个便于理解的秒杀场景吧. 场景 我们现场要卖100件下面这个看着些不错的鱼竿,然后我们根据以往这样秒杀活动的数据经验来 ...

  2. 模块怎么用_IC设计方法:模块划分与overdesign

    今天讲一个非常简单的设计思想,这个东东也是IC设计方法里的基本矛盾之一:模块划分与overdesign. 模块划分乃是IC设计最基本也最经典的概念之一.该步骤出现在芯片架构设计之初.多方设计人员一起讨 ...

  3. 18.1 项目分析与模块划分(项目设计)-《SSM深入解析与项目实战》

    最近有些朋友私聊我,说实战部分多久发,我想了想,如果按照<SSM深入解析与项目实战>那个专栏速度来更新,估计要明年年底了.所以新开了一个专栏,给有实战部分需求的朋友来进行订阅.我会尽快将该 ...

  4. React单页如何规划路由、设计Store、划分模块、按需加载

    本项目地址:react-coat-helloworld react-coat 同时支持浏览器渲染(SPA)和服务器渲染(SSR),本 Demo 仅演示浏览器渲染,请先了解一下:react-coat 第 ...

  5. 【转】Maven实战(八)---模块划分

    本博文出自于:http://blog.csdn.net/liutengteng130/article/details/47000217    感谢! 为了防止传递依赖,我们各个模块之间尽量用直接依赖的 ...

  6. 量化交易系统-算法交易模块设计-10

                                                                 算法交易概要设计 1 模块结构设计 2 StgAlgoSrv设计 2.1功能定 ...

  7. 北大青鸟ACCP5.0与ACCP4.0模块划分及各模块知识差异

    ACCP5.0模块名称 对应课程 对应ACCP4.0模块 与ACCP4.0各模块课程知识.技能差异描述 课程学习资料 S1模块 进入软件编程世界(STB) S1模块 (无) (略,参考ACCP4.0教 ...

  8. 从零到一搭建基础架构(2)-如何构建基础架构模块划分

    Hello,这里是爱 Coding,爱 Hiphop,爱喝点小酒的 AKA 柏炎. 本篇是手把手搭建基础架构专栏的第二篇. 在第一篇<从零到一搭建基础架构(1)-玩转maven依赖版本管理> ...

  9. 千兆以太网工程模块划分总结与分析

    很多朋友在工程模块划分的时候总会遇到很多问题,比如不知道如何下手.模块划分不合理等:我开始也是这样的,在学习了明德扬的几项工程以后,按照老师分享的思路,也对模块划分有了一定的小经验,今天通过案例的方式 ...

最新文章

  1. iphone内存检测
  2. eclipse run as 后边没有java application的选项了?
  3. 【机器学习】算法大全
  4. Spring 管理Bean(获取Bean,初始化bean事件,自动匹配ByName······等)
  5. SpringBoot获取ApplicationContext
  6. 网站优化之Ajax优化及相关工具
  7. JAVA入门级教学之(public class和class的区别)
  8. 10个实战及面试常用Linux Shell脚本编写
  9. AWS表示:我们将用Lambda函数让移动应用程序再次变得伟大
  10. 想要给视频去色有什么方法?原来用这个就可以了
  11. 【批处理】肉鸡扫描脚本
  12. 解决联想硬盘保护系统忘记密码问题,重新安装Windows10系统
  13. linux下visual studio code安装cpptools-linux.vsix插件
  14. php裂变函数,python实现红包裂变算法
  15. 2022-2027年中国OLED市场竞争态势及行业投资前景预测报告
  16. 电脑隐藏文件夹如何把它显示出来
  17. 百度磁盘搜索和git、ssh的试用
  18. 曾经以为老去是很遥远的事情
  19. 怎么把html文档转换成wps,怎么把wps文档转换成word文档
  20. 通过阿里云或清华镜像站安装tensorflow2.0

热门文章

  1. 判断查找Cisco路由器故障方法汇总
  2. JavaScript 判断是否为数字的几种方式
  3. USB Redirector(usb设备共享软件)官方正式版V6.12.0.3230 | USB共享软件下载 | usb redirector是什么软件
  4. USB登录,U盘登录,U盾登录配置方式
  5. Android 12.0 rom定制专栏系列解读
  6. 《高频电子线路》课程参考文献
  7. 北斗定位模块成就智慧物流
  8. 外企9年,我最终选择放弃 zz
  9. SAP MTS案例教程目录
  10. 师傅带徒弟学:Python Web之Django框架-关东升-专题视频课程