tianyuan-api-server/Domain域详解.md
2025-07-13 20:37:12 +08:00

399 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Domain 域概念详解
## 🤔 什么是 Domain
**Domain** 就像现实世界中的**部门**或**业务范围**。
### 📚 现实世界的类比
想象一个大公司:
```
阿里巴巴集团
├── 电商域 (淘宝、天猫)
├── 支付域 (支付宝)
├── 云计算域 (阿里云)
├── 物流域 (菜鸟)
└── 金融域 (蚂蚁金服)
```
每个域都有:
- **专门的团队** - 不同的开发团队
- **独立的业务** - 各自负责不同的业务功能
- **清晰的边界** - 知道自己管什么,不管什么
- **独立运作** - 可以独立决策和发展
## 🏗️ 在软件架构中的应用
### 传统方式 vs 域驱动方式
#### ❌ 传统方式(技术驱动)
```
项目结构:
├── controllers/ # 所有控制器
├── services/ # 所有服务
├── models/ # 所有数据模型
└── utils/ # 工具类
问题:
- 用户相关、产品相关、支付相关的代码混在一起
- 不同业务逻辑耦合
- 团队协作困难
- 修改一个功能可能影响其他功能
```
#### ✅ 域驱动方式(业务驱动)
```
项目结构:
├── user-domain/ # 用户域
│ ├── user/ # 用户管理
│ ├── auth/ # 认证授权
│ └── profile/ # 用户资料
├── product-domain/ # 产品域
│ ├── catalog/ # 产品目录
│ ├── inventory/ # 库存管理
│ └── pricing/ # 价格管理
├── payment-domain/ # 支付域
│ ├── wallet/ # 钱包
│ ├── order/ # 订单
│ └── billing/ # 计费
└── notification-domain/ # 通知域
├── email/ # 邮件通知
├── sms/ # 短信通知
└── push/ # 推送通知
优势:
- 按业务功能组织代码
- 团队可以独立开发不同的域
- 修改用户功能不会影响支付功能
- 新人容易理解业务边界
```
## 🎯 你的项目中的 Domain 重构
### 当前问题
你的项目中有这些编码式命名:
```
IVYZ - 不知道是什么业务
FLXG - 不知道是什么业务
QYGL - 不知道是什么业务
YYSY - 不知道是什么业务
JRZQ - 不知道是什么业务
```
### 重构后的 Domain 设计
```
用户域 (User Domain)
├── 用户注册登录
├── 用户信息管理
├── 企业认证
└── 权限管理
金融域 (Financial Domain)
├── 钱包管理
├── 支付处理
├── 账单生成
└── 财务报表
数据服务域 (Data Service Domain)
├── 风险评估服务 (原 FLXG)
├── 征信查询服务 (原 JRZQ)
├── 企业信息服务 (原 QYGL)
├── 数据查询服务 (原 IVYZ)
└── 应用系统服务 (原 YYSY)
产品域 (Product Domain)
├── 产品目录管理
├── 产品订阅
├── 访问控制
└── 白名单管理
平台域 (Platform Domain)
├── 管理后台
├── 系统监控
├── 日志管理
└── 配置管理
```
## 💻 代码层面的 Domain 实现
### 1. Domain 层的职责
```go
// domain/user/entity/user.go
package entity
import (
"errors"
"time"
)
// User 用户实体
type User struct {
ID int64 `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Phone string `json:"phone"`
Status UserStatus `json:"status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type UserStatus int
const (
UserStatusActive UserStatus = 1
UserStatusInactive UserStatus = 2
UserStatusBanned UserStatus = 3
)
// 业务规则用户名必须是3-20个字符
func (u *User) ValidateUsername() error {
if len(u.Username) < 3 || len(u.Username) > 20 {
return errors.New("用户名必须是3-20个字符")
}
return nil
}
// 业务规则:检查用户是否可以登录
func (u *User) CanLogin() bool {
return u.Status == UserStatusActive
}
// 业务规则:激活用户
func (u *User) Activate() error {
if u.Status == UserStatusBanned {
return errors.New("被封禁的用户不能激活")
}
u.Status = UserStatusActive
u.UpdatedAt = time.Now()
return nil
}
```
### 2. Domain Service (领域服务)
```go
// domain/user/service/user_service.go
package service
import (
"context"
"errors"
"your-project/domain/user/entity"
"your-project/domain/user/repository"
)
// UserDomainService 用户领域服务
type UserDomainService struct {
userRepo repository.UserRepository
}
func NewUserDomainService(userRepo repository.UserRepository) *UserDomainService {
return &UserDomainService{
userRepo: userRepo,
}
}
// 业务规则:检查用户名是否唯一
func (s *UserDomainService) IsUsernameUnique(ctx context.Context, username string) (bool, error) {
existingUser, err := s.userRepo.FindByUsername(ctx, username)
if err != nil {
return false, err
}
return existingUser == nil, nil
}
// 业务规则:用户注册
func (s *UserDomainService) RegisterUser(ctx context.Context, username, email, phone string) (*entity.User, error) {
// 1. 检查用户名唯一性
unique, err := s.IsUsernameUnique(ctx, username)
if err != nil {
return nil, err
}
if !unique {
return nil, errors.New("用户名已存在")
}
// 2. 创建用户实体
user := &entity.User{
Username: username,
Email: email,
Phone: phone,
Status: entity.UserStatusActive,
}
// 3. 验证业务规则
if err := user.ValidateUsername(); err != nil {
return nil, err
}
// 4. 保存用户
return s.userRepo.Save(ctx, user)
}
```
### 3. Repository 接口 (仓储模式)
```go
// domain/user/repository/user_repository.go
package repository
import (
"context"
"your-project/domain/user/entity"
)
// UserRepository 用户仓储接口
type UserRepository interface {
Save(ctx context.Context, user *entity.User) (*entity.User, error)
FindByID(ctx context.Context, id int64) (*entity.User, error)
FindByUsername(ctx context.Context, username string) (*entity.User, error)
FindByEmail(ctx context.Context, email string) (*entity.User, error)
Update(ctx context.Context, user *entity.User) error
Delete(ctx context.Context, id int64) error
List(ctx context.Context, offset, limit int) ([]*entity.User, error)
}
```
### 4. 应用层 (Application Layer)
```go
// application/user/service/user_app_service.go
package service
import (
"context"
userDomain "your-project/domain/user/service"
"your-project/application/user/dto"
)
// UserAppService 用户应用服务
type UserAppService struct {
userDomainService *userDomain.UserDomainService
}
func NewUserAppService(userDomainService *userDomain.UserDomainService) *UserAppService {
return &UserAppService{
userDomainService: userDomainService,
}
}
// 用户注册用例
func (s *UserAppService) RegisterUser(ctx context.Context, req *dto.RegisterUserRequest) (*dto.UserResponse, error) {
// 1. 调用领域服务
user, err := s.userDomainService.RegisterUser(ctx, req.Username, req.Email, req.Phone)
if err != nil {
return nil, err
}
// 2. 转换为 DTO
return &dto.UserResponse{
ID: user.ID,
Username: user.Username,
Email: user.Email,
Phone: user.Phone,
Status: string(user.Status),
}, nil
}
```
## 🔄 域与域之间的交互
### 事件驱动交互
```go
// 用户注册成功后,通知其他域
type UserRegisteredEvent struct {
UserID int64 `json:"user_id"`
Username string `json:"username"`
Email string `json:"email"`
}
// 金融域监听用户注册事件,自动创建钱包
func (h *WalletEventHandler) HandleUserRegistered(event UserRegisteredEvent) error {
// 为新用户创建钱包
wallet := &entity.Wallet{
UserID: event.UserID,
Balance: 0.0,
Currency: "CNY",
}
return h.walletRepo.Save(context.Background(), wallet)
}
```
## 📊 Domain 的好处
### 1. **团队协作**
```
用户域团队:专注用户相关功能
├── 张三:负责用户注册登录
├── 李四:负责用户资料管理
└── 王五:负责企业认证
支付域团队:专注支付相关功能
├── 赵六:负责钱包功能
├── 孙七:负责支付流程
└── 周八:负责账单生成
```
### 2. **独立部署**
```bash
# 可以独立部署不同的域
kubectl apply -f user-domain-deployment.yaml
kubectl apply -f payment-domain-deployment.yaml
kubectl apply -f product-domain-deployment.yaml
```
### 3. **技术选择自由**
```
用户域:使用 PostgreSQL (复杂查询)
支付域:使用 MySQL (事务性强)
数据域:使用 ClickHouse (分析查询)
```
### 4. **测试隔离**
```go
// 只测试用户域,不需要启动其他域
func TestUserDomain(t *testing.T) {
// 只需要用户域的依赖
userRepo := mock.NewUserRepository()
userService := service.NewUserDomainService(userRepo)
// 测试用户注册逻辑
user, err := userService.RegisterUser(ctx, "testuser", "test@example.com", "13800138000")
assert.NoError(t, err)
assert.Equal(t, "testuser", user.Username)
}
```
## 🎯 总结
**Domain就是按业务功能划分的代码组织方式**
1. **用户域** - 管理用户相关的所有功能
2. **支付域** - 管理支付相关的所有功能
3. **产品域** - 管理产品相关的所有功能
4. **数据域** - 管理数据查询相关的功能
**核心思想**
- 按业务划分,不按技术划分
- 每个域独立开发、测试、部署
- 域之间通过事件或 API 通信
- 团队可以专注于特定业务领域
这样组织代码后,你的项目会更容易理解、维护和扩展!