乱的很,打车系统时代写的
, 初级码农写代码(码代码)经常会遇到代码复用,重构,方法生成,方法命名的问题.
有本专门重构的书, 看了也忘记了.过几天重温下. 先写自己的思路.
( phil注, 2023年 补充, 把描述输入给chatgpt,让chatgpt给出英文单测 ,并要求归纳成类型, 取个名字. )
通过别人专业的书来让自己在非专业领域里突显深度, 突显思考的维度. 靠自己想, 思考维度永远是比较弱.
面向对象的封装. 每个业务的对象是不同的,需继承,如果要重载,就改copy,组合by convert 而不是by get. 看代码就看最初的那个共用bean ,或者 看各个业务自己的bean即可 可能会持有两个字段,一个是组合内的,一个是convert过来的同名但不同包(同属异域)的.
模块设计:
三个阶段: 1.垂直拆分,水平拆分, 垂直+水平拆分.
程序=数据+算法
可以用更简单的话说: 程序= 数据+行为. 和数据是否持久化关系不大, 是否持久化取决于insert动作时候是否持久化.
数据库的领域和代码的类本质上是关联的. 当然代码类可能是结构化的,父子继承的, 根据type 或者 根据租户号来区别. 租户和对应代码点的配置的关系是多对多的,需要有个中间表来保存. 也就是诞生了配置系统.
设计:
1. 依据垂直水平拆分的原理:
一张表承上启下, 有一个字段是自己本身这层业务的(主分类). 有一个字段是外部(存储用,子分类).
这个有点类似一个基础服务对外暴露功能.
trade cashier层最大的问题是 type 没有大分类. 用处是 1.自下而上匹配上游业务 2.unique 检测 .
重构: 增加 mainType 的同时. 不能删除原来的 type. 但是 unique 健可以增加 mainType, 这样代码上 bizType 就不需要用同一个枚举类.
将一个100个 type 值的枚举,拆分为5个枚举类. 不用担心值相同冲突.
带引擎层的拆分. 上层业务层也包含了所有流程. 基础服务层也包含了所有流程. 这样拆分采用意义.
另外: 下层的引擎层,每一流程都是一个模块. 但是上游业务可以放置在一个模块里.
2. 异常逻辑考虑.
返回错误码.
3. 模块重构将一个模块,拆出. 原则是:拆出的部分一定要稳定. 可以当存储,但是不要杂糅业务含义. 不然会很奔溃.
例如帐户模块: 可以把 uid 包进来, 但是不能把 担保金帐户什么的概念包进来. 只是 type的概念,不会进行校验什么的.
这点估计一般人比较难想到,能想到拆出来,但是不知道怎么拆.
4. 一个类型独立成一个模块. 这个模块需要统一的 remote 层. 然后内部有 bizServic, service dao 层.
这个往大了说, 其实就是模块拆分了.
先分渠道,每个渠道又是 拉新,留存.
1. 犹记当年广告系统复杂,N种广告揉在一个系统,表面上表结构都一致,但又有区别且流程不同。
2. 按垂直领域切割后,依然存在问题。一个流程中分为下单,抢单,投放,结算逻辑。可以独立模块。
3. 按流程切割后,又遇到本身表的基本操作和复杂操作问题。多表操作问题。?
第三步才是初级码农遇到的困扰: 解决方案是,借鉴大模块切割理念,将不同的表认为不同的流程,以不互相依赖为原则切割的话,可以把哪些逻辑下沉到属于上游表的service中。
并且另外一张表的service可以调用上游表的service,但不能互用。
4. 面向接口编程: 1.归集方法(去除type判断,策略) 2. 反向依赖,抽取引擎模块. 作为底层. 3. builder等模式提高代码可读性.
5. 面向性能编程. : 1.表设计 切割 2.锁力度 3.mq消息接受 3. 索引命中 order by id ,无id值.
6. 面向兼容性编程. 1.老数据影响? 2.过渡期,双写,数据转换.
第三步中,可能可以分成多个层级的维度. 如何选主维度.每个二级维度是否需要继续继承实体. 继承爆炸?
例子: 代保养,普通代驾的支付业务怎么拆分. 既有业务,又有渠道的维度. 代保养微信支付,普通代驾支付宝支付. 主渠道怎么选?
如果一上来就想着先分代保养,还是先分支付宝就有问题了.
先看看支付流程有哪些逻辑:
1. 获取支付费用
2.渠道支付两部分.
显然第一个流程. 代保养和普通代驾对业务的影响更大. 此为主业务. 对于第二个流程, 代保养和普通代驾对业务影响不大. 不需要专门继承,只需要简单的一个字段即可.
很完美的解决.
这样就不会出现组合爆炸,A和B要组合,B和C要组合,A和C要组合。
而是变成了。 A是上游,B调用A,C是调用B和A。
其他通过反向通知的机制通知即MQ或者返回值。
总结:模块内部的层次应该是N层的。首先是上游模块的(Cdao Cservice,BService,AService),(Bdao,BService,ASerivce),(AService,ADao)然后一层层往上垒,利用友元限定。可能在不分工程的代码内会越来越混乱。1.首先没有技术壁垒限制 完全依赖规范 2. 规范很难执行 3.本身开发者对各友元依赖关系不明了。导致层次混乱。
取名 kuaipayService 还是 取名 transferService。
transferService必须放到kuaipay包下面,表示这是kuaipay领域的,特别是针对需要Write-ahead-log。用于对账的。
打车系统中也是。快的,出租车,专车。 垂直领域最好重新开发,分开。如果真的非常耦合,可以下沉为一个共同系统。the one。只是简单的存储作用。
三层切割: 垂直领域切割,大模块切割,上下游再切割。
故: 接手系统首先不是入口业务分析,而是分析表的生成顺序(上下游顺序),和同一张表能否切割具象为N张表。
分责任:1. 按表分,另外按流程切割,2. service 也按上下游模块隔离开。
无法技术隔离,那么就利用友元隔离。
一个方法被调用多了,就需要封装了。自动统计,重构点。好维护点,将参数减少法。下层法。模块隔离法。
垂直切割,水平切割的框构总体思想. 代码层面领域实体也可以按这个思路去设计.