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

发布于 2024-08-28 18:58:40 字数 413 浏览 11 评论 0原文

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

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

Suppose we are designing a UserServiceImpl class which does CRUD (Create, Read, Update, and Delete) operations. In my view Create, Read, Update, and Delete are four reasons for a class to change. Does this class violates Single Responsibility Principle? If it violates,
then should we have four classes like CreateUserServiceImpl, ReadUserServiceImpl,
UpdateUserServiceImpl, and DeleteUserServiceImpl. Isn't it an overkill to have lots of
classes?

Suppose I define 4 interfaces each for create, read, update, and delete operations and my
service class implements all the four interfaces. Now I can only have a single
implementation class but by separating their interfaces I have decoupled the concepts as
far as rest of the application is concerned. Is this the right way or you see some problems
in it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

凌乱心跳 2024-09-04 18:58:40

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

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

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

That's what I love about patterns and principles - they are a consist way for everyone to disagree on software design as much as agree :-)

My view would be to build the class in whatever way makes it a usable and easy to understand class - depending on the complexity and context within which the class lives. With a simple implementation and context, a single class will do. You could say it does adhere to the SRP because it's responsibility is to manage the CRUD operations. But if the implementation is complex, or there's a lot of shared code that would be suitable for placing in an abstract parent class, then perhaps 4 separate classes, one for each CRUD operation make more sense. it's all about how you look at it.

Patterns and principles are great things, but used incorrectly they can make a simple problem just as complex as not having them.

仲春光 2024-09-04 18:58:40

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

为什么?

如果我有一个 Stack 类,PushPop 是该类更改的原因吗?

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

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

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

In my view Create, Read, Update, and Delete are four reasons for a
class to change.

Why?

If I have a Stack class, are Push and Pop reasons for the class to change?

I don't think so. These are two standard operations people do with a stack. The same with CRUD, it is a simple, established, well-known set of operations over a data storage.

Now your underlying storage technology itself IS a reason for your class to change. That is if your CRUD implementation is hard-coded to only work with a specific instance of an MS SQL 6.0 database, then you violate SRP and the class will not be easily reusable or extandable.

With regards to 4 interfaces, that is closer to another SOLID principle, the ISP, and the need here is determined by the patterns of usage of your data storage. For example, if some classes will only need to Read from the data storage it makes total sense to extract an interface with just the Read method and request that interface as an argument to such methods. By separating this interface you can later on make a separate implementation of it. Who knows, maybe for read-only clients you can issue a better optimized query or use a memory cache, but if not -- you can just pass them the instance of your default data storage implementing this interface.

Hello爱情风 2024-09-04 18:58:40

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

It does not violate the single responsibility principle till the service is responsible for the data services of a single type or business info.

っ左 2024-09-04 18:58:40

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

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

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

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

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

I would think that the Dao classes would target a single entity which in this case is the user. Then the service classes would receive the Dao as a dependency. The service classes would then apply an interface where it has methods as part of its interface and those service methods call Dao methods. Here you have the best of both worlds which is a Dao consisting of all crud operations relating to the user table and then Service classes with specific names e.g UserPointsUpdater which call whatever Dao methods they want. This could be a single Dao method or several Dao methods to get the job done.

This way we adhere to ISP and SRP. Our code is clear in what we are trying to do for each event.

You could always break your Daos into smaller classes which may target a specific column within a table if the entity it targets starts to have multiple complex methods peforming CRUDs on several columns.

The event specific service objects target whatever Dao methods they need for that specific event, but receive the Dao relating to that entity.

If you don’t have Daos and envoke methods directly within the service class (which I wouldn’t recommend for many reasons, such as testing to name just one) then I would make these classes event specific and use inheritance/composition to prevent DRY.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文