1 什么是单一职责(SRP)原则

单一职责原则的英文是 Single Responsibility Principle,缩写为 SRP。翻译过来就是:一个类或者模块只负责完成一个职责(或者功能)。

所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。

很多人认为这个原则是针对一个类进行描述,在我看来这里使用模块这个更加抽象的名词更为合适。在设计中,小到一个方法,大到一个模块我们都应该尽量取遵循单一职责原则。

2 为什么要遵循单一职责

相信在我们日常开发中,每个人都遇到过改了一个问题经常会引起另一个问题。其原因大多都是因为在设计上违背了单一职责原则。

如果一个类承担的职责过多,就等于把这些职责耦合在一起了。一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当发生变化时,设计会遭受到意想不到的破坏。而如果想要避免这种现象的发生,就要尽可能的遵守单一职责原则。此原则的核心就是解耦和增强内聚性,是为了实现代码高内聚、低耦合,提高代码的复用性、可读性、可维护性。。

如下图,就是一个非常明显的不满足单一职责的类。我们的业务类UserService中包含了add、log、persistence三个方法,同时也包含了三个职责业务添加、日志记录、持久化。而实际上我们的业务规则可能是经常变化的,但是我们的持久化方法和日志记录是不常变化的。由于耦合在一个类中我们频繁改动的业务方法,很有可能影响到日志记录与持久化。又或者是我们日志记录和持久化方法这与业务无关的变动也很有可能影响到我们的正常的也业务逻辑。

正确的做法是将他们分离开来。

3 如何判断职责是否足够单一

对于单一职责这一原则的定义和描述,相信每一个程序员都能张口就来。它理解起来也并不难,即我们不要设计大而全的类或模块,要尽量设计粒度小、功能单一的模块。但实际应用过程中确是非常困难的,也是一个非常有争议性的原则,原因就在于如何去判断职责是否足够单一。就像做菜一样,“放盐少许”,那么这个少许到底是多少?你与专业大厨的区别就在于对这个度的把握。

程序设计也是如此,上面那个例子是非常简单的一眼就能区分职责。但实际开发中往往有很多场景会让你对职责是否单一的判定难以拿捏。

如下面这个用户类是否满足单一职责呢?

我们可以看到,省市区地址信息在用户信息类里面,这种情况下你说它满足不满足似乎都有道理。这时就要根据具体的业务场景来看,如果你的业务场景中地址信息仅仅作为用户信息的一部分展示来看,这么设计就是合理的。而如果你的地址信息有一些单独的逻辑,那么就是不符合单一职责的。比如电商系统。

此时我们就要把地址信息拆分出来

再如社交系统中,也许起初地址信息只是用于用户信息的一部分来展示,但是随着业务的发展多了一些根据地址信息推荐好友等特殊的需求。那么我们就要在业务演进的过程中把类进行拆分。

综上所述,我们可以总结出

  1. 不同的应用场景,对同一个类的职责是否单一的判定,是不一样的。我们需要具体场景具体分析
  2. 一个类的设计可能已经满足单一职责原则了,但可能随着需求的迭代在未来的某个时候就不再满足单一职责原则了,此时我们没必要过于未雨绸缪,过度设计。可以先满足业务需求。随着业务的发展,如果类变得越来越庞大,代码越来越多,不再满足单一职责,这个时候,再把这个类持续进行重构拆分。

4 职责设计是否越单一越好

我们再来思考一个问题,为了满足单一职责原则,是不是把类拆得越细就越好呢?

比如我们常用与接口通信的类与序列化操作类

这时如果我们进一步把Get、 Post, Serialize,Derialize进行拆分到两个类里面,看似更好的遵循了单一职责原则,但实际上如果我们的协议格式发生改变或者序列化方式发生改变,那么就要去更改两个类的代码,如果我们漏掉了一个,后果可想而知。

5 不满足单一职责的坏味道

随着开发经验的积累,我们是很容易嗅到一些不满足单一职责的坏味道的

  1. 类的代码行数过多
  2. 类依赖的其他类过多
  3. 过长的方法
  4. 私有方法过多
  5. 不容易给类起名字,类名中包含两个或以上的名词

小结

单一职责原则是开发中最基础,最简单,确是最难把握的一个原则,我们需要不断地学习以及大量经验的积累,才能更好的掌握它。此外没有最好的设计,只有合适的设计,我们需要结合真实的业务场景。记住:无论任何的思想与原则的最终目的是让我们的代码具有更好的可读性、可维护性、可扩展性......

系列文章

设计原则:单一职责(SRP)

设计原则:开闭原则(OCP)

设计原则:里式替换原则(LSP)

设计原则:接口隔离原则(ISP)

设计原则:依赖倒置原则(DIP)

何谓高质量代码?

理解RESTful API

关注下方公众号,回复“代码的艺术”,可免费获取重构、设计模式、代码整洁之道等提升代码质量等相关学习资料

设计原则:单一职责(SRP)原则的更多相关文章

  1. 编写具有单一职责(SRP)的类

    这两周我需要对一个历史遗留的功能做一些扩展,正如很多人不愿意碰这些历史遗留的代码一样,我的内心也同样对这样的任务充满反抗.这些代码中充斥着各种null判断(你写的return null正确吗?),不规 ...

  2. 六大设计原则——单一职责原则【Single Responsibility Principle】

    声明:本文内容是从网络书籍整理而来,并非原创. 用户管理的例子 先看一张用户管理的类图:  再看一眼上面的图,思考:这样合理吗? 这个接口是一个很糟糕的设计! 用户的属性和行为竟然混合在一起!!! 正 ...

  3. S.O.L.I.D五大原则之单一职责SRP

    转自 : 汤姆大叔的blog Bob大叔提出并发扬了S.O.L.I.D五大原则,用来更好地进行面向对象编程,五大原则分别是: The Single Responsibility Principle(单 ...

  4. 深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP

    前言 Bob大叔提出并发扬了S.O.L.I.D五大原则,用来更好地进行面向对象编程,五大原则分别是: The Single Responsibility Principle(单一职责SRP) The ...

  5. 面向对象设计原则 单一职责原则(Single responsibility principle)

    单一职责原则(SRP:Single responsibility principle) 又称单一功能原则,面向对象的基本原则之一.它规定 一个类应该只有一个发生变化的原因. 该原则由罗伯特·C·马丁( ...

  6. 设计模式值六大原则——设计模式之六大原则——单一职责原则(SRP)

    定义: 应该有且仅有一个原因引起类的变更. There should never be more than one reason for a class to change. 优点: 1.类的复杂性降 ...

  7. Java设计原则—单一职责原则(转)

    定义: 应该有且仅有一个原因引起类的变更. There should never be more than one reason for a class to change. 优点: 1.类的复杂性降 ...

  8. 【设计原则和编程技巧】单一职责原则 (Single Responsibility Principle, SRP)

    单一职责原则 (Single Responsibility Principle, SRP) 单一职责原则在设计模式中常被定义为“一个类应该只有一个发生变化的原因”,若我们有两个动机去改写一个方法,那这 ...

  9. 面向对象设计原则一:单一职责原则(SRP)

    单一职责原则(SRP) 定义:系统中的每一个类都应该只有一个职责. 好处:高内聚.低耦合. 解释说明: 单一职责也就是说我们应该让一个类或一个对象只做一件事情,每个类所要关注的就是自己要完成的职责是什 ...

随机推荐

  1. requestAnimationFrame & canvas

    requestAnimationFrame & canvas https://codepen.io/xgqfrms/pen/jOEPjLJ See the Pen requestAnimati ...

  2. 翻译:《实用的Python编程》01_06_Files

    目录| 上一节(1.5 列表) | 下一节 (1.7 函数) 1.6 文件管理 大多数的程序需要从某处读取输入.本节讨论文件访问. 文件输入和输出 打开一个文件: f = open('foo.txt' ...

  3. 你见过老外的 Java 面试题吗 (上)?

    前言 最近无聊的在逛某 tube 网站,本来想看看大家是怎么吐槽川普的,结果无意间点进了一个老外面试 Java 的视频,对于常年面试被吊打的我瑟瑟发抖,于是决定进去一探究竟. 毕竟不是专业的后台开发, ...

  4. 看完了进程同步与互斥机制,我终于彻底理解了 PV 操作

    尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 CS-Wiki(Gitee 官 ...

  5. 顶级c程序员之路 选学篇-1 深入理解字节,字节序与字节对齐

     深入理解字节,字节序与字节对齐 一 总述 作为一个职业的coder玩家,首先应该对计算机的字节有所了解. 我们经常谈到的2进制流,字节(字符)流,数据类型流(针对编程),结构流等说法,2进制流,0和 ...

  6. Coposition 详解

    LifeCycle Hooks 在新版的生命周期函数,可以按需导入到组件中,且只能在setup()函数中使用. import { onMounted, onUnmounted } from 'vue' ...

  7. 最近没事DIY了个6通道航模遥控器

    在网上买了个外壳,挖空后换成自己的电路版. 开机后图: 液晶屏是320x240的,没有合适的贴纸,直接就这么用了 遥控器的内部电路有点乱哈,没办法,低成本就只能全靠跳线了 还好都能正常工作. 接收器也 ...

  8. 【图像处理】使用OpenCV进行图像处理教程(一)

    OpenCV是进行图像处理的工具,也是计算机视觉领域近十几年不断发展和完善的产物.面对这个已基本成熟的开源库知识体系,我们新生代有必要不断地总结.回顾,以新的视角快速融入计算机视觉的奥秘世界. 从这篇 ...

  9. Nginx配置翻译

    Windows 格式 server { listen 82; server_name localhost; root "D:/testfile/"; location / { in ...

  10. sap2000v21安装教程(附详细安装步骤+中文安装包)

    sap2000 v21是sap2000系列软件的全新版本,也是目前行业中的一款用于结构分析和设计的集成软件,该软件保持了原有产品的传统,具有完善.直观和灵活的界面,能够在交通运输.工业.公共事业.体育 ...