关于单一责任原则的几点思考

SOLID (单一职责,开放式,封闭式,Liskov替换,接口隔离和依赖性倒置)是由“叔叔”鲍勃·马丁(Bob Martin)推广的一组原则,旨在指导开发人员实施良好的软件设计。 原则定义了面向对象的类应如何相互关联,以创建一个灵活且能够适应不断变化的代码库。

首先, 单一责任原则 (SRP)指出:

“每个模块或类都应该有一个,只有一个改变的理由。”

资料来源: 维基百科

重新思考SRP

那里有许多教程提供了很好的SRP实现代码示例,在这里展示类似的教程没有什么价值。 我在本文结尾处提供了其中一些教程的链接。

我想做的是考虑一下在日常练习中应用SRP的优点。 根据我对此主题的了解,我的直觉是SRP可能容易产生误解。 正如本文后面所解释的,SRP的定义并不十分明显,并且那里的教程通常在狭窄的上下文中查看SRP,而没有考虑更广泛的应用。 如果应用不当,我认为SRP会对您的代码造成的伤害大于好处。 为了保持平衡,我们将探讨SRP对您的代码有什么正面和负面影响,我将分享一些技巧来成功实现这一重要原则。

SRP和职责链接

作为SOLID原则的第一条,SRP可能处于开发人员思想的最前沿,特别是因为与其他原则相比,它的定义看似简单。 不过,这是SRP的第一个问题 。 它自己的名称清楚地提到了责任,但随后的定义似乎与此没有多大关系。

发生什么了?

SRP和更改链接

在深入研究Bob叔叔的著作时,我们看到SRP确实是在处理变更源,特别是组织中的参与者最终利用了应用程序提供的功能。 他非常正确地指出,参与者的需求可以并且将会发生变化,因此,为参与者提供服务的功能也会发生变化。 最终,他将“责任”定义为“为一个特定演员服务的职能家族”。

不使用SRP的后果

那么,如果您打破了单一责任,会发生什么? 如果一个班级承担多个责任,那么改变的原因就不只一个。 如果一个班级承担多个责任,那么责任就成对了。 对一项职责的更改可能会削弱或阻碍班级履行其他职责的能力。 这种耦合导致脆弱的设计,在更改时会以意想不到的方式破坏。

好的,听起来很合逻辑。

具有多个职责的大型整体课程是不好的

那有什么选择呢?

走“小”……很多“小”

在线阅读许多文章,您会看到SRP的常见实现是从大型的整体类到包含大量方法的小型类。 这里的危险是,当您在设计中引入越来越多的类时,就会暴露出新的风险。 极端的是,Marco Ceconni在他的题为“ 我不爱单一责任原则 ”的文章中指出,针对SRP的shot弹枪方法可能导致大量贫血的微类 ,而这些微类几乎无济于事,并使代码库的组织复杂化。

更多抽象不一定导致代码更小,更稳定

起初,表面上似乎引入了新的抽象是一件好事,特别是如果它们代表了已达成共识的领域模型的某些方面,则尤其如此。 在代码中可以准确地表示企业对世界的看法,从而使开发人员和领域专家可以共享通用(普遍存在)的语言 。 另一方面,马什·巴达(Mash Badar)在他的“ 抽象思维 ”一文中指出,引入新类(或一般而言,抽象)通常会使整体代码更多而不是更少。 作为业务领域一部分的任何抽象特别容易受到更改的影响。 一旦在设计中嵌入了新的抽象,对它的更改仍然有可能导致代码库其他地方发生意外更改。

确定变更源的麻烦

很难确定更改源,这是SRP定义的核心。 变化的来源可能由我们无法控制的未知因素驱动。 因此,我们努力做出最佳猜测,确保我们的代码可以适应变化,并在迭代过程中继续降低风险。 但是即使有最好的意图,不仅仅未知因素会对良好的软件设计构成风险,而且在如何管理未知风险方面也已达成共识 ,这可能是同等或更大的风险。 如果确定变更源的过程是主观的,则我们将基于有缺陷的假设进行分类设计,从长远来看,它将没有什么成果。

因此,就像许多公认的软件开发“最佳实践”一样,在SRP方面似乎有两个方面。

可怜的开发者该怎么办?

有关应用SRP的一些建议准则

1.在耦合和内聚之间取得平衡

为了以最小的复杂度组织代码, Marco Ceconni建议在使用SRP时取得平衡。 班级应为:

  1. 足够小以降低耦合,但是
  2. 足够大以最大化内聚力。

第二点很重要,而且有可能被忽略。 关键信息是不要不必要地创建新的抽象,例如,如果从逻辑上讲两个类是合并而不是分开是合理的。 每个类都应该“发挥自己的作用”,这意味着应该一致清楚地表明一个类在应用程序中所扮演的角色及其所提供的价值。

2.不要过早优化

时机,尤其是考虑应用程序在项目生命周期中的位置的做法当然值得您考虑。 在项目生命周期中过早地执行单一职责将导致一系列问题。 如前所述,基于业务域的抽象在整个生命周期中尤其容易受到更改的影响,一开始可能更是如此。

在我最近的一个宠物项目中,我确实犯了过早优化的错误。 我在不知不觉中,在项目开始时就过于宽松地应用了SRP。 我站在那儿,凝视代码库,当我看着我的小型封装类队伍时,为自己感到骄傲。 问题是我的数据模型有误。 我必须对此进行一些重大更改,最终在整个代码库中引起巨大的涟漪效应。 不用说,结果我花了很多时间来修复我的代码,而这个错误结束了对该博客的启发。

3.如有疑问,请保持简单

最后,当不确定何时应用SRP时,请询问哪种选择更有可能使代码库的简单性最大化。 从代码中退后一步 ,并逐步浏览应用程序的结构。 更妙的是,可以成对工作或得到审查。 如果您太少或过多地应用SRP,它将很快变得显而易见。

最后,值得考虑的是,SRP只是SOLID中旨在实现良好代码设计的5条原则之一。 推荐阅读的是《简单设计四个规则》 ,正如书名所示,它采用了另一种简单的软件设计方法。 很棒的是,它考虑了SOLID的所有方面,包括SRP以及良好软件设计的其他常见理论。

加起来

尽管单一责任的意图似乎有良好的基础,但其实施可能会更加棘手。 SRP的定义是模糊的,容易引起误解,即使对该定义已广为人知,但在日常实践中应用SRP可能产生积极和有害的影响。 如果您考虑应用程序的更广泛的上下文,项目生命周期以及最终通过采用使代码库保持尽可能简单的策略,则SRP的成功实现更可能发生。

翻译自: https://www.javacodegeeks.com/2016/07/thoughts-single-responsibility-principle.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值