单一职责原则

0.一些碎碎念

最近一直在看Bob大叔(Robert C.Martin)的书籍,包括一本非常出名的《代码整洁之道》和一本不太出名的《敏捷软件开发:原则、模式与实践》。

今天才惊奇地发现,单一职责之类的设计原则原来正是Bob大叔提出来的。所以看了那么多设计模式之类的书,为啥不去看看设计原则的鼻祖提出来的书呢?很奇怪为什么没人跟我推荐过这本《敏捷软件开发:原则、模式与实践》,前辈们都是推荐的其他版本的设计模式类书籍,但是明明这本书才是最正宗的最原汁原味的啊。我是在阅读《代码整洁之道》的时候,发现有些设计模式和设计原则没有讲的透彻,又在《代码整洁之道》这本书中看到作者提到了《敏捷软件开发》这本书,所以好奇地买来看,当我收到这本书并翻开的时候,我知道它就是我一直在找的。真的强烈推荐这本书!它比很多资料讲得更生动,也更透彻,最好跟《代码整洁之道》一同阅读!从书名也可以看出来,这本书不仅讲了设计原则和设计模式,还有实践案例。通过展示在实际案例中如何应用设计模式,会给读者更加具体的指导。

以下内容来自《敏捷软件开发》一书和极客时间王争老师的专栏《设计原则之美》。

1.什么是单一职责原则

王争老师在他的专栏中这样说道:单一职责原则的英文是 Single Responsibility Principle,缩写为 SRP。这个原则的英文描述是这样的:A class or module should have a single reponsibility。如果我们把它翻译成中文,那就是:一个类或者模块只负责完成一个职责(或者功能)。

但是我更加倾向于使用《敏捷软件开发》这本书中的定义:“就一个类而言,应该仅有一个引起它变化的原因”。

注意,这里有两点,一是就一个类而言,其实这个原则是对于类的,当然,也可以针对模块而言。二是仅有一个引起变化的原因。这里我们就会疑惑,一个原因是怎么衡量的?即,我如何衡量原因的大小和数量?别着急,Bob大叔都会告诉你(可以参考Bob大叔的博客https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html)

如果一个类承担的职责过多,就等于把这些职责耦合在了一起,一个职责的变化可以会削弱或者抑制这个类完成其他职责地能力。这种耦合会导致脆弱的设计,以至于无法应对需求的变化。

这就是我们常常说的,系统的正交性弱,耦合性太强,修改了一个地方反而会影响其他的功能。这是程序员不愿意看到的。

2.什么是职责?

Bob大叔把职责定义为“变化的原因”。

3.如何判断类的职责是否是单一的

如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责。

大部分情况下,类里的方法是归为同一类功能,还是归为不相关的两类功能,并不是那么容易判定的。在真实的软件开发中,对于一个类是否职责单一的判定,是很难拿捏的。

不同的应用场景、不同阶段的需求背景下,对同一个类的职责是否单一的判定,可能都是不一样的。在某种应用场景或者当下的需求背景下,一个类的设计可能已经满足单一职责原则了,但如果换个应用场景或着在未来的某个需求背景下,可能就不满足了,需要继续拆分成粒度更细的类。除此之外,从不同的业务层面去看待同一个类的设计,对类是否职责单一,也会有不同的认识.

综上所述,评价一个类的职责是否足够单一,我们并没有一个非常明确的、可以量化的标准,可以说,这是件非常主观、仁者见仁智者见智的事情。实际上,在真正的软件开发中,我们也没必要过于未雨绸缪,过度设计。所以,我们可以先写一个粗粒度的类,满足业务需求。随着业务的发展,如果粗粒度的类越来越庞大,代码越来越多,这个时候,我们就可以将这个粗粒度的类,拆分成几个更细粒度的类。这就是所谓的持续重构.

一些小技巧,能够很好地帮你,从侧面上判定一个类的职责是否够单一

  • 类中的代码行数、函数或属性过多,会影响代码的可读性和可维护性,我们就需要考虑对类进行拆分;* 类依赖的其他类过多,或者依赖类的其他类过多,不符合高内聚、低耦合的设计思想,我们就需要考虑对类进行拆分;
  • 私有方法过多,我们就要考虑能否将私有方法独立到新的类中,设置为 public 方法,供更多的类使用,从而提高代码的复用性;
  • 比较难给类起一个合适名字,很难用一个业务名词概括,或者只能用一些笼统的 Manager、Context 之类的词语来命名,这就说明类的职责定义得可能不够清晰;
  • 类中大量的方法都是集中操作类中的某几个属性。

当一个类的代码,读起来让你头大了,实现某个功能时不知道该用哪个函数了,想用哪个函数翻半天都找不到了,只用到一个小功能要引入整个类(类中包含很多无关此功能实现的函数)的时候,这就说明类的行数、函数、属性过多了。实际上,等你做多项目了,代码写多了,在开发中慢慢“品尝”,自然就知道什么是“放盐少许”了,这就是所谓的“专业第六感”。

4.类的职责不是越单一越好。

你在将一个类拆分成多个类的时候,记住自己是在做解耦,所以不能破坏类本身的内聚性。一般情况下,你不能把类拆到只剩下一个函数。

以下内容节选自Bob大叔的博客:https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html

However it begs the question: What defines a reason to change?

who must the design of the program respond to?

Another wording for the Single Responsibility Principle is:

Gather together the things that change for the same reasons. Separate those things that change for different reasons.

If you think about this you’ll realize that this is just another way to define cohesion and coupling. We want to increase the cohesion between things that change for the same reasons, and we want to decrease the coupling between those things that change for different reasons.

However, as you think about this principle, remember that the reasons for change are people. It is people who request changes. And you don’t want to confuse those people, or yourself, by mixing together the code that many different people care about for different reasons.

posted @ 2020-03-08 20:19  代码喵在进步  阅读(250)  评论(0编辑  收藏  举报