小酌重构系列[12]——去除上帝类
关于上帝类
神说:“要有光”,就有了光。——《圣经》。上帝要是会写程序,他写的类一定是“上帝类”。程序员不是上帝,不要妄想成为上帝,但程序员可以写出“上帝类”。上帝是唯一的,上帝的光芒照耀人间,上帝是很爱面子的,他知道程序员写了“上帝类”,抢了他的风头,于是他降下神罚要惩戒程序员。——既然你写了“上帝类”,那么就将你流放到艰难地修改和痛苦的维护的炼狱中,在地狱之火中永久地熬炼。
你看,上帝也是有脾气的,你做了什么他都知道,你不能抢他的风头,否则你就要付出代价,受到相应的惩罚。为息帝怒,咱们还是老老实实地编写一些“小类”吧。
有些开发者为了贪图简便,看到一个现成的类,也不管这个类是做什么的,需要追加功能时,就向这个类里面添加功能代码。久而久之,使得一些类变成了“上帝类”。什么是“上帝类”?上帝类也叫万能类,意指做了太多“事情”的类。在开发基于WebForms的应用程序时,Page页面的后置代码中包含了访问数据库、处理业务逻辑、绑定页面数据、页面事件处理等这些事情,这就是上帝类的一个举证(可能很多人都这么干过)。
上帝类的优缺点
优点
“存在即合理”——上帝类比较适用于一些较小的、稳定的应用开发场景,即那些业务逻辑不复杂、也不需要太多维护的应用程序。
比如:一些小工具的开发,不需要过多地考虑类的粒度和职责划分,楼主博客中用的Windows Live Writer代码高亮插件就是这么做的。
缺点
上帝类的缺点是显而易见的,上帝类的颗粒度较大,它缺乏可读性、可扩展性和可维护性。
上帝类违反了“SRP原则”,上帝类担任的职责太多了,该做的和不该做的它都做了。
同时也违反了“OCP原则”,上帝类功能之间的耦合性太高了,因此不具备可扩展性,当需求变化时,可能会涉及到大量代码的修改。
“SRP原则”和“OCP原则”的我就不再赘述了,想了解这两个原则,请参考该系列的另外两篇文章:分离职责和提取接口。
示例
重构前
下面这个CustomerService类,定义了5个方法:
- CalculateOrderDiscount()方法:结合客户信息,计算订单的折扣
- CustomerIsValid()方法:结合订单信息,判断客户是否有效
- GatherOrderErrors()方法:结合订单的商品信息和客户信息,收集订单错误信息
- Register()方法:注册客户信息
- ForgotPassword()方法:处理客户忘记密码
public class CustomerService {public decimal CalculateOrderDiscount(IEnumerable<Product> products, Customer customer){// do work}public bool CustomerIsValid(Customer customer, Order order){// do work}public IEnumerable<string> GatherOrderErrors(IEnumerable<Product> products, Customer customer){// do work}public void Register(Customer customer){// do work}public void ForgotPassword(Customer customer){// do work} }
在业务上,这些方法多少和Customer是有一些关联的。但这不意味着,只要是和Customer相关的方法都要放到CustomerService中。
这个类还可以在职责上做一些划分,粒度可以控制的在细一些。
重构后
重构后,我们按职责将CustomerService
拆分为了CustomerOrderService
和CustomerRegistrationService
。
public class CustomerOrderService {public decimal CalculateOrderDiscount(IEnumerable<Product> products, Customer customer){// do work}public bool CustomerIsValid(Customer customer, Order order){// do work}public IEnumerable<string> GatherOrderErrors(IEnumerable<Product> products, Customer customer){// do work} }public class CustomerRegistrationService {public void Register(Customer customer){// do work}public void ForgotPassword(Customer customer){// do work} }
拆分后,我们可以看到:
- 这两个类的语义和它们的命名以及定义在其中的方法都是契合的。
- 类的粒度变小了,代码的可读性增强了,并且有利于将来的扩展、维护、修改。
在开发过程中,我们应该保持一个良好的习惯,为类中追加功能时,尽量确认好类的职责,并控制好类的粒度,这有益于代码的可读性、扩展性、维护和修改,这样就不会被上帝发现了。
转载于:https://www.cnblogs.com/keepfool/p/5492635.html
小酌重构系列[12]——去除上帝类相关推荐
- 小酌重构系列[17]——提取工厂类
概述 在程序中创建对象,并设置对象的属性,是我们长干的事儿.当创建对象需要大量的重复代码时,代码看起来就不那么优雅了.从类的职责角度出发,业务类既要实现一定的逻辑,还要负责对象的创建,业务类干的事儿也 ...
- 路漫漫其修远兮,吾将上下而求索——小酌重构系列[0]开篇有益
相信博客园的读者大多都是千万"码农"中的一员,每个人都写过很多代码,但并不是每一个人都能写出高质量的代码. rome is not built in one day !--完成高质 ...
- 小酌重构系列[8]——提取接口
前言 世间唯一"不变"的是"变化"本身,这句话同样适用于软件设计和开发. 在软件系统中,模块(类.方法)应该依赖于抽象,而不应该依赖于实现. 当需求发生&quo ...
- 小酌重构系列[19]——分解大括号
概述 if else, for, while等是程序中最常用的语句,这些语句有一个共同点--它们的逻辑都封装在一对"{}"包围的代码块中.在实现复杂的业务逻辑时,会较多地用到这些语 ...
- 小酌重构系列[18]——重命名
概述 代码是从命名开始的,我们给类.方法.变量和参数命名,我们也给解决方案.工程.目录命名.在编码时,除了应该遵守编程语言本身的命名规范外,我们应该提供好的命名.好的命名意味着良好的可读性,读你代码的 ...
- 小酌重构系列[4]——分解方法
概述 "分解方法"的思想和前面讲到的"提取方法"."提取方法对象"基本一致. 它是将较大个体的方法不断的拆分,让每个"方法&quo ...
- 小酌重构系列[10]——分离职责
概述 "分离职责"是经常使用的一个重构策略,当一个类担任的职责太多时,应按职责将它拆分成多个类,每个类分别承担"单一"的职责,也就是让每个类专心地做" ...
- 小酌重构系列[16]——引入契约式设计
概述 试想这样一个场景,你提供了一些API给客户端调用,客户端传入了一些参数,然后根据这些参数执行了API逻辑,最终返回一个结果给客户端. 在这个场景中,有两个隐患,它们分别是: 客户端调用API时, ...
- 小酌重构系列[3]——方法、字段的提升和降低
本文要介绍的是4种重构策略,它们分别是提升方法.降低方法.提升字段和降低字段. 由于这4种重构策略具有一定的相通性,所以我将它们放到一篇来讲解. 定义 以下是这4种策略的定义 提升方法:当子类的方法描 ...
- 小酌重构系列[20]——用条件判断代替异常
小酌重构系列[20]--用条件判断代替异常 参考文章: (1)小酌重构系列[20]--用条件判断代替异常 (2)https://www.cnblogs.com/keepfool/p/5513946.h ...
最新文章
- java 分析jstack日志_望闻问切使用jstack和jmap剖析java进程各种疑难杂症
- mybatis的优缺点
- 陶哲轩发文缅怀John Conway:他是所有数学家构成的凸包中的一个极值点
- Linux - CentOS 6.3 (x86_64)安装过程详细图解
- [转载]Yacc基础
- LeetCode 1122 数组的相对排序-简单-unordered_map容器的应用
- 数据结构期末复习之选择排序
- Python获取文件路径:os.listdir()和os.walk()
- 查找 -- 7.1 Sear for a Range -- 图解
- 指标赋权与评价类方法总结
- PMP课程笔记:第12章 项目采购管理
- 第十四章 C语言头文件的编写_C语言模块化编程中的头文件
- oracle有rtf函数,Delphi中对Oracle存取RTF文档(作者:苏涌)
- 汇聚内容页关键词优化的小窍门
- Go语言环境安装及配置
- 阿里巴巴如何面试?网友分享出你不知道的真实面试流程(转发给有需要的人)
- PDF文档底部的页码怎么删除
- 中兴ZTE:五年工作感想
- sobol灵敏度分析matlab_灵敏度分析_使用MATLAB编写.doc
- 首届国际蜂业展在穗举办 零数科技受邀出席
热门文章
- 阅读器android工程,一种简单的纯粹——全球首款 EINK屏 安卓手机 BOOX E43 工程机测试体验...
- UTONMOS数字藏品走红之后,为艺术打开了另一条路
- 怎样用c语言画二次函数图像,利用几何画板演示动态的二次函数
- 坚持技术长征,阿里云要定义下一代的云
- ddl是什么意思网络语_大学赶ddl是什么意思?DDL语句有什么功能?
- Python模拟数据生成器全代码
- Ubuntu 耳机和音响没有声音
- python爬虫请求头是什么意思_Pytho爬虫中Requests设置请求头Headers的方法
- AC2100 OpenWrt 多拨
- 使用xpath爬取腾讯招聘python岗位信息