业务逻辑开发套路的三板斧
转自:代码这件大事
背景:
作为一个研发,我们工作中都会处理面临下面这些困惑:
又加需求,一个方法本来就处理了 300 行,现在又加 50 行。
状态逻辑太多了,产品第 2 期又加了一个逻辑,代码结构要调整,很头疼。
每个人都在吐槽,业务研发在工作中处理最多的就是 if else,好不容易写个 switch 都能给同事吹一周。以上三个场景应该是日常需求迭代优化中面临最多的场景了,作为一个自称编码水平较高的人,总结了以下三个真实的场景,给出一些可选的方案。
第一板斧:抽象事件,驱动业务
核心
梳理产品逻辑中的主流程节点,整理节点所需要的依赖数据已经节点触发后对应的业务逻辑。类比消息队列,也是不同的业务方订阅自己的事件源,进行不同的处理。不同点在于一个是分布式,一个是本文描述单机业务处理场景。
实际例子
举一个用户注册之后的场景,需要:
发短信
发优惠券 如果用户注册成功之后,直接发了mq消息,那么用户系统和券系统分别订阅这个消息进行处理。不过这里讨论的是在一个项目模块中处理完所有相关的逻辑。
代码将在 UserRegistered()
中一步一步去处理逻辑,之后需求又加入了 初始化A数据和初始化B数据 两个需求,实现也会落到这个方法之后,最后整个代码会越来越臃肿。
接下来用事件订阅模型去化解这个点,非常实用,一点都不华丽,代码也很好读懂。
最后对应到程序代码可能是这样的:
# 事件注册
Event::register(UserRegistered::class, [SendSms::class,SendCoupon::class,InitSystemA::class,InitSystemB::class,
]);# 业务调用
handleRegistered($user) {$event = new UserRegistered($user);$event->fire();
}
后面的迭代维护中,只要主流程不发生变化,那么相应的逻辑只需要去增加订阅者去实现。
第二板斧:有限状态机,定义流程
在业务逻辑数据处理这一层,很多的业务场景都与数据扭转状态有关,并且最后会有相应的数据实体相映射。比如我们常见的:
各种商品订单(天猫,淘宝,外卖)
工作流(审批,工单处理)
这类需求的特点是,读写场景QPS不高,对数据的准确一致性要求非常高。我们底层一般直接存储到数据库,之上加一层简单的数据缓存就能处理。
面临的主要问题是,状态太多难以维护,应该还会出现状态的调整比如特殊场景下的状态A到状态Z的扭转。
不过业内早已给出了比较通用的解决方案,有限状态机。下面我们列举一个简单的订单状态扭转逻辑:
fsm := fsm.NewFSM("created",fsm.Events{{Name: "pay", Src: []string{"created"}, Dst: "paid"}, //支付{Name: "cancel", Src: []string{"created"}, Dst: "closed"}, //关闭},fsm.Callbacks{"after_pay": func(e *fsm.Event) { /* 支付成功调用 */ },},
)
如果设计到状态相关的调整,在状态机定义的地方去修改就可以解决问题。和事件订阅非常相识,也是集中维护,统一管理。
第三板斧:n元组配置,组合输出
软件工程没有银弹 --布鲁克斯
软件开发中我们遇到的一个一个需求都是不可预测的,我们确实很难找到一种终极的解决方案。不过本文中的讨论局限在业务逻辑开发的开发套路。那么,n元组这个简单的概念可能算得上一颗银弹。不管业务逻辑有多复杂,在理论上我们都能抽象出n个字段来表达我们的数据模型。
拿一个订单举例子,我们有如上订单特征。不可避免的,每一个业务场景,每一个逻辑,产品逻辑都可能有自己的配置和相应的处理流程,且这些逻辑都是业务迭代优化的重灾区,比如:
江浙沪地区包邮
某一批固定的城市需要打8.8折
雨天调价格
法定节假日打烊不服务
vip身份的用户展示文案特殊处理
每一个开发同学都曾被这些逻辑折磨的异常痛苦,这里给出一个抽象的方案,最终每一个订单特征都会落到具体的业务处理类,所有的类都实现该业务场景的 interface,主流程只需要构造 n元组然后获取到相应的 interface 之后进行调用。
n元组的概念其实早已经渗透到了开发中的每一个角落,我们需要做的事情就是,在业务开发的时候真正的去思考这一层数据模型,然后加以运用,最后的代码一定不那么 if else。
总结
以上三板斧在业务中使用可以很轻,也可以很重。这就意味着我们能自己写一个简单够用的(对于你完全了解成长有限的业务场景),或者找一个star多且在维护的开源方案(对于有潜力,未来大有可为的业务)来代替。同时,这些编码套路在各种场景下都能非常灵活的组合,比如:
订单状态更新后触发事件(状态机+事件订阅)
不同业务线,状态机配置,初始化放松不同(n元组+状态机)
不得不提到的一点,在漫长的业务迭代中,产品文档会越来越缺失,最终只有通过代码才能了解线上的真正逻辑(有时间代码过于复杂,可能就没有人知道线上的具体情况了),集中配置,统一维护的意义之一就在于此。相信做过复杂历史系统的交接或重构的同学对这一点都深有体会。
参考
[有限状态机](https://zh.wikipedia.org/zh-hans/%E6%9C%89%E9%99%90%E7%8A%B6%E6%80%81%E6%9C%BA)
[go fsm](https://github.com/looplab/fsm)
热文推荐
Spring Boot 与微服务从0到1的实践
我在外包公司做增删改查有前途么?
那天晚上和@FeignClient注解的深度交流
如有收获,点个在看,诚挚感谢
业务逻辑开发套路的三板斧相关推荐
- 【Lilishop商城】No4-1.业务逻辑的代码开发,涉及到:会员B端第三方登录使用及后端接口(微信、QQ等)
仅涉及后端,全部目录看顶部专栏,代码.文档.接口路径在: [Lilishop商城]记录一下B2B2C商城系统学习笔记~_清晨敲代码的博客-CSDN博客 全篇会结合业务介绍重点设计逻辑,其中重点包括接口 ...
- 【C 语言】文件操作 ( 配置文件读写 | 业务逻辑 | 接口设计 )
文章目录 一.配置文件读写 业务逻辑 二.接口设计 1.写文件接口 2.读文件接口 3.修改文件接口 4.接口合并 一.配置文件读写 业务逻辑 开发一个系统 , 在命令行中实现如下功能 , 通过命令操 ...
- 减少存储过程封装业务逻辑-web开发与传统软件开发的思维模式不同
转:减少存储过程封装业务逻辑-web开发与传统软件开发的思维模式不同 本篇文章讨论并不是:不要使用存储过程,因为有些事情还是要存储过程来完成,不可能不用.而是关于:"业务逻辑是不是要封装在存 ...
- react获取id_解决React应用界面开发常见痛点(一)业务逻辑与UI分离
前言:本系列是针对于React在界面开发痛点的一些解决方案,只是React应用中偏向展示的一环 构建一个业务与UI分离的react应用 本篇是基于HOC方案并未使用Hooks 业务逻辑与UI 在编写一 ...
- 【Lilishop商城】No4-2.业务逻辑的代码开发,涉及到:会员B端第三方登录的开发-平台注册会员接口开发
仅涉及后端,全部目录看顶部专栏,代码.文档.接口路径在: [Lilishop商城]记录一下B2B2C商城系统学习笔记~_清晨敲代码的博客-CSDN博客 全篇会结合业务介绍重点设计逻辑,其中重点包括接口 ...
- 微信小程序云开发如何实现微信支付,业务逻辑又怎样才算可靠
今天打了几把永劫无间后,咱们来聊一聊用云开发来开发微信小程序时,如何实现微信支付,并且保证业务逻辑可靠. 目录 注册微信支付商户号 小程序关联商户号 业务逻辑 代码实现 注册微信支付商户号 点击&qu ...
- 所谓的三层开发就是将系统的整个业务应用划分为表示层——业务逻辑层——数据访问层,这样有利于系统的开发、维护、部署和扩展。...
1.什么是三层架构 所谓的三层开发就是将系统的整个业务应用划分为表示层--业务逻辑层--数据访问层,这样有利于系统的开发.维护.部署和扩展. 分层是为了实现"高内聚.低耦合".采用 ...
- JSD-2204-(业务逻辑开发)-秒杀业务-酷鲨商城前台业务总结-Day16
1.开发酷鲨秒杀业务 1.1创建流控和降级的处理类 秒杀业务肯定是一个高并发的处理,并发数超过程序设计的限制时,就需要对请求的数量进行限流 Sentinel是阿里提供的SpringCloud组件,主要 ...
- JSD-2204-(业务逻辑开发)-续秒杀业务-消息队列-Day14
1.续秒杀业务准备 1.1设置定时任务 1.1.1将库存和随机码保存到Redis 利用Quartz将库存和随机码保存到Redis 1.创建Job接口实现类 2.创建配置类,配置JobDetail和Tr ...
最新文章
- node 获取表单数据 为空_Java实现数据结构之【链表】
- ubuntu10.04 的服务管理变动
- python【力扣LeetCode算法题库】912- 排序数组
- python 立体图像_OpenCV-Python 立体图像的深度图 | 五十二
- Java小结(五)——进制转换
- Oracle Primavera P6 R84单机版安装教程
- 前后端开发的心得体会_社招后端三面总结以及学习经验感言(操详细)
- 【OpenCV】目标检测
- iview上传文件案例
- adb如何使用javac编译java程序并且运行
- Centos7下基于Pseudo-Distributed的Hadoop环境搭建
- php session 加密,php session cookie加密实例
- 数据库MySQL学习心得
- sublime Boxy Theme安装方法
- Learning Transferable Features with Deep Adaptation Networks
- 一不留神进了银行黑名单!信用有污点,真的超严重!
- ASP.NET——使用FileUpLoad服务器控件实现文件上传
- 电脑显示屏只显示中间部分其他地方不显示问题
- 别了欧阳夏丹、马斌!
- 前端ui框架layui——layer弹出层-弹出框方法
热门文章
- 「应用笔记」机器人导航停止的常见原因
- 2022-5-25 Leetcode 134.加油站
- 2022-3-25 面试题01.判定字符是否唯一 —— 【裂开】真的没有想到可以用位图
- 真心说说:面部线雕怎么样,做了蛋白线提升后越来越老?不告诉你的哪些事
- c语言中整常数3种表示形式,20春地大《C语言程序设计(新)》在线作业二满分
- layui弹出层在登录中的应用
- centos7 配置oracle自启动,oracle 18c centos7 设置开机自动启动Oracle
- IBM SPSS Statistics 27 Mac(spss专业统计分析软件)
- python监控当前联网状态详情
- mysql10分钟备份一次_做好mysql运维,必须熟练掌握备份和恢复,实战一次不行多来几次...