如何使用 spring 的分层架构并仍然遵循面向对象的结构?

How to use Layered architecture of spring and still follow object oriented structure?

我学习了spring及其分层结构(controller、service和dao)

@Controller("userController")

@service("userService")
@Transactional(     propagation = Propagation.REQUIRED,     isolation = Isolation.DEFAULT,      readOnly = true)

@Repository("userDAO")

现在我很困惑如何利用 良好的 OOPS 实践(如 this)和这些分层结构来制作一个大项目(现实世界有更多复杂的业务逻辑然后通常提供示例应用程序)。我还想使用框架提供的这些 spring 事务和其他功能。 有没有人可以帮我解决这个问题,或者参考开源项目来澄清我的疑问。

简而言之

分层架构只会在代码变得庞大和复杂时简化代码的可维护性和一致性。

要记住的事实是,在执行之前进行适当的软件设计。

  • 封装 - 特定于域模型的业务逻辑应该放在其中。
  • 抽象 - 根据服务分组分离接口,同时在抽象中编写通用业务逻辑。
  • 继承 - 在起草域对象时使用
  • 多态性 - 当您想要更改子模型的业务逻辑时与继承一起使用。

详细

下面我将尽力提供一个 ERP 应用程序示例以供讨论。希望ERP足够大项目查看业务逻辑的复杂性。

下面的描述适用于任何需要了解和使用 Spring(或任何其他框架)中的分层项目结构的想法的开发人员。

但请注意,这些不是要遵循的规则,而是要使用的最佳实践。 :)


1。数据访问层 - 模型/域对象

这包含实际表到 类 的映射。

In an ERP example, this is where you get the models: CustomerOrder, CustomerOrderLine

This also contains the en-capsuled logic of child domain objects and the domain logic of self. For example, the CustomerOrderLine is a child of CustomerOrder. The child cannot exists without the parent. So the parent will have the full control of building the childs within it. ie Business logic encapsulation.. ie: Add CustomerOrderLine, RemoveCustomerOrderLine etc.. And when it comes to self domain logic, ApproveCustomerOrder, RejectCustomerOrder etc..


2。数据访问层 - 存储库

这只包含使用 SELECT, INSERT, UPDATE and DELETE SQLs 对数据库的简单 CRUD。您可以在 Spring 中使用存储库模式以及 Spring Data JPA.

重点说明:不要在这一层写任何复杂的逻辑,除非你的逻辑是高度数据密集型的

在那种情况下,您可能必须编写一个或多个函数来执行复杂的查询语句。 (最好在JPQL

In an ERP example, this is the place you write logic for GetCustomerOrders, GetCustomerOrderByCustomer, GetCustomerOrderLines, GetOrderByStatus

In simple terms this layer defines how the application will communicate with the outside entities such as Database.


3。服务层

这是您应该放置涉及多个未连接(不是子-父)域模型的复杂业务逻辑的地方。这些将在 Web 控制器和 Rest API 控制器中重复使用。

因此,为了保持一致性并实现安全性,我更希望所有业务逻辑都包含在这一层,即使是在域模型中编写的。

In the ERP exmple this is the place you write the logic or wrap the logic which is written in Domain Model. For example CreateCustomerOrder, ListCustomerOrder, ApproveCustomerOrderLine, ReleaseCustomerOrder,...

如果这些逻辑应该与其他模型逻辑一起执行,那么这些逻辑也应该在服务层内按顺序调用。例如.

关于复杂业务逻辑的杂项示例

If you want to create a Purchase Order for your supplier, when the Customer Order is released.

然后,这可以通过创建一个名为 SupplyChainService 的服务来完成,该服务使用 Spring AOP 绑定到 CustomerOrderService.ReleaseCustomerOrder。在微服务设计中,这可以通过 Supply chain 域微服务发布到队列并被 Customer Order 域微服务

消费的事件来完成

4.控制器

控制器可以分为两类,即:Web 控制器和 REST 控制器。不应在此层中实现任何业务逻辑,因为在 Web 和 API 级别中调用可能需要相同的逻辑。

In the ERP system, this is the place where you will write the controller for your customer order form to enter data and save it to create a new customer order.

This will be the place you will also create a API controller like REST to create the customer order via a mobile application or from a windows client.

感谢 SO 社区向我展示了我在这个答案中没有涉及 OOP 原则的领域

编辑


这是在微服务还不是太主流的情况下的回答。虽然它回答了 OOP 概念,但也研究了基于 CQRS 的设计,因为它在基于现代微服务的体系结构中更为常见。无论哪种方式,无论您使用何种软件架构模式,您都可以合并 OOP 概念。

我想,你在这里问错了问题。分层架构本质上不是 object-oriented,因此,虽然使用(某些)object-oriented 实践是可能的,甚至是可取的,但它本身不应该是目标。这类似于询问我如何使用最佳卡车驾驶习惯来骑自行车。

为什么我说分层架构不是面向对象的?嗯,正如我们所知,区分object-oriented设计的三个原则是:封装、继承和多态。

虽然最后两个可能存在也可能不存在,这取决于您的设计选择,分层架构几乎是封装的对立面:从这种方法的本质来看,您明确地将数据 ("DTOs") 与逻辑 ("services") 分开。

不要误会我的意思,事实上这种方法不是 object-oriented 并不意味着它有任何问题。反之亦然,"object-oriented" 不是 "good" 的同义词,它是程序员工具箱中的众多工具之一,并且与任何工具一样,它比其他工具更适合解决某些问题。

分层架构是一种很好的设计模式,可以成功用于解决许多real-life工程问题。它有自己的一组可以而且应该使用的最佳实践,虽然该集合可能与 OOP 的对应部分有一些交集,但两者肯定不等同。

您正在尝试理解可以一起互操作的两个不同概念。

分层架构

分层架构是业界的架构风格之一。在这里,我们有单独的层来执行特定的逻辑。例如我们有表示层、业务层和数据服务层。这称为应用程序的水平切片。还有其他架构风格,例如基于服务 Oriented/Component 的架构,其中应用程序是垂直切片的。

假设您有自动预订流程。通常,如果您使用分层架构设计(水平切片),那么我们有不同的层来完成所需的工作。但是当谈到垂直切片时,我们将应用程序的不同实体识别为预订、客户管理、资金管理。我们将实现这些组件,它们相互通信以构建我们的预订应用程序。这里要记住的一点是内部组件可以使用相同的分层架构。

OOPS 概念

OOPS 概念帮助您以面向对象的方式设计应用程序。一旦确定了架构风格,就必须以易于维护的可扩展方式实施应用程序。所以,他们不同的实现方法。 OOPS 在其中。它提出了一些设计原则,可以帮助您更好地实现应用程序

SOLID

Spring 应用程序设计和 OOD 并不相互排斥。

典型的 Spring (MVC) 应用程序具有以下结构:

  1. 一个或多个 @Controllerclass。这些是您的应用程序的入口点。它们不应包含任何业务逻辑。尽管名称我将它们识别为 MVC 中的 V (Model-View-Controller)
  2. 一个或多个 @Service class。这是您开发业务逻辑 (BL) 的地方。将 BL 放在这里的好处之一是它可以被多个控制器重用(例如 @Controller@RestController)。它们是MVC中的C
  3. 一个或多个 @Repository classes,您在其中实现持久层(数据库,in-memory,随便...)。此外,您可以实现一组 @Components classes 来描述您的域对象。这些是MVC中的M
  4. 其他class无法在 MVC 模式中映射的元素,例如 @Configuration@ControllerAdvice 和其他 Spring configuration/management classes.

在设计这些对象中的每一个时,您可以遵循任何您喜欢的OOD方法。

在您提到的 OOD 示例中,我会这样设计我的应用程序:

  1. 每个演员一次观看 (@Controller)
  2. 每个用例@Service
  3. 每个域一个 @Repository 和一个 @Component class

编辑:您可以找到我为大学写的示例项目 here。它使用附加层(@Controller 和@Service 之间)实现了我在最后三点中解释的内容,因为需要最小化对 C 层的依赖性。这些概念仍然适用。