单一职责原则(Single Responsibility Principle SRP)
参考书籍
敏捷软件开发 原则、模式与实践
Agile Software Development Principles, Patterns, and Practices
什么是单一职责
参考书中,职责被定义为:a reason for change,变化的原因。怎么理解呢?
在我目前的认知深度里职责和功能似乎是一样的,因为她们存在相似相关性,因此,我个人似乎总喜欢将职责潜意识定位成功能。疑惑也随之而至,陈述一个类应该具有单一职责,让我久久想不明白。一条语句实现的是一个功能,一个函数也常常被设计成仅完成单一功能的模块。基于语句的划分的确粒度太细,那么单一职责的类就只能有一个函数吗?可是这完全不符合现实情况。
通过仔细的思考,我认为书中所说的职责和潜意识里的我所定义的功能还是有区别的。书中的职责是从提供服务和请求服务模型中来陈述的,也就是说这里的职责是请求服务者所能看到的提供服务者所具有的功能。之前我是站在类自身的角度对职责和功能进行区分的,所以看不清他们的区别。
再看 a reason for change ,有了上面的陈述后理解“变化的原因”应该不难。因为,根据上下文我们可以推断出,变化的原因实际上隐式地指服务提供者需要变化的原因,是服务提供者需要变化。那么,谁才是变化的需求者呢?毫无疑问,服务的请求者。可理解为,当服务请求者需求发生变化,服务提供者就应该发生变化满足需求。客户真是上帝。服务提供者提供的服务是其职责,在这里职责和变化的原因就自然产生了一一对应的关系,因此可以用变化的原因来定义职责。
总结:什么是职责,职责就是类向外能够提供的服务。单一职责指的是一个类应该仅向外提供一种类型的服务。
为什么要保证单一职责
关于为什么要保证单一职责我们可以这样考虑,假如不保证单一职责会产生什么问题。其实,产生的问题主要出现在具体代码的生成和运行流程上,例如编译、链接、部署以及运行。
问题1,当一个类有多个职责时,一个仅请求其中一个职责的服务请求者需要在编译时要编译他不需要的代码,在链接时要链接他不需要的代码,在运行时要加载他不需要的代码,因此会浪费编译时间、链接时间以及运行时的内存占用。
问题2,当一个类有多个职责时,如果一个服务请求者的需求发生变化,那么该类就要做出变化,这种变化会导致另一个服务请求者也要相应地发生变化,例如,重新构建、测试以及部署。
具体情况具体分析
当然,并不是所有的地方都必须做到单一职责,具体是否需要做到单一职责应该按具体的使用环境进行判断。
如果一个具有多个职责的类每次发生变化时都是这几个职责同时发生变化,那么就有理由不需要将这几个职责进行分离。
如果一个具有多个职责的类,其中某些职责总是发生频繁变化,而另一些却不是,那么强烈推荐进行职责分离。
切记,如书中所说,如果没有征兆,那么去应用SRP或者任何其他原则都是不明智的。