如何将单一职责原则应用于服务类

问题描述 投票:0回答:4

假设我们正在设计一个 UserServiceImpl 类,它执行 CRUD(创建、读取、更新和删除)操作。在我看来,创建、读取、更新和删除是类更改的四个原因。这个类是否违反了单一职责原则?如果违反的话, 那么我们应该有四个类,如

CreateUserServiceImpl
ReadUserServiceImpl
UpdateUserServiceImpl
DeleteUserServiceImpl
。拥有很多是不是有点过分了 上课?

假设我定义了 4 个接口,每个接口用于创建、读取、更新和删除操作,我的 服务类实现了所有四个接口。现在我只能拥有一个 实现类,但通过分离它们的接口,我将概念解耦为 就应用程序的其余部分而言。这是正确的方法还是您发现了一些问题 在里面?

oop solid-principles single-responsibility-principle
4个回答
5
投票

这就是我喜欢模式和原则的原因 - 它们是每个人对软件设计的不同意见和同意的一致方式:-)

我的观点是,以任何使其成为可用且易于理解的类的方式来构建该类——具体取决于类所在的复杂性和上下文。通过简单的实现和上下文,一个类就可以了。您可以说它确实遵守 SRP,因为它的职责是管理 CRUD 操作。但如果实现很复杂,或者有很多共享代码适合放在抽象父类中,那么也许 4 个独立的类(每个 CRUD 操作一个)更有意义。这完全取决于你如何看待它。

模式和原则是伟大的东西,但如果使用不当,它们可能会使一个简单的问题变得像没有它们一样复杂。


3
投票

在我看来,创建、读取、更新和删除是创建、读取、更新和删除的四个原因 班级要改变。

为什么?

如果我有

Stack
课程,课程更改的
Push
Pop
原因是什么?

我不这么认为。这是人们对堆栈执行的两个标准操作。与 CRUD 相同,它是对数据存储的一组简单、既定、众所周知的操作。

现在你的底层存储技术本身就是你的类改变的一个原因。也就是说,如果您的 CRUD 实现被硬编码为仅适用于 MS SQL 6.0 数据库的特定实例,那么您就违反了 SRP,并且该类将无法轻松重用或扩展。

关于 4 个接口,这更接近另一个 SOLID 原则,ISP,这里的需求取决于数据存储的使用模式。例如,如果某些类只需要从数据存储中读取,那么仅使用 Read 方法提取接口并请求该接口作为此类方法的参数是完全有意义的。通过分离这个接口,您可以稍后对其进行单独的实现。谁知道呢,也许对于只读客户端,您可以发出更好的优化查询或使用内存缓存,但如果没有,您可以将实现此接口的默认数据存储的实例传递给它们。


1
投票

服务只负责单一类型或业务信息的数据服务,不违反单一责任原则。


0
投票

我认为 Dao 类将针对单个实体,在本例中是用户。然后服务类将接收 Dao 作为依赖项。然后,服务类将应用一个接口,该接口将方法作为其接口的一部分,并且这些服务方法调用 Dao 方法。在这里,您可以两全其美,这是一个由与用户表相关的所有增删改查操作组成的 Dao,然后是具有特定名称的 Service 类,例如 UserPointsUpdater,它可以调用他们想要的任何 Dao 方法。这可以是单个 Dao 方法或多个 Dao 方法来完成工作。

这样我们就遵守 ISP 和 SRP。我们的代码很清楚我们要为每个事件做什么

您始终可以将 Dao 分解为较小的类,如果它的目标实体开始具有在多个列上执行 CRUD 的多个复杂方法,这些类可能会针对表中的特定列。

事件特定服务对象以该特定事件所需的任何 Dao 方法为目标,但接收与该实体相关的 Dao。

如果您没有直接在服务类中使用 Dao 和 envoke 方法(出于多种原因,我不会推荐这种方法,例如仅举一个例子进行测试),那么我将使这些类特定于事件,并使用继承/组合来防止干燥。

© www.soinside.com 2019 - 2024. All rights reserved.