基于领域驱动设计架构创建node端Api服务

本文基于领域驱动设计(DDD)的架构实现用户注册功能。在DDD中,关注点在于围绕业务域创建模型,通常涉及实体(Entities)、值对象(Value Objects)、领域服务(Domain Services)、应用服务(Application Services)等。

总述传送门

1. DDD项目的文件结构

在my-koa-ddd-project项目文件夹中,创建以下结构:

bash 复制代码
mkdir my-koa-ddd-project && cd my-koa-ddd-project
npm init -y
npm install koa koa-router koa-bodyparser sequelize mysql2

# 创建DDD目录结构
mkdir -p src/domain src/application src/infrastructure

# 创建文件
touch src/app.js
touch src/domain/user.js
touch src/application/userService.js
touch src/infrastructure/router.js
touch src/infrastructure/database.js

2. 领域模型(Domain Model)

文件路径: src/domain/user.js

javascript 复制代码
class User {
  constructor(username, password) {
    this.username = username;
    this.password = password; // 在实际应用中应加密处理
  }

  // 可以添加领域逻辑,如密码验证等
}

module.exports = User;

3. 应用服务(Application Service)

文件路径: src/application/userService.js

javascript 复制代码
const User = require('../domain/user');

class UserService {
  async registerUser(username, password) {
    // 在这里实现应用逻辑,例如调用领域模型
    const user = new User(username, password);
    // 保存用户逻辑(伪代码)
    // await database.saveUser(user);
    return user;
  }
}

module.exports = UserService;

4. 路由和应用程序入口

文件路径: src/infrastructure/router.js

javascript 复制代码
const Router = require('koa-router');
const UserService = require('../application/userService');

const router = new Router();
const userService = new UserService();

router.post('/register', async (ctx) => {
  const { username, password } = ctx.request.body;
  try {
    const user = await userService.registerUser(username, password);
    ctx.body = { message: 'User registered successfully', user };
  } catch (error) {
    ctx.status = 400;
    ctx.body = { message: error.message };
  }
});

module.exports = router;

应用程序入口文件:

文件路径: src/app.js

javascript 复制代码
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const router = require('./infrastructure/router');
// const sequelize = require('./infrastructure/database');

const app = new Koa();

app.use(bodyParser());
app.use(router.routes()).use(router.allowedMethods());

// 假设数据库连接和同步已经设置好
```javascript
// sequelize.sync()
//   .then(() => {
//     console.log('Database connected.');
//   })
//   .catch((err) => {
//     console.error('Unable to connect to the database:', err);
//   });

const port = 3000;
app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

module.exports = app;

在这个DDD示例中,创建了一个简单的用户注册功能,包括领域模型(User)和应用服务(UserService)。用户通过发送POST请求到/register路由来注册,请求包含他们的用户名和密码。应用服务(UserService)处理创建用户的逻辑,而领域模型(User)定义了用户数据和相关业务逻辑。

DDD架构的关键在于业务逻辑的深入理解和丰富表达。实体和服务的划分更多地依赖于业务领域的复杂性和具体需求。此架构有助于管理复杂的业务规则,并在业务逻辑变化时提供更好的灵活性和可维护性。对于大型项目,特别是那些涉及复杂业务逻辑和多个子域的项目,DDD提供了一个清晰的框架来组织和管理代码。


English version

For an architecture based on Domain-Driven Design (DDD), we continue to implement the user registration feature. In DDD, the focus is on creating models around the business domain, often involving entities, value objects, domain services, application services, and more.

1. File Structure of the DDD Project

Inside the my-koa-ddd-project project folder, create the following structure:

bash 复制代码
mkdir my-koa-ddd-project && cd my-koa-ddd-project
npm init -y
npm install koa koa-router koa-bodyparser sequelize mysql2

# Create DDD directory structure
mkdir -p src/domain src/application src/infrastructure

# Create files
touch src/app.js
touch src/domain/user.js
touch src/application/userService.js
touch src/infrastructure/router.js
touch src/infrastructure/database.js

2. Domain Model

File Path: src/domain/user.js

javascript 复制代码
class User {
  constructor(username, password) {
    this.username = username;
    this.password = password; // In a real application, encryption should be applied
  }

  // You can add domain logic here, such as password validation, etc.
}

module.exports = User;

3. Application Service

File Path: src/application/userService.js

javascript 复制代码
const User = require('../domain/user');

class UserService {
  async registerUser(username, password) {
    // Implement application logic here, e.g., calling the domain model
    const user = new User(username, password);
    // Save user logic (pseudo-code)
    // await database.saveUser(user);
    return user;
  }
}

module.exports = UserService;

4. Routing and Application Entry

File Path: src/infrastructure/router.js

javascript 复制代码
const Router = require('koa-router');
const UserService = require('../application/userService');

const router = new Router();
const userService = new UserService();

router.post('/register', async (ctx) => {
  const { username, password } = ctx.request.body;
  try {
    const user = await userService.registerUser(username, password);
    ctx.body = { message: 'User registered successfully', user };
  } catch (error) {
    ctx.status = 400;
    ctx.body = { message: error.message };
  }
});

module.exports = router;

Application entry file:

File Path: src/app.js

javascript 复制代码
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const router = require('./infrastructure/router');
// const sequelize = require('./infrastructure/database');

const app = new Koa();

app.use(bodyParser());
app.use(router.routes()).use(router.allowedMethods());

// Assume that database connection and synchronization are already set up
```javascript
// sequelize.sync()
//   .then(() => {
//     console.log('Database connected.');
//   })
//   .catch((err) => {
//     console.error('Unable to connect to the database:', err);
//   });

const port = 3000;
app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

module.exports = app;

In this DDD example, we have created a simple user registration feature, including the domain model (User) and application service (UserService). Users register by sending a POST request to the /register route, which includes their username and password. The application service (UserService) handles the logic for creating the user, while the domain model (User) defines the user data and related business logic.

DDD architecture focuses on a deep understanding and rich expression of business logic. The division between entities and services depends more on the complexity of the business domain and specific requirements. This architecture helps manage complex business rules and provides better flexibility and maintainability when business logic changes. For large projects, especially those involving complex business logic and multiple subdomains, DDD offers a clear framework for organizing and managing code.

相关推荐
晚风叙码3 小时前
MySQL 数据类型详解:从数值到字符串,一篇讲透
android·mysql·adb
做运维的阿瑞4 小时前
SQL 面试高频:用户、商品、订单三表查询全解析
数据库·sql·mysql
CJi0NG4 小时前
【自用】MySQL - 语法:DDL、DML、DQL、DCL
数据库·mysql
一技安身5 小时前
【mysql】Windows MySQL 8.4.10 绿色免安装喂饭教程
windows·mysql·adb
斯内普吖6 小时前
(开源)宠物饲养系统实战指南 基于 Java + SSM + Vue + MySQL
java·vue.js·mysql·开源·宠物
ao-weilai6 小时前
MySQL数据库:表约束
数据库·mysql·adb
梦帮科技8 小时前
【3.0修订版】 RNS 代币架构:ERC20 五件套扩展与六钱包分配
数据结构·后端·算法·架构·node.js·区块链·php
FYKJ_20109 小时前
springboot心理健康管理系统86254-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·mysql·django·课程设计
做运维的阿瑞9 小时前
MYSQL从语义到执行计划:UNION、EXISTS、IN 的深度辨析
数据库·sql·mysql
小马同学-20 小时前
MySQL主从复制和读写分离
数据库·mysql