如何结构化我们的代码

软件设计最佳实践,探讨按层、按特性和六边形架构/端口和适配器的代码结构。

在这篇文章中,我将探讨如何组织我们的代码并讨论最佳实践,涵盖三种不同的方法:按层、按特性和六边形架构/端口和适配器,以及它们的优缺点。

在探讨不同的代码结构方法之前,我们需要了解基本的软件设计原则:

内聚性(Cohesion) :指模块内部的类彼此相关的程度。•耦合性(Coupling) :指不同模块之间的依赖程度。

1*2Q8ye2K8hYRtNOMHWxoOBQ.png

模块性(Modularity) :指软件系统被分成独立模块的程度。每个模块封装了一组特定的功能,并被设计成能够独立工作,通过明确定义的接口与其他模块交互。•抽象化(Abstraction) :隐藏实现细节,只通过接口暴露必要的功能。•关注点分离(Separation of Concerns) :具有明确定义的各个部分,每个部分处理特定的关注点。•封装性(Encapsulation) :将数据和方法捆绑到单个模块或类中,以隐藏内部细节。

让我们更仔细地看看内聚性和耦合性?

内聚性描述软件的 关注点有多集中。它与单一职责原则密切相关。

高内聚性 意味着模块内的类彼此密切相关,并共享一个共同的、明确定义的目的。•低内聚性 意味着模块内的类关系不紧密,缺乏明确的目的,具有无关的责任。

遵循的最佳实践是追求高内聚性和松耦合

1*6DpCfIP-T09sZBfxu8G2DA.png

松散的耦合被认为是计算机系统良好结构和良好设计的迹象,与高内聚性结合使用时,可实现高可读性和可维护性。

1*WVS54T-5rqEvL7xf1AeADA.png

现在,让我们探讨不同的代码组织方式。首先,我将介绍按层组织,然后是按特性组织,对比这两者。之后,我们将探讨六边形架构/端口和适配器模式。

1*fmBZBkeP4RAmM9DwFoynyQ.png

按层组织

它表示一个项目结构,其中类被组织到多个层中,每个层负责一组特定的功能。

other 复制代码
src
├── main
│   ├── java
│   │   └── com
│   │       └── app
│   │           ├── service
│   │           │   └── UserService.java
│   │           │   └── OrderService.java
│   │           │   └── ProductService.java
│   │           ├── domain
│   │           │   └── User.java
│   │           │   └── Order.java
│   │           │   └── Product.java
│   │           ├── repository
│   │           │   └── UserRepository.java
│   │           │   └── OrderRepository.java
│   │           │   └── ProductRepository.java
│   │           ├── controller
│   │           │   └── UserController.java
│   │           │   └── OrderController.java
│   │           │   └── ProductController.java

典型的层包括:

1.表示层(Presentation Layer) :负责处理用户交互并向用户呈现信息。通常包括与用户界面、控制器和视图相关的组件。2.服务层(Service Layer) :包含业务逻辑并提供演示层所需的数据。3.领域包(Domain Package) :该包包含领域实体。4.数据访问层(Data Access Layer) :该层处理数据到/从数据库的持久化和检索。5.基础设施包(Infrastructure Package) :该包提供支持应用程序操作的服务。它可能包括用于日志记录、配置、安全等横切关注点的组件。

使用 按层组织 的一些缺点:

•低内聚性:不相关的类被组合到同一个包中。•高耦合性•封装性差:大多数类是公共的,因此我们无法将类设置为包私有,因为它们在其他层中是需要的。•低模块性:由于每个包包含与特定层相关的类,因此很难将代码分解为后来的微服务。•可维护性差:由于类散布在不同的包中,很难找到正在寻找的类。•它促进了数据库驱动设计,而不是领域驱动设计。

按特性组织

它表示一种根据功能或特性而不是层次结构组织代码的结构。在这种方法中,每个包代表一个独特且独立的功能。

目标是将与特定特性相关的所有组件(如控制器、服务、存储库和领域类)组合到一个包中。

other 复制代码
src
├── main
│   ├── java
│   │   └── com
│   │       └── app
│   │           ├── user
│   │           │   ├── UserController.java
│   │           │   ├── UserService.java
│   │           │   └── UserRepository.java
│   │           ├── order
│   │           │   ├── OrderController.java
│   │           │   ├── OrderService.java
│   │           │   └── OrderRepository.java
│   │           ├── product
│   │           │   ├── ProductController.java
│   │           │   ├── ProductService.java
│   │           │   └── ProductRepository.java

使用此结构的一些好处包括:

•高内聚性•低耦合性•强封装性:允许某些类将其访问修饰符设置为包私有而不是公共。•高模块性:由于每个包包含与特定功能相关的类,因此很容易将代码分解为后来的微服务。•可维护性:减少了在包之间导航的需求,因为所有与特性相关的类都在同一个包中。•促进了领域驱动设计

六边形架构/端口和适配器模式

六边形架构,也称为端口和适配器,是由阿利斯泰尔·科克本博士在他2005年的一篇文章中介绍的软件架构模式。[1]

该模式通过保持核心业务逻辑独立于外部细节,并不紧密耦合于数据库、用户界面或外部服务等外部依赖,促进了关注点的隔离/分离。

这使得测试、维护和发展系统更加容易。

1*wF_VJcN5dpwCQB_sx1z2_w.png

在此模式中:

1.领域/核心(Domain / Core) 代表应用程序的业务逻辑或领域(应用程序的核心)。2.端口(Ports) 端口是核心定义的接口,允许与外部组件进行交互。这些可以包括服务、存储库或任何外部依赖的接口。3.适配器(Adapters) 适配器是端口的实现。它们将核心应用程序连接到数据库、用户界面和外部服务等外部组件。适配器可以针对不同的技术或协议进行特定的实现。4.主要操作者(Primary actors) 系统的使用者,如webhook、UI请求或测试脚本。5.次要操作者(Secondary actors) 被应用程序使用的这些服务是 Repository(例如数据库)或 Recipient(例如消息队列)。

1*AUdml5HCo92xf8WgHkZfRA.gif

六边形形状:

六边形形状象征着核心应用程序位于中心,周围是适配器。这个形状代表了核心与其外部依赖之间的明确分离。

顶级包结构应如下所示:

other 复制代码
src/main/
  java
    mina
      dev
        <servicename>
          adapters
          config
          core
          <ServiceApplication>.java

根包应只包含包:coreadaptersconfig

core 包含服务的所有领域逻辑。它可以包含子包。•端口应该位于 core 包中:端口只是由核心声明的要调用或由适配器实现的接口。•adapters 包含所有适配器实现代码。它可以包含子包以按单个适配器或技术组织适配器代码。•config 包含用于连接不同组件的配置类。

包依赖规则:

•根包可以依赖于所有其他包。•config 包可以依赖于 coreadapters。•adapters 可以依赖于 core,但不可以依赖于 config。•core 不得依赖于其他任何包。

希望这篇文章能够帮助您更好地理解不同的代码结构。

引用链接

[1] 软件架构模式。: alistair.cockburn.us/hexagonal-a...

相关推荐
济南小草根1 小时前
JVM知识点学习-1
jvm·学习
爪哇学长1 小时前
如何构建一个高效安全的图书管理系统
java·spring boot·安全
材料苦逼不会梦到计算机白富美1 小时前
DIY-Tomcat项目 part 1 实现和测试Request以及Response
java·tomcat
晚渔声2 小时前
【线程】Java多线程代码案例(2)
java·开发语言·多线程
5-StarrySky2 小时前
Java 线程中的分时模型和抢占模型
java·开发语言
君败红颜2 小时前
设计模式之结构型模式
java·算法·设计模式
阿维的博客日记2 小时前
java八股-分布式服务的接口幂等性如何设计?
java·接口幂等
爱吃烤鸡翅的酸菜鱼2 小时前
Java算法OJ(11)双指针练习
java·数据结构·算法·leetcode
麒麟而非淇淋2 小时前
Day3 苍穹外卖项目 公共字段自动填充(AOP)、文件上传、新增菜品、菜品分页查询、删除菜品、修改菜品
java·mybatis
Gary董2 小时前
ArraList和LinkedList区别
java