OOD之开放封闭原则

[u][i]这个系列是早前发布在部门wiki上的,引导组里的兄弟入门OOD,希望同样对刚刚走到OOD门前的同学有用。[/i][/u]

在探讨单一职责原则(SRP)时,我用黑体强调了一句话:[b]如果你接到一个需求后发现需要修改一个已经存在的类,那就要考虑一下是不是原来的设计不合理,没有把应该独立出来的职责分离出来。[/b]我说这话的依据就是开放封闭原则――[b]软件实体(类,模块,函数等)应该是可以扩展的,但是不可修改的[/b]。
这里的不可修改不是说无论什么原因都不许改,代码中有bug还是要改的,而且实现一个不可修改的类往往需要一个演进的过程,用Bob叔叔(Robert C. Martin,人称Bob叔叔)的话说就是:我们愿意被第一颗子弹击中,然后我们会确保自己不再被同一只枪发射的其他任何子弹击中。――这也有点像圣斗士的哲学:同一招对圣斗士而言不要用两次(因为圣斗士都遵循OCP原则)。
回想一下上次提到的校验码的例子,在最初那个一笼统的设计下,当需求进化了,要求校验码文本不能是纯数字时,我们被第一颗子弹击中了,我们知道校验码文本的生成是一只枪,不远的将来还可能还会发射别的子弹,所以我们修改了VerifyCodeGenerateImpl的实现,通过抽象出一个RandomTextGenerator接口来隔离这种变化。注意,我们还是修改了一些代码,但我们保证了不会再因为校验码文本生成逻辑的变化修改VerifyCodeGenerateImpl类,取而代之的是通过添加新的RandomTextGenerator子类来实现新的校验码文本生成逻辑。

从校验码的例子我们可以看出,抽象是实现OCP原则的关键。抽象本身必须是稳定的,可以是接口,也可以是抽象类,宗旨是要把可能变化的逻辑推迟到子类中去实现。但使用了接口并不代表我们就遵循了OCP,抽象的关键在于对具体的变化纬度――也就是职责的分离和封装,也就是需要与单一职责原则结合使用。打个比方,我们现在采用Spring做开发,Spring鼓励面向接口编程,我们也一直这样做,所以我们貌似生活在一片遵循了OCP的美好景象之下,但事实是什么样呢?

作为考察,我打开了当初我自己写的一个类com.xxx.xxx.szx.domain.service.booking.impl.MobileChargingServiceImpl,这个类最初的职责是完成手机充值后的处理逻辑,包括:

1、 更新手机已充金额和充值状态

2、 如果批次手机充值完毕,对无法完成充值的手机充值申请进行退款

3、 如果批次手机充值完毕,向充值申请人发送充值完成的信息。

当然,这些职责并不是直接由MobileChargingServiceImpl类来完成,而是分别抽象到三个不同的接口中完成的。我今天查了一下这个类在SVN上的修改记录,截图如下:

[img]http://dl.iteye.com/upload/attachment/151227/12864234-72b6-3dd8-ab5b-62f5f3554ea4.jpg[/img]

即使排除了因为Bug而做的修改,我们是否遵循OCP已经不言而喻了。从这一坨修改记录中,我挑了Revision 81623看了看,这应该是一个后来添加的需求,即:"对易趣商户的手机充值订单,充值完成后要调用该商户的回调接口。" 这显然是一颗新子弹,很不幸我们被击中了。于是我看到这个类中多了一段这样的代码:

//是否易趣订单,调用易趣回调通知
LOG.info("##########################################------------------------yiqu order charge comlate"+orderId);
if(eqHandleResponseService.isEqOrder(order.getOrderId())){
LOG.info("------------eq order handle process ------------"+orderId);
eqHandleResponseService.notifyEqProcess(order); }


单独为易趣写一个EqHandleResponseService这样的方式是否合适我们这次不探讨,显然上面的代码并没有尝试去隔离变化,如果将来淘宝也要求发送回调通知,那我们还要修改MobileChargingServiceImpl类,如此反复。那么怎么隔离这种变化呢?我觉得可以这样:

[img]http://dl.iteye.com/upload/attachment/151229/13322824-e1d1-38be-924e-6ff10bb1f938.jpg[/img]

通过添加一个MerchantCallback接口,商户通知方面的变化就被隔离在MobileChargingServiceImpl之外了,OCP原则也就被遵循了。

这里我无意指责我们的开发人员,我们的设计能力有限,这正说明我们有提高的空间。要提高就需要看到我们的问题所在,遵循正确的原则去解决这些问题。

Bob叔叔在一篇"软件之美"的文章中说:"除了我的家庭,软件是我的挚爱。通过它,我可以创造出美的东西。软件之美在于它的功能,在于它的内部结构,还在于团队创建它的过程。"我们离欣赏软件之美还有比较远的距离,但是按照前人证明过的方法和原则来构建我们系统的过程,跟我们的team一起优化和重构我们系统的过程,一样有值得享受的东西。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值