软件设计之美
郑晔
开源项目 Moco 作者
19890 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 42 讲
软件设计之美
15
15
1.0x
00:00/00:00
登录|注册

20 | 单一职责原则:你的模块到底为谁负责?

你好!我是郑晔。
经过前面的讲解,我们对各种编程范式已经有了基本的理解,也知道了自己手上有哪些可用的设计元素。但只有这些元素是不够的,我们还需要一些比编程范式更具体的内容来指导工作。从这一讲开始,我们就进入到设计原则的学习。
在众多的原则中,我们该学习哪个呢?我选择了 SOLID 原则,因为 SOLID 原则是一套比较成体系的设计原则。它不仅可以指导我们设计模块(在面向对象领域,模块主要指的就是类),还可以被当作一把尺子,来衡量我们设计的有效性。
那 SOLID 原则是什么呢?它实际上是五个设计原则首字母的缩写,它们分别是:
单一职责原则(Single responsibility principle,SRP)
开放封闭原则(Open–closed principle,OCP)
Liskov 替换原则(Liskov substitution principle,LSP)
接口隔离原则(Interface segregation principle,ISP)
依赖倒置原则(Dependency inversion principle,DIP)
这些设计原则是由 Robert Martin 提出并逐步整理和完善的。他在《敏捷软件开发:原则、实践与模式》和《架构整洁之道》两本书中,对 SOLID 原则进行了两次比较完整的阐述。在这两本时隔近 20 年的书里,你可以看到 Robert Martin 对 SOLID 原则的理解一步步在深化,如果你想了解原作者的思考,这两本书都推荐你阅读。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

单一职责原则的重要性在于确保模块只有一个变化的原因,从而降低代码的复杂性和频繁变动。文章通过实例阐述了单一职责原则的内涵和应用场景,强调了将不同需求引起的变动拆分开来的重要性。作者指出,单一职责原则不仅适用于类的设计,还可以指导不同子系统之间的职责分配。此外,文章还提到了康威定律对单一职责原则的影响,以及如何将其应用于不同层次的设计。总结时刻强调了单一职责原则的本质是分离关注点,需要将模块拆分成更小的粒度,并且应用该原则衡量模块时,粒度越小越好。读者在阅读完本文后,将能够深入理解单一职责原则的思路和方法,以及如何在现有系统设计中改进不符合该原则的地方。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《软件设计之美》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(26)

  • 最新
  • 精选
  • Demon.Lee
    老师,请教一个类的循环依赖问题。 以文章和评论为例,并假设一篇文章的评论,一般在100~1000条之间。 我设计的时候,文章和评论是两个service:ArticleService和CommentService【同一个服务中的两个类,不是两个微服务中的两个类】。 1. 新增一篇文章:调用ArticleService; 2. 发表一条评论:调用CommentService,但CommentService需要先调用ArticleService校验文章是否存在,然后再保存评论【CommentService中依赖了ArticleService】; 3. 删除文章(要求把评论删除):先调用ArticleService删除文章,再调用CommentService删除评论【ArticleService中依赖了CommentService】; 由于业务比较简单,所以就没有使用异步之类的方式来避免循环依赖。 老师,我的设计是否不对?还请解惑。

    作者回复: 这个设计的关键在于哪里是访问的入口,也就是聚合的根。在这个例子里,根就是Article。所以,所有的访问都从ArticleService进去就好了。

    2020-09-30
    4
    29
  • giteebravo
    ·不能简单的把单一职责原则理解为「一个类只做一件事」 ·在做设计时,要考虑引起变化的原因,分而治之 ·更进一步,若能考虑到变化的来源是什么,那就 perfect 了

    作者回复: 总结得很到位!

    2020-07-22
    11
  • sam
    变化仍在,只是通过单一职责原则进行分别,减少变化带来更大的影响。

    作者回复: 这是一个现实的选择,不能完全规避的话,就尽可能限制。

    2020-07-19
    8
  • 阳仔
    单一职责原则,相信很多人都了解过,但为何还是会出现高度耦合,职责不明的代码逻辑? 我觉得最根本原因是没有深入理解这个职责内涵(当然我自己也是),一开始的时候我们都自信满满的希望写出漂亮的代码,但随着版本迭代过程中,需求也不断变化,不知不觉就陷入到了变化之中。我们应该把这个原则铭记于心,当我们要修改这个模块或者类的时候,都要思考一下 我为何要修改这个类?这部分修改可不可以放在其它地方?

    作者回复: 指望每个人铭记是不现实的,需要配合代码评审去发现问题。

    2020-07-13
    8
  • 邵俊达
    郑老师,关于单一职责我有一个疑问,比如我要做的一件事儿是「把大象装进冰箱里」,这件事会分为 3 步: 1. 把冰箱门打开 2. 把大象放进冰箱 3. 把冰箱门关上 如果是用一个类/函数来完成「把大象装进冰箱里」的话,这个类/函数里面会分别调用 3 个方法(把冰箱门打开、把大象放进冰箱、把冰箱门关上),这样 这个类/函数在另一个角度就不是「只做一件事」了,这是否违背了「单一职责」原则呢?

    作者回复: 难道不是直接调用“把大象装进冰箱里”这一个函数吗?对这个类的用户来说,它就是一个函数,内部怎么实现是这个类设计者的问题,不要把复杂度交给用户。

    2021-08-14
    3
    6
  • Being
    老师提出的三个理解,是个层层递进的过程。 单个原子性模块固化下来的越多,可积累的就越多。

    作者回复: 对,这个理解没有问题。

    2020-07-14
    4
  • 桃子-夏勇杰
    找到那个谁,才有后续的职责澄清。重点不在单一,而在谁,否则,单一就是对自己的限定[得意]

    作者回复: 那个谁,这个说法,哈哈哈!

    2020-07-27
    3
  • Jxin
    1.老项目大部分应该都没有规范吧。自然也不会有符合单一职责这一说法。 2.要保障类或方法单一职责,并不总是单纯分割代码。更常见的,是要通读逻辑后,通过重构一点一点分离,对原逻辑改动还是比较大的。 3.我经常说接口要标准化,单一职责就是这里面的一个指标。写新项目可以逼着自己遵守这个。我不接受引入设计原则会降低需求迭代的认知,我相信刻意训练熟能生巧,有序的设计实现功能不会比无厘头的翻译功能慢,更多的是因为手生。但老项目,需不需要改进比如何改进重要。

    作者回复: 一点一点改动,很有 10x 程序员的味道。

    2020-07-13
    3
  • 蓝士钦
    问一个和单一职责不那么相关的问题,service层提供接口和模型,controller层调用service层方法,controller对外并不想暴露所有数据库字段,这样就需要controller对返回的数据集做一次加工,是否有必要。

    作者回复: 有。

    2020-07-28
    2
  • Janenesome
    看起来最简单的原则,其实做起来也挺难的,日拱一卒吧。 有意识去做关注点分离的人挺少的,大部分都是代码能 work 就行。 等有意识了,想去做也不容易。分离关注点、厘清职责与模块边界,哪个是容易的?只能多练多想多对比了。 有这个意识了就能抛开一部分人,能坚持下去精进的就又能抛开一部分人了,加油。 回答文章的问题:现有系统设计中很少会遵循单一原则的,很多黄金大锤般的大类,开发的时候也很少会认真花时间去思考新加的接口放在哪里合适的。 最近公司在评估和申请企业版,希望身边多些人来一起学习,有好的代码环境才更有动力持续进步。

    作者回复: 知易行难

    2020-10-23
    1
收起评论
显示
设置
留言
26
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部