在本文中你可以看到一套较为完整的仓储层 => 领域层 => 表现层的 Golang 代码实现,但是肯定不会覆盖全部 DDD 概念,各位可以将它看作一种 Golang 中 DDD 的最佳实践来参考。
01背景
因为业务需求,我们当时正在用 Golang 从 0 到 1 构建一个Web 系统,由于是个新系统,所以很多东西要自己摸索,当时摆在面前的实际问题是如何更好的组织数据访问层和核心领域模型的代码。
相比 Java 构建的系统,代码组织方式、分层等最佳实践已经固化在 Sprint Boot、Sofa Boot 等框架中,Golang 缺乏这种标准化的最佳实践。这个时候我们想到领域驱动设计(DDD),看起来可以解决我们的问题。
02整体设计
指导思想(DDD):重点借鉴了 DDD 中的表现层(User Interface)、领域层(Domain)和基础设施层(Infrastructure)解决我们的问题。
03代码实现
领域层
领域层(Domain)是系统的核心,负责表达业务概念,业务状态信息以及业务规则,即包含了该领域(问题域)所有复杂的业务知识抽象和规则定义。该层主要精力要放在领域对象分析上,可以从实体,值对象,聚合(聚合根),领域服务,领域事件,仓储,工厂等方面入手;
本文中放置核心模型定义(实体)和仓储抽象。
什么是实体(Entity)?
一个实体是一个唯一的东西,并且可以在相当长的一段时间内持续地变化。唯一的身份标识和可变性(mutability)特征将实体对象和值对象(Value Object)区分开来。
——《实现领域驱动设计》
package entity
import (
"fmt"
"net/url"
"time"
)
// Source represents the specific configuration code source,
// which should be a specific instance of the source provider.
type Source struct {
// ID is the id of the source.
ID uint
// SourceProvider is the type of the source provider.
SourceProvider SourceProviderType
// Remote is the source URL, including scheme.
Remote *url.URL
// CreatedAt is the timestamp of the created for the source.
CreatedAt time.Time
// CreatedAt is the timestamp of the updated for the source.
UpdatedAt time.Time
}
仓储(Repository)接口定义
package repository
import (
"context"
"github.com/elliotxx/ddd-demo/pkg/domain/entity"
)
// SourceRepository is an interface that defines the repository operations for sources.
// It follows the principles of domain-driven design (DDD).
type SourceRepository interfa