设计原则-单一职责原则

单一职责原则

概述

在软件领域,我们有时候写代码的过程中,有时候会遇到一些问题,这些问题已经被前人进行总结 归纳。 帮助我们在遇到问题的时候,如何写出更加优雅的代码,更加简洁的代码,更加没有重复的代码等。 于是就出现了很多设计原则,通过这些设计原则可以帮助我们写出更加优雅的代码,以及可以应对以后 代码的可能变动。实现低耦合,高内聚,代码复用的特点。 今天我们就来学习 软件设计原则之一,单一职责原则 这一原则开起来 简单,但实际在工作编码过程中 却很容易忽略。写代码的时候,可以多想想有没有坚持这个原则,刻意地朝这个方向努力吧。 废话不多说,进入正题。

单一职责原则,英文缩写SRP,全称Single Responsibility Principle

原始定义:There should never be more than one reason for a class to change。

官方翻译:应该有且仅有一个原因引起类的变更。简单点说,一个类,最好只负责一件事,只有一个引起它变化的原因。

  • 一个类应该仅有一个引起它变化的原因
  • 变化的方向隐含着类的责任(职责)

单一职责原则问题由来

类T 负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生问题.

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

职责如何理解呢? 什么是职责呢 ?

在 SRP中 职责就是 “变化的原因” (a reason for change), 如果你能想到有两个原因 将来会修改这个类,那么就说明 这个类承担了多个职责. 其实有的时候,我们却很难意识到这一点, 总是会把一个类 写的比较大,功能比较全面,所谓"功能强大"的类.

举例1 Rectangle

class Rectangle:
    """
    假设这个类

    有两个不同的 application 使用

     一个application 有关计算几何学的, 这个类会提供几何形状计算方面的帮助, 但它从来不会绘制矩形

     另一个application 有关图形绘制方面的, 它可能也会进行几何学方面的工作,但是它一定会在屏幕上绘制矩形.



    这个设计违反了单一职责原则(SRP).Rectangle类具有两个职责
        第一个职责提供了一个矩形几何形状的数学模型;
        第二个职责是把矩形在一个图形用户界曲上绘制出来。

    """

    def draw(self) -> None:
        pass

    def area(self) -> float:
        pass

所以 应该职责划分更加清晰一些,类似下面的代码一样, 职责明确.

class Rectangle:
    def draw(self) -> None:
        pass


class GeometricRectangle:
    def area(self) -> float:
        pass

个人理解

当然这些都是建立 在我的虚拟假设上 将来有一个应用 会使用两个方法, 一个应用 只会使用一个方法, 计算面积.并且两个这两个应用是独立的. 如果说 这个应用 同时会用到 几何形状计算, 和绘制的方法, 我觉得就没有必要 分成两个单独的类. 因为此时 改变这个类的原因只有一个. 即职责也只有一个. 所以对职责的界定 相对 比较宽松,取决于你 系统的环境.

再来回忆一下 职责: 变化的原因

举例2 Modem

假设有一个调节器, 有以下接口:

from abc import abstractmethod


class Modem:
    """
    调制解调器
    """

    @abstractmethod
    def dial(self, pro):
        pass

    @abstractmethod
    def hungup(self):
        pass

    @abstractmethod
    def send(self):
        pass

    @abstractmethod
    def recv(self):
        pass

首先看这个类 有四个接口. 都是和调解器的接口. 看起来也很合理. 但是仔细想想

这个有两个职责 ,连接管理 和 数据通信 .

连接管理
dail
hungup

数据通信
recv
send

这个时候有必要把它们分开吗? 这要考虑一个问题, 如果 应用程序的变化会影响 连接的方式,那么就要分开这个职责. 另外一方面 如果应用程序变化会导致 这两个职责同时变化,那么就没有必要拆分它们. 实际上拆分它们就会具有不必要的复杂性的臭味.

在此还有一个推论, 变化的轴线仅当变化实际发生时,才有意义. 如果没有征兆 ,就去应用SRP, 这是不明智的. 就是取决于系统的变化. 系统如果不变, 这样的设计也没有什么问题啊.

SRP核心思想

SRP 核心思想就是 要降低类的修改成本,防止未来发生变化,改动一个类的很多处,难免会出现问题. 把职责明确划分好后,这样就可以应对以后的变化. 打个比方, 你是想把工具归置到许多抽屉, 每个抽屉中装有定义和标记良好的工具箱, 还是想把少数几个能随便把所有东西扔进一个抽屉呢? 我想 你会把不同的物件 归置到不同的抽屉里面吧,这样 第一方便查找,第二方便修改,可以应对未来可能的变化.

目标:

我们的目标就是要分离耦合的职责, 使不同的职责 在不同的类中, 而不是一个类中有多个职责.

总结

本文主要介绍了SRP 这种设计理念,当然这种理念,需要在不断写代码中,慢慢体会就好. 不可直接照搬理论,需要根据实际的场景,灵活应对. 主要在于理解 职责 这个重要的概念, 在不同的环境下,可能划分中不同的职责,也有可能是一个职责,也有可能有多个职责.

参考文档

敏捷软件开发:原则,模式,实践

代码整洁之道

小话设计模式原则之:单一职责原则SRP

分享快乐,留住感动. '2022-01-11 18:35:23' --frank
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值