使用DDD模型实现服务

举报
码乐 发表于 2025/02/24 10:18:14 2025/02/24
80 0 0
【摘要】 1 简介本文介绍在web服务中应用DDD领域驱动思想? 使用一个管理系统用于说明DDD的设计和使用步骤,如何帮助管理系统的实现。在web框架 中实现 DDD(领域驱动设计) 的费用管理系统需要遵循以下步骤,将系统分为清晰的领域层次和模块。DDD 强调 领域模型的核心地位,围绕 实体、值对象、领域服务 构建应用,同时解耦应用层和基础设施层。 2. DDD 的基本分层DDD 通常分为以下几个层...

1 简介

本文介绍在web服务中应用DDD领域驱动思想? 使用一个管理系统用于说明DDD的设计和使用步骤,如何帮助管理系统的实现。

在web框架 中实现 DDD(领域驱动设计) 的费用管理系统需要遵循以下步骤,将系统分为清晰的领域层次和模块。DDD 强调 领域模型的核心地位,围绕 实体、值对象、领域服务 构建应用,同时解耦应用层和基础设施层。

2. DDD 的基本分层

DDD 通常分为以下几个层次:

  用户界面层(Interface Layer):负责与外部交互,比如 HTTP 请求处理。
  应用层(Application Layer):负责用例编排,调用领域层完成业务流程。
  领域层(Domain Layer):包含业务逻辑核心,包括实体、值对象、领域服务、聚合根等。
  基础设施层(Infrastructure Layer):与数据库、外部服务、消息队列等基础设施交互。
  • 管理系统的业务背景

功能需求:

管理用户的费用记录(增、删、改、查)。
按用户生成报表。
计算总额和分类统计。

3 设计管理系统的 DDD 架构

    1. 界面层(Interface Layer)

负责 HTTP 请求的处理,调用应用层接口。

示例代码:

		type ExpenseHandler struct {
		    appService *application.ExpenseAppService
		}

		func NewExpenseHandler(appService *application.ExpenseAppService) *ExpenseHandler {
		    return &ExpenseHandler{appService: appService}
		}

		func (h *ExpenseHandler) CreateExpense(c *gin.Context) {
		    var req application.CreateExpenseRequest
		    if err := c.ShouldBindJSON(&req); err != nil {
		        c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
		        return
		    }

		    err := h.appService.CreateExpense(req)
		    if err != nil {
		        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		        return
		    }

		    c.JSON(http.StatusOK, gin.H{"message": "Expense created successfully"})
		}
    1. 应用层(Application Layer)

用例编排,协调领域层完成业务需求,依赖领域服务和基础设施服务。

示例代码:

	type CreateExpenseRequest struct {
	    UserID   string  `json:"user_id"`
	    Amount   float64 `json:"amount"`
	    Category string  `json:"category"`
	    Remark   string  `json:"remark"`
	}

	type ExpenseAppService struct {
	    expenseRepo domain.ExpenseRepository
	}

	func NewExpenseAppService(repo domain.ExpenseRepository) *ExpenseAppService {
	    return &ExpenseAppService{expenseRepo: repo}
	}

	func (s *ExpenseAppService) CreateExpense(req CreateExpenseRequest) error {
	    expense := domain.NewExpense(req.UserID, req.Amount, req.Category, req.Remark)
	    return s.expenseRepo.Save(expense)
	}
    1. 领域层(Domain Layer)

核心业务逻辑,包含实体、值对象、领域服务等。

实体(Expense):

	type Expense struct {
	    ID        string
	    UserID    string
	    Amount    float64
	    Category  string
	    Remark    string
	    CreatedAt time.Time
	}

	func NewExpense(userID string, amount float64, category, remark string) *Expense {
	    return &Expense{
	        ID:        generateID(), // 自定义 ID 生成逻辑
	        UserID:    userID,
	        Amount:    amount,
	        Category:  category,
	        Remark:    remark,
	        CreatedAt: time.Now(),
	    }
	}

值对象(Category):

	package domain

	type Category string

	const (
	    Food     Category = "Food"
	    Travel   Category = "Travel"
	    Shopping Category = "Shopping"
	    Other    Category = "Other"
	)

领域服务(ExpenseReportService):

	package domain

	type ExpenseReportService struct {
	    repo ExpenseRepository
	}

	func NewExpenseReportService(repo ExpenseRepository) *ExpenseReportService {
	    return &ExpenseReportService{repo: repo}
	}

	func (s *ExpenseReportService) GenerateReport(userID string) (map[Category]float64, error) {
	    expenses, err := s.repo.FindByUserID(userID)
	    if err != nil {
	        return nil, err
	    }

	    report := make(map[Category]float64)
	    for _, expense := range expenses {
	        report[Category(expense.Category)] += expense.Amount
	    }

	    return report, nil
	}
    1. 基础设施层(Infrastructure Layer)

与外部资源交互,比如数据库。

示例代码:

		package infrastructure
		type InMemoryExpenseRepository struct {
		    data map[string][]*domain.Expense
		}

		func NewInMemoryExpenseRepository() *InMemoryExpenseRepository {
		    return &InMemoryExpenseRepository{data: make(map[string][]*domain.Expense)}
		}

		func (r *InMemoryExpenseRepository) Save(expense *domain.Expense) error {
		    r.data[expense.UserID] = append(r.data[expense.UserID], expense)
		    return nil
		}

		func (r *InMemoryExpenseRepository) FindByUserID(userID string) ([]*domain.Expense, error) {
		    if expenses, ok := r.data[userID]; ok {
		        return expenses, nil
		    }
		    return nil, errors.New("no expenses found for user")
		}
    1. 小结

实现步骤总结

分析领域模型:

确定实体(Expense)、值对象(Category)。
定义领域服务(如报表生成服务)。

分层构建系统:

界面层:负责 HTTP 请求。
应用层:编排用例逻辑,调用领域服务。
领域层:实现核心业务逻辑,独立于技术细节。
基础设施层:实现数据存储、网络交互等。

依赖注入:

在应用启动时,初始化领域服务和存储依赖,并注入到各层。

  • 优势

清晰职责:每层只专注于自己擅长的事情,易于维护。
业务驱动:领域模型清晰体现业务逻辑,便于业务变化时修改。
测试友好:领域逻辑易于单独测试,基础设施层可以被模拟。
这套架构确保了 管理系统的灵活性和可扩展性,适合复杂的业务场景。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。