六边形架构实现:领域驱动设计 + 端口适配器模式

07.领域驱动设计:掌握整洁架构、六边形架构以及3种常见微服务架构模型的对比和分析 DDD分层架构、整洁架构、六边形架构这三种架构模型放到一起,对比分析,看看如何利用好它们,帮助我们设计出高内聚低耦合的中台以及微服务架构。DDD分层架构、整洁架构、六边形架构都是以领域模型为核心,实行分层架构,内部核心业务逻辑与外部应用、资源隔离并解耦。请务必记好这个设计思想,今后会有大用处。 阅读详情

下面是一个更详细的六边形架构实现方案,包含清晰的架构图和完整代码实现。这个方案严格遵循领域驱动设计(DDD)和六边形架构原则,实现环境无关的数据库服务接口。

架构图

graph TD
    subgraph 外部适配器
        A[API 控制器] -->|使用| B[应用服务]
        C[数据库适配器] -->|实现| D[领域端口]
        E[消息队列适配器] -->|实现| D
    end
    
    subgraph 应用层
        B -->|依赖| F[领域服务]
    end
    
    subgraph 领域层
        F -->|依赖| D[DatabasePort]
        G[实体] --> D
        H[值对象] --> G
    end
    
    subgraph 基础设施
        I[环境配置] --> C
        J[外部服务] --> E
    end
    
    style D fill:#f9f,stroke:#333
    style F fill:#9f9,stroke:#333
    style G fill:#ff9,stroke:#333
    style C fill:#f99,stroke:#333
 

完整代码实现

项目结构

src/
├── main/
│   ├── java/
│   │   ├── com/
│   │   │   └── example/
│   │   │       ├── domain/            # 领域层
│   │   │       │   ├── model/         # 领域模型
│   │   │       │   │   ├── User.java
│   │   │       │   │    └── UserId.java
│   │   │       │   ├── service/       # 领域服务
│   │   │       │   │    └── UserService.java
│   │   │       │   └── port/          # 领域端口
│   │   │       │        └── DatabasePort.java
│   │   │       ├── application/       # 应用层
│   │   │       │   └── UserAppService.java
│   │   │       ├── adapter/           # 适配器层
│   │   │       │   ├── in/            # 输入适配器
│   │   │       │   │    └── web/       # Web控制器
│   │   │       │   │        └── UserController.java
│   │   │       │   └── out/           # 输出适配器
│   │   │       │       ├── persistence/ # 持久化适配器
│   │   │       │       │   ├── jdbc/  # JDBC实现
│   │   │       │       │   │    └── JdbcUserRepository.java
│   │   │       │       │   ├── mongo/ # MongoDB实现
│   │   │       │       │   │    └── MongoUserRepository.java
│   │   │       │       │    └── env/   # 环境选择适配器
│   │   │       │       │       └── EnvironmentAwareRepository.java
│   │   │       │       └── messaging/ # 消息适配器
│   │   │       │            └── KafkaEventPublisher.java
│   │   │       ├── config/            # 配置
│   │   │       │   └── AppConfig.java
│   │   │        └── MainApplication.java # 启动类
│   └── resources/
│        └── application.properties      # 配置文件
└── test/                              # 测试目录
 

代码实现

1. 领域层 - 模型与端口
// src/main/java/com/example/domain/model/UserId.java
package com.example.domain.model;

import java.util.Objects;
import java.util.UUID;

public final class UserId {
    private final String value;

    public UserId(String value) {
        if (value == null || value.isBlank()) {
            throw new IllegalArgumentException("User ID cannot be null or empty");
        }
        this.value = value;
    }

    public static UserId generate() {
        return new UserId(UUID.randomUUID().toString());
    }

    public String getValue() {
        return value;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UserId userId = (UserId) o;
        return Objects.equals(value, userId.value);
    }

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }
}

// src/main/java/com/example/domain/model/User.java
package com.example.domain.model;

import java.time.LocalDateTime;

public class User {
    private final UserId id;
    private String username;
    private String email;
    private final LocalDateTime createdAt;

    public User(UserId id, String username, String email) {
        this.id = id;
        this.username = username;
        this.email = email;
        this.createdAt = LocalDateTime.now();
    }

    // Getter方法
    public UserId getId() { return id; }
    public String getUsername() { return username; }
    public String getEmail() { return email; }
    public LocalDateTime getCreatedAt() { return createdAt; }

    // 领域行为
    public void updateEmail(String newEmail) {
        if (!isValidEmail(newEmail)) {
            throw new IllegalArgumentException("Invalid email format");
        }
        this.email = newEmail;
    }
    
    private boolean isValidEmail(String email) {
        return email != null && email.contains("@");
    }
}

// src/main/java/com/example/domain/port/DatabasePort.java
package com.example.domain.port;

import com.example.domain.model.User;
import com.example.domain.model.UserId;

import java.util.Optional;

public interface DatabasePort {
    Optional<User> findById(UserId userId);
    User save(User user);
    void delete(UserId userId);
}
2. 领域服务
// src/main/java/com/example/domain/service/UserService.java
package com.example.domain.service;

import com.example.domain.model.User;
import com.example.domain.model.UserId;
import com.example.domain.port.DatabasePort;
import com.example.domain.port.EventPublisher;

public class UserService {
    private final DatabasePort databasePort;
    private final EventPublisher eventPublisher;

    public UserService(DatabasePort databasePort, EventPublisher eventPublisher) {
        this.databasePort = databasePort;
        this.eventPublisher = eventPublisher;
    }

    public User createUser(String username, String email) {
        UserId userId = UserId.generate();
        User user = new User(userId, username, email);
        User savedUser = databasePort.save(user);
        eventPublisher.publish("USER_CREATED", savedUser);
        return savedUser;
    }

    public User updateUserEmail(UserId userId, String newEmail) {
        return databasePort.findById(userId)
                .map(user -> {
                    user.updateEmail(newEmail);
                    User updatedUser = databasePort.save(user);
                    eventPublisher.publish("USER_UPDATED", updatedUser);
                    return updatedUser;
                })
                .orElseThrow(() -> new RuntimeException("User not found"));
    }
}
3. 应用层服务
// src/main/java/com/example/application/UserAppService.java
package com.example.application;

import com.example.domain.model.User;
import com.example.domain.model.UserId;
import com.example.domain.service.UserService;

public class UserAppService {
    private final UserService userService;

    public UserAppService(UserService userService) {
        this.userService = userService;
    }

    public User createUser(String username, String email) {
        return userService.createUser(username, email);
    }

    public User updateUserEmail(String userId, String newEmail) {
        return userService.updateUserEmail(new UserId(userId), newEmail);
    }

    public User getUser(String userId) {
        return userService.getUser(new UserId(userId))
                .orElseThrow(() -> new RuntimeException("User not found"));
    }
}
4. 适配器层 - 输入适配器 (Web控制器)
// src/main/java/com/example/adapter/in/web/UserController.java
package com.example.adapter.in.web;

import com.example.application.UserAppService;
import com.example.domain.model.User;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {
    private final UserAppService userAppService;

    public UserController(UserAppService userAppService) {
        this.userAppService = userAppService;
    }

    @PostMapping
    public User createUser(@RequestBody CreateUserRequest request) {
        return userAppService.createUser(request.username(), request.email());
    }

    @PatchMapping("/{userId}/email")
    public User updateEmail(@PathVariable String userId, @RequestBody String newEmail) {
        return userAppService.updateUserEmail(userId, newEmail);
    }

    @GetMapping("/{userId}")
    public User getUser(@PathVariable String userId) {
        return userAppService.getUser(userId);
    }

    record CreateUserRequest(String username, String email) {}
}
5. 适配器层 - 输出适配器 (持久化实现)
// src/main/java/com/example/adapter/out/persistence/jdbc/JdbcUserRepository.java
package com.example.adapter.out.persistence.jdbc;

import com.example.domain.model.User;
import com.example.domain.model.UserId;
import com.example.domain.port.DatabasePort;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.Optional;

public class JdbcUserRepository implements DatabasePort {
    private final JdbcTemplate jdbcTemplate;
    private final String environment;

    public JdbcUserRepository(JdbcTemplate jdbcTemplate, String environment) {
        this.jdbcTemplate = jdbcTemplate;
        this.environment = environment;
    }

    @Override
    public Optional<User> findById(UserId userId) {
        System.out.println("Querying JDBC database in " + environment + " environment");
        String sql = "SELECT * FROM users WHERE id = ?";
        return jdbcTemplate.query(sql, (rs, rowNum) -> 
                new User(
                    new UserId(rs.getString("id")),
                    rs.getString("username"),
                    rs.getString("email")
                ), userId.getValue())
                .stream()
                .findFirst();
    }

    @Override
    public User save(User user) {
        System.out.println("Saving to JDBC database in " + environment + " environment");
        String sql = "INSERT INTO users (id, username, email) VALUES (?, ?, ?) " +
                     "ON DUPLICATE KEY UPDATE username = ?, email = ?";
        jdbcTemplate.update(sql, 
                user.getId().getValue(), 
                user.getUsername(), 
                user.getEmail(),
                user.getUsername(), 
                user.getEmail());
        return user;
    }

    @Override
    public void delete(UserId userId) {
        System.out.println("Deleting from JDBC database in " + environment + " environment");
        jdbcTemplate.update("DELETE FROM users WHERE id = ?", userId.getValue());
    }
}

// src/main/java/com/example/adapter/out/persistence/mongo/MongoUserRepository.java
package com.example.adapter.out.persistence.mongo;

import com.example.domain.model.User;
import com.example.domain.model.UserId;
import com.example.domain.port.DatabasePort;
import org.springframework.data.mongodb.core.MongoTemplate;

import java.util.Optional;

public class MongoUserRepository implements DatabasePort {
    private final MongoTemplate mongoTemplate;
    private final String environment;

    public MongoUserRepository(MongoTemplate mongoTemplate, String environment) {
        this.mongoTemplate = mongoTemplate;
        this.environment = environment;
    }

    @Override
    public Optional<User> findById(UserId userId) {
        System.out.println("Querying MongoDB in " + environment + " environment");
        return Optional.ofNullable(mongoTemplate.findById(userId.getValue(), User.class));
    }

    @Override
    public User save(User user) {
        System.out.println("Saving to MongoDB in " + environment + " environment");
        return mongoTemplate.save(user);
    }

    @Override
    public void delete(UserId userId) {
        System.out.println("Deleting from MongoDB in " + environment + " environment");
        mongoTemplate.remove(findById(userId).orElseThrow());
    }
}
6. 环境感知适配器
// src/main/java/com/example/adapter/out/persistence/env/EnvironmentAwareRepository.java
package com.example.adapter.out.persistence.env;

import com.example.domain.model.User;
import com.example.domain.model.UserId;
import com.example.domain.port.DatabasePort;
import java.util.Optional;

public class EnvironmentAwareRepository implements DatabasePort {
    private final DatabasePort devRepository;
    private final DatabasePort testRepository;
    private final String activeEnvironment;

    public EnvironmentAwareRepository(DatabasePort devDataSource, 
                                     DatabasePort testDataSource,
                                     String activeEnvironment) {
        this.devRepository = devDataSource;
        this.testRepository = testDataSource;
        this.activeEnvironment = activeEnvironment;
    }

    @Override
    public Optional<User> findById(UserId userId) {
        return getActiveRepository().findById(userId);
    }

    @Override
    public User save(User user) {
        return getActiveRepository().save(user);
    }

    @Override
    public void delete(UserId userId) {
        getActiveRepository().delete(userId);
    }

    private DatabasePort getActiveRepository() {
        switch(activeEnvironment.toLowerCase()) {
            case "test":
                return testRepository;
            case "dev":
            default:
                return devRepository;
        }
    }
}
7. 配置类
// src/main/java/com/example/config/AppConfig.java
package com.example.config;

import com.example.adapter.out.persistence.env.EnvironmentAwareRepository;
import com.example.adapter.out.persistence.jdbc.JdbcUserRepository;
import com.example.adapter.out.persistence.mongo.MongoUserRepository;
import com.example.domain.port.DatabasePort;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.data.mongodb.core.MongoTemplate;

@Configuration
public class AppConfig {
    
    @Value("${app.environment:dev}")
    private String environment;
    
    @Value("${app.database.type:jdbc}")
    private String databaseType;
    
    private static final String JDBC = "jdbc";
    private static final String MONGO = "mongo";

    @Bean
    public DatabasePort databasePort(JdbcTemplate jdbcTemplate, 
                                    MongoTemplate mongoTemplate) {
        // 根据不同环境创建不同的数据库适配器
        DatabasePort devAdapter = createDatabaseAdapter("dev", JDBC.equals(databaseType) ? jdbcTemplate : mongoTemplate);
        DatabasePort testAdapter = createDatabaseAdapter("test", JDBC.equals(databaseType) ? jdbcTemplate : mongoTemplate);
        
        // 返回环境感知的适配器
        return new EnvironmentAwareRepository(devAdapter, testAdapter, environment);
    }
    
    private DatabasePort createDatabaseAdapter(String env, Object template) {
        if (template instanceof JdbcTemplate) {
            return new JdbcUserRepository((JdbcTemplate) template, env);
        } else if (template instanceof MongoTemplate) {
            return new MongoUserRepository((MongoTemplate) template, env);
        }
        throw new IllegalArgumentException("Unsupported database template type");
    }
}

架构优势说明

  1. ‌领域核心隔离‌:

    • 领域模型(User, UserId)完全独立,不依赖任何框架或数据库
    • 领域服务(UserService)只依赖抽象端口(DatabasePort)
  2. ‌环境透明性‌:

    • 通过EnvironmentAwareRepository实现环境自动切换
    • 业务代码完全不知道底层使用的具体环境
  3. ‌可扩展性‌:

    • 支持多种数据库类型(JDBC/MongoDB)
    • 轻松添加新环境(如生产环境)或新数据库类型
  4. ‌可测试性‌:

    • 领域核心可独立测试,无需数据库连接
    • 可使用内存数据库或Mock对象进行测试
  5. ‌运行时配置‌:

    • 通过application.properties配置环境和数据库类型
    • 无需修改代码即可切换环境

配置示例 (application.properties)

# 可选值: dev, test
app.environment=dev

# 可选值: jdbc, mongo
app.database.type=jdbc

# 其他环境特定配置...

这种架构设计确保了业务代码与底层实现的完全解耦,调用方只需要通过统一的接口访问服务,不需要关心具体使用哪个环境或哪个数据库。当需要添加新环境或切换数据库时,只需扩展适配器层,核心业务逻辑完全不受影响。

六边形架构在Java项目中的应用:告别混乱代码的实战指南 当我第一次接触那个拥有超过50万行代码的遗留Java系统时,它已经运行了8年,由12个不同的团队维护过。表面上,它遵循经典的三层架构:表示层、业务层和数据层。但实际上,这些边界早已模糊不清。 这种代码结构导致了几个严重问题:某金融科技公司的案例特别能说明问题:他们的支付处理系统在传统架构下,平均每次功能更新需要4周时间,其中50%用于修复意外的副作用。测试覆盖率仅为40%,因为模拟外部依赖太复杂。行业内部人才才知道的洞见:大多数架构失败不是因为设计初期的决策错误,而是因为随着时间推移,团队逐渐忽视了架构边界 阅读详情

相关推荐

领域驱动设计(DDD)中的应用架构:六边形、洋葱、整洁与清晰

六边形架构、洋葱架构、整洁架构和清晰架构都是领域驱动设计中常用的应用架构模式。它们通过不同的方式来实现业务逻辑与外部系统的分离,从而提高系统的可维护性、可扩展性和灵活性。在实际项目中,应根据具体需求和团队特点选择合适的架构模式来构建健壮且易于演化的软件系统。

wjianwei666的专栏 980

领域驱动设计(六) - 架构设计浅谈

Domain Driven Design(领域驱动设计, DDD),不是一种架构而是一种架构方法论,是一种拆解业务、划分业务、确定业务边界的方法。核心思想:建立领域模型,领域模型处于架构的核心位置。核心目标:避免业务逻辑的复杂度与技术实现的复杂度混淆在一起。DDD包括战术设计和战略设计两部分。战略设计:侧重于高层次、宏观上去划分和集成限界上下文。

编程是一门实践技术 876

domain-driven-hexagon:领域驱动设计,六边形体系结构,最佳实践等指南

此仓库正在进行中 域驱动的六边形 该项目的主要重点是就如何设计软件应用程序提供建议。 在本自述文件中介绍了从不同来源收集的一些技术,工具,最佳实践,体系结构模式和指南。 下面的所有内容都应视为建议。 请记住,不同的项目有不同的要求,因此可以根据需要替换或跳过本自述文件中提到的任何模式。 代码示例使用书面 ,, 框架和数据库访问。 尽管此处介绍的模式和原理与框架/语言无关,所以可以轻松地用任何替代方法替换上述技术。 无论使用哪种语言或框架,任何应用程序都可以从以下描述的原理中受益。 注意:代码示例适用于TypeScript和上述框架,因此可能不适用于其他语言。 还请记住,此处提供的代码示例仅是示例,必须根据项目的需要或个人喜好进行更改。 目录 建筑学 主要依据: 和许多其他资源(每章下面的更多链接)。 在开始之前,这里是使用这样的完整体系结构的利弊: 优点: 独立于外部框架,技术

(一)初识领域驱动模型-六边形架构

领域驱动模型

songzerong的博客 2109

示波器学习(一):示波器的作用、类型和基本结构

示波器的作用、使用场景;示波器的类型和基本结构介绍

qq_41300605的博客 9140

PWM调光原理详解:为什么你的LED灯会闪烁?从硬件到软件的避坑指南

本文深入解析PWM调光原理,揭示LED灯闪烁的根本原因,并提供从硬件设计到软件算法的全面解决方案。通过分析人眼视觉暂留机制和PWM参数设置,帮助开发者避免频闪问题,提升照明质量。特别适合电子工程师和智能家居开发者参考。

weixin_29189363的博客 293

DDD之六边形架构(二)

统。为了有效应对软件复杂性,通常会对其进行分类,然后对症下药逐个击破。

tian830937的专栏 1632

kettle连接达梦资源库数据库插件

kettle自定义插件plugin database plugin 达梦插件 dm插件

weixin_42122126的博客 2169

GD32F4XX移植RT-Thread实战指南,六边形架构实现:领域驱动设计 + 端口适配器模式。

通过以上步骤,可完成 RT-Thread 在 GD32F4XX 上的基础移植,并进一步扩展外设功能。

2501_93981299的博客 489

破解现代反爬虫:JS加密、OB混淆与CSS反爬的实战攻防分析

摘要: 随着反爬技术的升级,JS加密、OB混淆和CSS反爬成为主流防护手段,阻碍传统爬虫获取数据。本文解析了这些技术的工作原理,并提出破解策略:通过模拟浏览器(如Selenium、Puppeteer)执行动态JS,逆向混淆代码,以及利用开发者工具突破CSS隐藏。针对复杂防护,开发者需结合技术分析与工具应用,如API接口抓取、动态渲染破解等,以应对不断演进的反爬机制。未来,爬虫攻防将持续升级,需保持技术敏锐性。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1644

Access查询中的Dlookup函数的妙用

在Microsoft Access中,处理和分析数据的过程中,常常会遇到需要根据条件从其他记录中提取特定数据的情况。这时候,Dlookup函数就成了开发者和数据分析师的得力助手。今天我们将通过一个具体的实例,详细探讨如何利用Dlookup函数来解决复杂的查询问题。

m0_62153576的博客 294

这 3 种 DDD 分层架构的模式,你掌握了么?

- 前言 -在讨论DDD分层架构的模式之前,我们先一起回顾一下DDD和分层架构的相关知识。- DDD 的基本概念 -DDD(Domain DrivenDesi...

中生代技术 518

【SAP HANA 46】关于HANA CPU高峰到 80-100%

关于HANA CPU高峰到 80-100%

探索 Java 编程的技巧、最佳实践和解决方案。本博客提供针对 Java 开发者的实用指南,涵盖从基础到高级话题,旨在提升编程效率和技能。 428

《从单体到中台:九家电商API统一适配器的DDD建模实战》(附Python源码)

九家电商API从单体泥潭进化到中台,核心不是“写九个SDK再拼起来”,而是。战术上收敛为。实测:DDD重构后,新增1家平台的平均工时从,核心业务代码零改动。

yuweide19761218的博客 182

YOLO + SubspaceAD:一张良品图,检出所有未知缺陷

当YOLO遇上子空间建模,工业质检正迎来从“见多识广”到“举一反三”的质变时刻。

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 495

【PyTorch项目实战】之ResNet系列:resnet18、resnet34、resnet50、resnet101、resnet152

ResNet (Residual Network) :是一种深度卷积神经网络(CNN)架构,其核心思想是引入残差学习(Residual Learning)机制,通过跳跃连接(skip connections)来解决深层网络训练中的退化问题。

📷 图像处理践行者 | 传统算法 · 深度学习 · 多模态 | 分享实战经验与技术洞见,探索从像素到智能的无限可能。 6372

Java 架构 03:六边形架构(端口适配器模式)落地

本文介绍了六边形架构(端口适配器模式)在Java系统中的应用。传统三层架构存在业务逻辑与技术框架耦合的问题,而六边形架构通过将核心业务逻辑置于中心,外部组件通过端口和适配器与之交互,实现了技术细节的可插拔性。 文章通过订单系统案例,展示了如何构建完全解耦的领域层: 定义输入端口(如CreateOrderUseCase)和输出端口(如OrderRepository) 实现纯Java的领域模型(Order类) 开发各种适配器(REST控制器、Kafka监听器、JPA存储等) 该架构支持灵活切换技术实现(如数据库

千淘万漉虽辛苦,吹尽狂沙始到金 2万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

六边形架构设计理论

** 六边形架构设计 ** 六边形架构 从分层架构到六边形架构,将系统划分为外层和内层,一个系统包括适配器和应用程序,由各种适配器负责应用程序与外界交互。 六边形架构还是一种分层架构,如图所示,它被分为了三层:端口适配器、应用层与领域层。而端口又可以分为输入端口和输出端口。 六边形架构将系统分为内部(内部六边形)和外部,内部代表了应用的业务逻辑,外部代表应用的驱动逻辑、基础设施或其他应用。内部通过端口和外部系统通信,端口代表了一定协议,以API呈现。一个端口可能对应多个外部系统,不同的外部系统需要使用不同

weixin_42279401的博客 9314

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

DDD with Spring深度解析:六边形架构与端口适配器模式的终极实践指南

在现代企业级应用开发中,领域驱动设计(DDD)与Spring框架的结合已经成为构建复杂业务系统的**黄金标准**。本文将深入解析如何通过**六边形架构**和**端口适配器模式**实现高效的DDD实践,帮助开发者构建可维护、可扩展的Spring应用。无论你是DDD新手还是希望提升架构设计能力的开发者,这篇**完整指南**都将为你提供实用的解决方案。 ## 📊 什么是DDD with Spring

gitblog_00751的博客 409

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

架构模式对比:分层架构、六边形架构与 DDD 在后端应用中的取舍

7 月,我在设计刷题系统时遇到了一个架构选择的问题。最开始用的是经典的分层架构(Controller → Service → Repository),代码结构清晰、上手快。后来读了一些关于"六边形架构"和"领域驱动设计(DDD)"的文章,觉得自己的代码"不够高级",于是开始重构。重构后的代码确实更"干净"了——端口适配器、领域模型、应用服务层层分离。但随之而来的是:一个简单的"用户提交题解"功能,现在需要跨越 4 个包、6 个类。每次修改一个业务规则,需要在 3 个地方做相应的调整。

cannonjinx的博客 6392

应用层架构:CQRS模式与端口适配器设计

应用层架构:CQRS模式与端口适配器设计 【免费下载链接】domain-driven-hexagon Learn Domain-Driven Design, software architecture, design patterns, best practices. Code examples included ...

gitblog_00264的博客 555

六边形架构深度解析:端口适配器、依赖倒置与测试友好设计

摘要:本文剖析了六边形架构如何通过端口适配器模式和依赖倒置原则解决传统分层架构的耦合问题。架构核心包含独立领域层(纯Java代码)和双向端口(入站/出站),适配器连接外部系统。关键优势包括:业务逻辑与框架解耦、依赖指向中心、测试友好(可替换Mock适配器)。通过接口定义契约、实现类处理具体交互,六边形架构显著提升了系统的可维护性和可测试性。

瘦到被风吹走的博客 367

2.5万字讲解DDD领域驱动设计,从理论到实践掌握DDD分层架构设计,赶紧收藏起来吧

DDD领域驱动设计分层架构,MVC模式 VS DDD模式,战略设计,战术设计,问题空间,解决空间,事件风暴,通用语言,限界上下文,上席文映射,问题域,领域,贫血模型,充血模型,领域模型,问题空间,解决空间,问题域,子域,核心子域,通用子域,支撑子域,领域事件,实体,聚合,聚合根,应用服务,领域服务,仓库,工厂,防腐层等概念)的DDD分层架构-四层架构(接口层,应用层,领域层,基础设施层)越、六边形架构,洋葱架构,整洁架构等来越热了,使代码依然整洁,利于扩展和维护,高度自治,高度内聚,边界领域划分的很清楚。

qq_41889508的博客 20万+

《领域驱动设计(Thoughtworks洞见)》读书摘记

战略层面,DDD非常强调针对业务问题的分析和分解,通过识别核心问题域来降低分析的复杂度。在战术层面,DDD强调通过识别问题域里的不同业务上下文来进行面向业务需求的组件化。最后在实现层面利用成熟的技术模式屏蔽掉技术细节的复杂度。...

小人物的草稿本 1293

领域驱动设计-架构篇

大家好,我是老王随聊。筹备了一周之久的架构篇终于出炉了……

老王随聊 2031

03.DDD六边形架构

对于程序单元A和B编译依赖:如果要编译A,必须要用到B的编译结果,则在编译期A依赖B。运行依赖:在运行期,如果B不能运行,则A一定也不能运行,则A在运行期依赖B。语义依赖:如果要理解A的语义,必须先理解B的语义,那么A在语义上依赖B。一般A在编译上依赖B,那么A在语义上也会依赖B,因为A使用的B的代码。

theflowerofac^MQLYES的专栏 1188
上一篇: 活动图讲解
下一篇: 高效存储大List对象到Redis的解决方案,使用分片存储和压缩技术
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值