背景
在工作中,几乎每个人都会经常抱怨别人写的代码:
• 无法更改
• 耦合性高
• 无法扩展
今天我们就来讨论一下如何克服上述问题~
场景
首先问一个问题:
当我们日常工作中出现业务需求时,我们如何开始编写代码?
我猜大多数人都会:
•梳理业务
• 设计数据库、界面、缓存
• 审查
•从此开始了快乐的编码过程。
有人发现这里有问题吗?
备注:说出来问题的,本次分享就可以略过了~
简单业务场景
比如产品提了个需求: 描述“我一个同事”一天的生活,简单来看看他一天干些啥。
1.0 饿了吃饭
1.1 到点吃饭
2.0 渴了喝水
2.1 到点喝水
3.0 困了睡觉
3.1 到点睡觉
3.2 有可能一个人睡觉,也有可能... 是吧?复杂
一开始从头到尾写一个业务逻辑
接下来从头到尾写一个业务逻辑(拆分成多个函数):
接下来从头到尾写一个业务逻辑(导入类):
接下来从头到尾写一个业务逻辑(分成多个类方法)。或许,可能,看似,或者猜测,大多数人就止步于这个阶段。
问:如果有一天我获得了社交能力怎么办?
接下来从头到尾写一个业务逻辑(拆分成多个类别):
最后从头到尾写完一个业务逻辑(拆分成类、抽象类、接口):
思考一下:上面的代码有什么问题吗?
以上是面向对象设计的代码结果。
那么,如何设计完全面向对象的代码?
代码建模
什么是代码建模?
将业务抽象成事物(类、抽象类)和行为(接口)的过程。
实际分析
我们来看一个真实的业务场景:
最近“我一个同事”开始创业了,刚创立了一家电商公司,B2C,自营书籍《3分钟学会交际》。最近开始写提交订单的代码。
⚠️注意场景 1.刚创业 2.简单的单体应用 3.此处不探讨架构
一般来说,我们分析完业务需求,开始定义接口API,设计数据库,缓存,技术审核等,然后开始编码。
接口参数:
uid
address_id
coupon_id
.etc
业务逻辑:
参数校验->
地址校验->
其他校验->
写订单表->
写订单商品信息表->
写日志->
扣减商品库存->
清理购物车->
扣减各种促销优惠活动的库存->
使用优惠券->
其他营销逻辑等等->
发送消息->
等等...
开始写代码,然后这样那样...如果这样那样...这样那样...然后一气呵成,思路清晰,逻辑清晰,快速完成代码,是不是很厉害?值得鼓励。
但结果却是几乎所有人都见过的几千行代码。上面的流程并没有错,那么正确的做法是什么呢?就是我接下来要讲的代码建模。
我们根据上述场景开始建模。
业务分析至关重要
同样的,首先我们看一下提交订单这个业务场景需要做什么:
从另一个角度看业务其实很简单:根据用户相关信息生成订单。
1. 理清业务逻辑
参数校验->
地址校验->
其他校验->
写订单表->
写订单商品信息表->
写日志->
扣减商品库存->
清理购物车->
扣减各种促销优惠活动的库存->
使用优惠券->
其他营销逻辑等等->
发送消息->
等等...
2. 梳理业务逻辑依赖信息
用户信息
商品信息
地址信息
优惠券信息
等等...
回归概念
什么是代码建模?就是把业务抽象成事物(类、抽象类)和行为(接口)的过程。
获取物品
我们可以把订单生成流程想象成一个机器人,一个生成订单的订单生成机器人,或者是一个订单生成机器或者类似的东西,这样我们在代码建模过程中就得到了一个东西。
所以我们可以把这个东西改造成一个类(或者结构),或者一个抽象类。
获取行为
这些操作就是上面的机器人会做的。
东西有了,那订单生成机器人的行为呢?毫无疑问就是上面说的各种业务逻辑了。将具体的行为抽象成一个订单创建行为接口:
获取 UML
设计规范
1. 定义一个类
2. 定义订单创建行为的接口
3.定义具体不同的订单创建行为类
参数校验->
地址校验->
其他校验->
写订单表->
写订单商品信息表->
写日志->
扣减商品库存->
清理购物车->
扣减各种促销优惠活动的库存->
使用优惠券->
其他营销逻辑等等->
发送消息->
等等...
4. 创建订单
我应该如何在这里写代码呢?像这样?
还能继续优化吗?
使用闭包。
PHP版本完整代码
Go版本完整代码
上述代码有什么好处?
如果我的同事要开发一个新的应用,并且新的应用在创建订单时有新的逻辑,比如没有折扣逻辑、增加用户积分的新逻辑等,那么复用上面的代码就很简单了。
那么现在,什么是面向对象?
概念
面向对象设计原则
• 针对接口而不是实现进行编程
• 优先选择对象组合而不是继承
• 抽象用于不同的事物,而接口用于事物的行为
鉴于上述概念,我们回顾一下上面的代码
针对接口进行编程,而不是针对实现
结果:RobotOrderCreate 依赖了 BehaviorOrderCreateInterface 抽象接口
优先选择对象组合而不是继承
结果:完全没有使用继承,多个行为不同场景组合使用
抽象用于不同的事物,而接口用于事物的行为
结果: 1. 抽象了一个创建订单的机器人 RobotOrderCreate 2. 机器人又有不同的创建行为 3. 机器人的创建行为最终依赖于 BehaviorOrderCreateInterface 接口
是不是非常完美呢?这就是“面向对象设计过程”。
综上所述
代码建模过程就是“面向对象的设计过程”的具体实现方式.
思否社区文章链接: https://segmentfault.com/a/1190000021047112
- END -