为什么类的职责要单一化?

类的职责单一化很容易吗?

首先,我要提醒一下看到这篇文章的同学,我认为保证类(一定是类吗?)的单一职责并不容易

软件开发过程中,自古就流传着几大规则,无论如何这里都要和大家阐述一遍

单一职责原则

一个类应该只有一个发生变化的原因

开闭原则

软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。这个原则是诸多面向对象编程原则中最抽象、最难理解的一个。

里氏替换原则

所有引用基类的地方必须能透明地使用其子类的对象,换句话说,子类在任何引用基类的地方都可以替换成子类。

依赖倒置原则

这个原则说的详细一点其实可以概括为两点:

  1. 高层模块不应该直接依赖于底层模块,应该依赖于抽象

  2. 抽象不应该依赖于具体实现,具体实现应该依赖于抽象

接口隔离原则

程序不依赖于不使用的接口,换句话说,一个程序只依赖于它需要的接口。

单纯从概念上讲呢,单一职责原则可算是最简单易懂的一种原则了,就像设计模式中的单例模式一样无趣,是这样吗?

谁的职责

说实话,看过不少讲解“职责单一”设计原则的文章,都是以类来阐述。其实我觉得不对,职责单一设计原则本质上是软件设计原则的一种思想,具有指导意义。至于谁的职责需要单一,是一个伪命题,不仅仅指面向对象编程中的类,系统的模块,甚至于微服务在架构设计中也应该遵循此规则。

在面向对象设计的理解中,程序最基本的组成单位是类(class),多个类组成模块(module),多个模块组成服务(service),多个服务组成系统(system),一般的软件系统都会存在以上几个概念。

无论是类,还是模块,还是服务,还是系统,我认为设计的时候都要保证“单一职责”。

单一真的容易吗

说到“单一”职责,每个人都有不同的看法

class UserInfo
{//用户idpublic int UserId{get ;set ;}//用户登录账号public string Account{get;set ;}//用户登录密码public string Pwd{get ;set;}//用户姓名public string Name{get ;set ;}}

以上是最常见的用户信息实体,你认为它职责单一吗?说一说,我自己的看法:

站在用户信息的角度来说,这个类代表的是用户信息,它就是单一的,这也是大多数人的看法,有错吗?其实没错。因为在当前场景下,它确实是这样。

随着业务的发展,用户的信息字段会越来越多,比如:用户的年龄,性别,学历....等等。看着越来越大的UserInfo类,是否该拆分呢?

这个时候我觉得你可以根据用户信息的类型来进行拆分,毕竟大而全的类其实并不好。怎么拆分呢?比如:可以根据用户登录场景拆分出用户认证的类型

class UserAuth
{//用户idpublic int UserId{get ;set ;}//用户登录账号public string Account{get;set ;}//用户登录密码public string Pwd{get ;set;}
}

可以根据用户信息在系统中的出现频率和重要度拆分出用户基本信息和用户扩展信息

class UserBasicInfo
{//用户idpublic int UserId{get ;set ;}//用户姓名public string Name{get ;set ;}//用户手机号public string Phone{get ;set ;}//其他基本属性
}
class UserExtendnfo
{    //用户邮箱public string Email{get ;set ;}//用户QQ号public string QQ{get ;set ;}//其他属性
}

当然这里我只是举个栗子,如果用户的Email和手机号一样常用,可以把Email属性提到基本属性中。

以上只是以用户信息为例,根据不同的用途进行拆分的一个栗子。在不同的业务背景下,不同的业务阶段,对同一个类的拆分可能会有很大不同。有的时候,你所认为的"正确“会随着系统的发展慢慢变成”错误“,当然这种”错误“并不可怕,毕竟系统的架构都是慢慢迭代出来的。

总之呢,评价一个类是否一定满足单一原则,并没有一个统一标准和规范,在实际的开发中,也没有必要进行过度设计,在项目初级,完全可以是一个满足业务需求的大而全的类,随着业务的发展,你必然会经历拆分的过程,这也是软件发展的必然阶段。

以上只是针对类这个最基本的面向对象单位来聊了聊,上升到模块以及系统也是一样的道理,微服务也是随着软件开发的不断演进而出现的,其实从职责上来看,微服务也是职责单一原则的产物,而这个这则单一更多的是倾向于业务单一性,并非功能单一性。

那职责拆分的越细越好吗?我不这么认为,当一个类或者模块甚至系统,被拆分过细的时候,就会面临着维护的问题,拿微服务来说,当微服务的数量过多,就会面临着治理等一系列问题,这也是K8s要解决的问题之一。

拆分原则

说到底,虽然职责单一很难在主观上给予准确判断,但是还是有一些通用规则可以借鉴,这里以类为例

  • 高内聚。系统在修改任一功能的时候,只需要修改一处地方,如果你需要修改多处才能满足某个需求,很有可能你的职责划分的不合理

  • 属性过多。当一个类属性过多的时候,可以考虑把这个类进行职责的拆分。而至于多少个才算多呢?当查找某个属性令你头疼的时候,说明已经到了可以拆分的程度了(自己杜撰)

  • 依赖过多。当一个类型中依赖的资源过多的时候,可以进行拆分

  • 独立变化。当一个类的某些属性被大量使用而且会经常变化的时候,可以考虑把这些属性进行拆分成独立的类。

说到职责单一,这里顺便提一下接口的设计,接口的设计更要遵循职责单一的原则,接口本质上是对业务的抽象,不同的业务应该抽象成不同的接口,以保证每个类,每个模块,每个系统都可以独立扩展。

论系统设计的高可扩展性

写在最后

没有绝对好的方法可以让所有人都认为你的拆分是正确的“职责单一”,有的时候,怎么样才能职责单一真是要靠“灵感”

面试官扎心一问:数据量很大,分页查询很慢,有什么优化方案?

吊打MySQL,MariaDB到底强在哪?

程序员过关斩将--领导说我的类的职责不单一相关推荐

  1. 程序员过关斩将--论商品促销代码的优雅性

    点击上方蓝色字体,关注我们 菜菜哥,YY说你帮她解决了几个问题,也帮我解决一个呗 原来是D妹子,来坐我身边,说下情况 我的项目是个电商项目,现在产品狗要给商品做活动 正常呀 我一个新手初来咋到顶不住压 ...

  2. 程序员过关斩将--从未停止过的系统架构设计步伐

    " 首先,这篇文章肯定会得罪一些人 " 其次,此文只代表我个人的意见,仅供参考 从分层说起 谈到系统架构的分层和系统领域边界的划分,每个架构师,每个技术经理,甚至每个程序员都有自己 ...

  3. 程序员过关斩将--作为一个架构师,我是不是应该有很多职责?

    点击上方"蓝字"关注我们领取架构书籍 每一个程序员都有一个架构梦. 上面其实本质上是一句富有事实哲理的废话,要不然也不会有这么多人关注你的公众号.这些年随着"企业数字化& ...

  4. 程序员过关斩将--为微服务撸一个简约而不简单的配置中心

    点击上方蓝字  关注我们 毫不犹豫的说,现代高速发展的互联网造就了一批又一批的网络红人,这一批批网红又极大的催生了特定平台的一大波流量,但是留给了程序员却是一地鸡毛,无论是运维还是开发,每天都会担心服 ...

  5. 程序员过关斩将-- 工作好多年可能还未真正了解接口和抽象类

    点击上方"蓝字"关注我们 菜菜哥,我偷偷出去面试了,然后面试官让我回来等消息 那你可能挂了呀,有什么问题没回答上来吗 确实有一个问题回答的不太好哎,就是接口和抽象类 这个确实是面试 ...

  6. 程序员过关斩将--redis做消息队列,香吗?

    菜菜哥,我刚做完了一个订单系统,感觉很简单呀 说说看,大量的订单状态怎么处理的? 我设计的时候可是考虑了这一点,所以用了异步处理,采用了MQ 那用的什么MQ呢,透露一下呗 我用的redis做的MQ,很 ...

  7. 程序员过关斩将--你为什么还在用存储过程?

    点击上面"蓝字"关注,带你看好电影 菜菜哥,我新接手了一个项目,看的我头疼呀 业务有这么复杂呀? 不是的,这个老项目完全是用存储过程写的,每个存储过程都好几百行 这样呀,是够头疼的 ...

  8. 程序员过关斩将--你的面向接口编程一定对吗?

    菜菜哥,出大事啦 怎么了,你和男票分手了?很正常,谁让你男票是产经经理呢 不是啦,是我做的一个小游戏,需求又变了,程序我快改不动了 说来让我欢乐一下? 菜菜哥,咱两还能不能好好相处了 玩笑 玩笑,sh ...

  9. 程序员过关斩将--少年派登录安全的奇幻遐想

    " 据说,这篇也是快餐,完全符合年轻人口味 说到登录,无人不知无人不晓.每一个有用户体系的相关系统都会有登录的入口,登录是为了确认操作人的正确性.说到登录安全,其实是一个很伟大的命题,不过常 ...

最新文章

  1. 我潜入清华神秘实验室,用脑机接口写了两句诗
  2. C语言 位移运算符的使用
  3. UA MATH564 概率论VI 数理统计基础3 卡方分布中
  4. anaconda+python3.6利用命令安装BeautifulSoup4-4.6.0
  5. Freemarker基于模板字符串生成静态化html文件
  6. 独热编码 one-hot Encoding
  7. python经典实例-Python机器学习经典实例
  8. python:numpy.random.shuffle打乱顺序函数
  9. IM消息重试机制Java实现_消息的重试机制的设计思路
  10. ubuntu系统共享桌面的使用和配置
  11. 小目标 | 4周学会用邮箱管理时间和工作流
  12. unity|火焰和烟效果(粒子系统)
  13. 51nod1423 最大二“货”
  14. 惠州市有哪些学计算机的学校,惠州有哪些好学校?
  15. halcon 图像合成与通道
  16. 【计算机视觉与深度学习 北京邮电大学 鲁鹏 视频笔记】1. 线性分类器
  17. opencv 单个圆形孔和针检测
  18. 计算机领域常用的英文名称和缩写,计算机常用英文缩写.doc
  19. 文章汇总【就R不E让I找D到系列part1】
  20. html load c,loadtxt()函数的糟心历程

热门文章

  1. Express框架开发知识点总结
  2. JavaScript之闭包
  3. git add * 提示warning: LF will be replaced by CRLF in 解决办法
  4. HDU - 5686-Problem B (递推+高精)
  5. SqlServer之代码块相关
  6. OOD之问题空间到解空间—附FP的建模
  7. thinkphp的select和find的区别(转)
  8. 将数据库设置为运行在限制模式下
  9. 如何组合救援磁盘以创建最终Windows修复磁盘
  10. 火狐 增强查找工具栏_在“提示”框中:简单的IE至Firefox同步,轻松的Windows工具栏和识别USB电缆...