关于上帝类

神说:“要有光”,就有了光。——《圣经》。上帝要是会写程序,他写的类一定是“上帝类”。程序员不是上帝,不要妄想成为上帝,但程序员可以写出“上帝类”。上帝是唯一的,上帝的光芒照耀人间,上帝是很爱面子的,他知道程序员写了“上帝类”,抢了他的风头,于是他降下神罚要惩戒程序员。——既然你写了“上帝类”,那么就将你流放到艰难地修改和痛苦的维护的炼狱中,在地狱之火中永久地熬炼。

你看,上帝也是有脾气的,你做了什么他都知道,你不能抢他的风头,否则你就要付出代价,受到相应的惩罚。为息帝怒,咱们还是老老实实地编写一些“小类”吧。

有些开发者为了贪图简便,看到一个现成的类,也不管这个类是做什么的,需要追加功能时,就向这个类里面添加功能代码。久而久之,使得一些类变成了“上帝类”。什么是“上帝类”?上帝类也叫万能类,意指做了太多“事情”的类。在开发基于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拆分为了CustomerOrderServiceCustomerRegistrationService

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}
}

拆分后,我们可以看到:

  • 这两个类的语义和它们的命名以及定义在其中的方法都是契合的。
  • 类的粒度变小了,代码的可读性增强了,并且有利于将来的扩展、维护、修改。

在开发过程中,我们应该保持一个良好的习惯,为类中追加功能时,尽量确认好类的职责,并控制好类的粒度,这有益于代码的可读性、扩展性、维护和修改,这样就不会被上帝发现了。

小酌重构系列目录汇总
关注keepfool

转载于:https://www.cnblogs.com/keepfool/p/5492635.html

小酌重构系列[12]——去除上帝类相关推荐

  1. 小酌重构系列[17]——提取工厂类

    概述 在程序中创建对象,并设置对象的属性,是我们长干的事儿.当创建对象需要大量的重复代码时,代码看起来就不那么优雅了.从类的职责角度出发,业务类既要实现一定的逻辑,还要负责对象的创建,业务类干的事儿也 ...

  2. 路漫漫其修远兮,吾将上下而求索——小酌重构系列[0]开篇有益

    相信博客园的读者大多都是千万"码农"中的一员,每个人都写过很多代码,但并不是每一个人都能写出高质量的代码. rome is not built in one day !--完成高质 ...

  3. 小酌重构系列[8]——提取接口

    前言 世间唯一"不变"的是"变化"本身,这句话同样适用于软件设计和开发. 在软件系统中,模块(类.方法)应该依赖于抽象,而不应该依赖于实现. 当需求发生&quo ...

  4. 小酌重构系列[19]——分解大括号

    概述 if else, for, while等是程序中最常用的语句,这些语句有一个共同点--它们的逻辑都封装在一对"{}"包围的代码块中.在实现复杂的业务逻辑时,会较多地用到这些语 ...

  5. 小酌重构系列[18]——重命名

    概述 代码是从命名开始的,我们给类.方法.变量和参数命名,我们也给解决方案.工程.目录命名.在编码时,除了应该遵守编程语言本身的命名规范外,我们应该提供好的命名.好的命名意味着良好的可读性,读你代码的 ...

  6. 小酌重构系列[4]——分解方法

    概述 "分解方法"的思想和前面讲到的"提取方法"."提取方法对象"基本一致. 它是将较大个体的方法不断的拆分,让每个"方法&quo ...

  7. 小酌重构系列[10]——分离职责

    概述 "分离职责"是经常使用的一个重构策略,当一个类担任的职责太多时,应按职责将它拆分成多个类,每个类分别承担"单一"的职责,也就是让每个类专心地做" ...

  8. 小酌重构系列[16]——引入契约式设计

    概述 试想这样一个场景,你提供了一些API给客户端调用,客户端传入了一些参数,然后根据这些参数执行了API逻辑,最终返回一个结果给客户端. 在这个场景中,有两个隐患,它们分别是: 客户端调用API时, ...

  9. 小酌重构系列[3]——方法、字段的提升和降低

    本文要介绍的是4种重构策略,它们分别是提升方法.降低方法.提升字段和降低字段. 由于这4种重构策略具有一定的相通性,所以我将它们放到一篇来讲解. 定义 以下是这4种策略的定义 提升方法:当子类的方法描 ...

  10. 小酌重构系列[20]——用条件判断代替异常

    小酌重构系列[20]--用条件判断代替异常 参考文章: (1)小酌重构系列[20]--用条件判断代替异常 (2)https://www.cnblogs.com/keepfool/p/5513946.h ...

最新文章

  1. java 分析jstack日志_望闻问切使用jstack和jmap剖析java进程各种疑难杂症
  2. mybatis的优缺点
  3. 陶哲轩发文缅怀John Conway:他是所有数学家构成的凸包中的一个极值点
  4. Linux - CentOS 6.3 (x86_64)安装过程详细图解
  5. [转载]Yacc基础
  6. LeetCode 1122 数组的相对排序-简单-unordered_map容器的应用
  7. 数据结构期末复习之选择排序
  8. Python获取文件路径:os.listdir()和os.walk()
  9. 查找 -- 7.1 Sear for a Range -- 图解
  10. 指标赋权与评价类方法总结
  11. PMP课程笔记:第12章 项目采购管理
  12. 第十四章 C语言头文件的编写_C语言模块化编程中的头文件
  13. oracle有rtf函数,Delphi中对Oracle存取RTF文档(作者:苏涌)
  14. 汇聚内容页关键词优化的小窍门
  15. Go语言环境安装及配置
  16. 阿里巴巴如何面试?网友分享出你不知道的真实面试流程(转发给有需要的人)
  17. PDF文档底部的页码怎么删除
  18. 中兴ZTE:五年工作感想
  19. sobol灵敏度分析matlab_灵敏度分析_使用MATLAB编写.doc
  20. 首届国际蜂业展在穗举办 零数科技受邀出席

热门文章

  1. 阅读器android工程,一种简单的纯粹——全球首款 EINK屏 安卓手机 BOOX E43 工程机测试体验...
  2. UTONMOS数字藏品走红之后,为艺术打开了另一条路
  3. 怎样用c语言画二次函数图像,利用几何画板演示动态的二次函数
  4. 坚持技术长征,阿里云要定义下一代的云
  5. ddl是什么意思网络语_大学赶ddl是什么意思?DDL语句有什么功能?
  6. Python模拟数据生成器全代码
  7. Ubuntu 耳机和音响没有声音
  8. python爬虫请求头是什么意思_Pytho爬虫中Requests设置请求头Headers的方法
  9. AC2100 OpenWrt 多拨
  10. 使用xpath爬取腾讯招聘python岗位信息