单一职责原则有什么用?

What is the use of single responsibility principle?

我试图理解单一职责原则,但我很难理解这个概念。我正在看书"Design Patterns and Best Practices in Java by Lucian-Paul Torje; Adrian Ianculescu; Kamalmeet Singh ."

在这本书中我正在阅读单一职责原则章节, 他们有车的地方[​​=29=]如下图:

他们说Car既有Car逻辑也有数据库操作。将来如果我们想要更改数据库,那么我们需要更改数据库逻辑,并且可能还需要更改汽车逻辑。反之亦然...

解决方案是创建两个 classes,如下所示:

我的问题是即使我们创建了两个 classes ,让我们考虑我们正在向 class CAR 添加一个名为“price”的新 属性 [或者改变 属性 'model' 到 'carModel' ] 那么你不认为我们还需要更新 CarDAO class 就像改变 SQL 等等。

那么SRP在这里有什么用呢?

要添加新的 属性,只有当 属性 应该保存到数据库时,您才需要更改两个 classes。如果它是业务逻辑中使用的 属性 那么您不需要更改 DAO。此外,如果您将数据库从一个供应商更改为另一个供应商或从 SQL 更改为 NoSQL,您将只需要在 DAO class 中进行更改。如果您需要更改一些业务逻辑,那么您只需更改 Car class.

好问题。

首先,请记住这是书中的一个简单示例。 reader 可以对此进行一些扩展并想象更复杂的场景。在所有这些场景中,进一步想象你不是团队中唯一的开发人员;相反,您在一个大型团队中工作,开发人员之间的沟通通常采用协商 class 接口 APIs,public 方法的形式, public 属性,数据库模式。此外,您经常需要担心回滚、向后兼容性以及同步发布和部署。

例如,假设您要换出数据库,例如,从 MySQL 到 PostgreSQL。使用 SRP,您将重新实现 CarDAO,更改使用的任何方言特定 SQL,并保持 Car 逻辑不变。然而,您可能需要做一个小的改变,可能是在配置上,告诉 Car 使用新的 PostgreSQL DAO。合理的 DI 框架将使这变得简单。

假设,在另一个示例中,您希望将 CarDAO 委托给另一个开发人员以与 memcached 集成,这样读取虽然最终一致,但速度很快。同样,该开发人员不需要了解 Car 中的 业务逻辑 的任何信息。相反,他们只需要在 CarDAO 的 CRUD 方法后面操作,并可能在 CarDAO API 中声明一些具有不同一致性保证的方法。

假设,在另一个示例中,您的团队雇用了一名专攻合规性法律的数据库工程师。在为即将到来的 IPO 做准备时,数据库工程师的任务是在公司的 35 个数据库中保存所有 table 的所有更改的审计日志。有了 SRP,我们勇敢的 DBA 就不必担心使用我们任何 table 的任何 业务逻辑 ;相反,他们的突变跟踪魔法可以巧妙地注入到整个 DAO 中,使用装饰器或其他方面的编程技术。 (顺便说一下,这也可以在 SQL 界面的另一侧完成。)

好吧,最后一个 - 假设现在一名系统工程师加入了团队,其任务是在 AWS 的多个区域(数据中​​心)之间分片数据。这位工程师可以更进一步地使用 SRP 并添加一个组件,该组件的唯一作用是为每个 ID 告诉我们每个实体的家乡区域。每次我们进行跨区域读取时,新组件都会触发一个计数器;每周,自动化工具都会将经常跨区域读取的数据迁移到新的主区域以减少延迟。

现在,让我们把想象力放得更远,假设业务蒸蒸日上 - 突然间,您在一家财富 500 强公司工作,其多个部门横跨多个国家。财务部的业务分析师希望使用您的 table 在他们的 post-IPO 投资者报告中绘制汽车销售的季度增长图。与其让他们访问 Car(因为用于报告的逻辑可能不同于用于准备在 Web 上呈现的数据的逻辑 UI),您可以潜在地创建一个只读的CarDAO 的界面,其中包含您现在必须跨部门边界维护的精心策划的 public 属性的简短列表。上帝禁止您必须重命名其中一个属性:为 3 个月的日落计划和许多悲伤的仪表板和深夜升级做好准备。 (并且请不要让他们直接访问实际的 SQL table,因为隐含的假设是整个 table 是 the public界面。)哎呀,我的伤疤可能要露出来了。

一个推论是,如果您需要在 Car 中更改 业务逻辑 (例如,添加一个方法来计算每辆特斯拉的较低销售价格令人尴尬的回忆),您不会触摸 CarDAO,因为 if car.brand == 'Tesla; price = price * 0.6 与数据访问无关。

补充阅读:CQRS

Single responsibility principle 如 Robert C. Martin 所述,意味着

A class should have only one reason to change.

牢记这一原则通常会导致更小和高度内聚的 类,这反过来意味着更少的人需要同时处理这些 类,并且代码变得更健壮。

在您的示例中,将数据访问业务逻辑(价格计算)逻辑分开意味着您不太可能破坏更改时其他。