|SOLID之单一职责原则:简约而不简单

|SOLID之单一职责原则:简约而不简单

文章图片


SOLID是5个面向对象设计原则英文单词的缩写 , 旨在帮助软件设计变得可理解、可伸缩、可维护 。 在 Robert C. Martin(他是一位软件工程师 , 也是一位大学老师)2000年的文章《设计原则和设计模式中》 , 这5个原则首次被提出来 。 SOLID原则分别指:
单一职责原则:有且只有一个引起变更的原因
开闭原则:软件实体应该被设计为对扩展开放 , 对修改关闭
里式替换原则:使用基类引用(或指针)的方法 , 应该无需关注基类的继承(派生)类 , 就能够使用 。 也可以参考面向契约的设计
接口隔离(分割)原则:多个有明确职责的接口要由于一个通用目的的接口 , 只关注需要的接口 。
依赖注入原则:依赖抽象 , 而非具体 。
考虑到表达的抽象性 , 我们把维基百科的英文原文也贴在这里 , 方便对照 。 我们也会对这5个原则用“人话”逐个进行解读 , 并且给出代码示例 。

在后面的章节里 , 我们会分若干部分对这几个设计原则进行分析和理解 , 我们先从单一职责原则( Single-Responsibility Principle)开始 。
单一职责是指任何一个模块、类、方法的都应该只有一个职责 , 他们提供的能力和方法 , 包括底层的封装也应该只跟他们的职责相关 。
Robert C. Martin , 在解释单一职责是提到一个类只有一个使其变更的理由(reason) , 快赶上中文一样的抽象了 。 举个栗子就说 , 我是餐厅的服务员 , 我的职责好多 , 比如为顾客点菜、为顾客上菜、为顾客结账 , 我就有很多使我“变更的理由” 。 如果遵循单一职责原则的话 , 我只承担一个职责即可 , 我是点菜服务员 , 他是上菜服务员 , 还有结账服务员 。
在新手工程师做CRUD开发时很容易写出像saveUser(user)的接口出来

也许刚开始还蛮高兴的 。 看 , 我一个接口就搞定了用户创建 , 用户更新 , 而且用户更新还能处理更新用户名 , 激活用户 , 删除用户等各种操作 , 真是一个全能接口 。
但越到后面 , 这个接口就越来越失控了 , 比如激活用户是什么时候触发的?创建用户的时候和更新用户名的时候 , 对用户的校验应该是差异非常大的?如果这个接口是对外提供的服务 , 如果他只想激活用户 , 却不小心传了个用户名 , 如果跟原来的一样 , 貌似也没问题 , 但说不定哪天传个不一样的用户名就暴雷了 。
一个模块承担的职责越多 , 意味着引起它内部发生变化的因素越多 , 因为代码是需要人去维护的 , 所以关注不过来的时候就容易出问题了 。 小到一个接口 , 需要做到适当的封装 , 做Code Review的时候我们常常定个规约说每个方法不能超过200行;大到一个微服务 , 其实都是为了将责任更加清晰的划分出来 。
化整为零 , 化繁为简 , 一个软件就是一套精密的仪器 , 每个模块的作用如果单一的、可预期的、好测试的、健壮的 , 那么所有的模块组合在一起才能够值得信赖 。
笔者原文发布在CSDN , 欢迎点击查看:
【|SOLID之单一职责原则:简约而不简单】也可以前往(请给我一根烟的时间)查看更多个人心得和分享 , 和笔者一起互相讨论