# 用户域实体优化总结 ## 🎯 **优化目标** 将 User 实体从"贫血模型"升级为"充血模型",将业务逻辑从 Service 层迁移到实体层,实现更好的封装和职责分离。 ## ✅ **完成的优化** ### **1. 实体业务方法增强** #### **密码管理方法** ```go // 修改密码(包含完整的业务验证) func (u *User) ChangePassword(oldPassword, newPassword, confirmPassword string) error // 验证密码 func (u *User) CheckPassword(password string) bool // 设置密码(用于注册或重置) func (u *User) SetPassword(password string) error ``` #### **手机号管理方法** ```go // 验证手机号格式 func (u *User) IsValidPhone() bool // 设置手机号(包含格式验证) func (u *User) SetPhone(phone string) error // 获取脱敏手机号 func (u *User) GetMaskedPhone() string ``` #### **用户状态检查方法** ```go // 检查用户是否可以登录 func (u *User) CanLogin() bool // 检查用户是否活跃 func (u *User) IsActive() bool // 检查用户是否已删除 func (u *User) IsDeleted() bool ``` ### **2. 业务规则验证** #### **密码强度验证** - 长度要求:8-128 位 - 必须包含数字 - 必须包含字母 - 必须包含特殊字符 #### **手机号格式验证** - 11 位数字 - 以 1 开头 - 第二位为 3-9 #### **业务不变性验证** - 新密码不能与旧密码相同 - 确认密码必须匹配 - 用户状态检查 ### **3. 工厂方法** ```go // 创建新用户的工厂方法 func NewUser(phone, password string) (*User, error) ``` ### **4. 静态工具方法** ```go // 验证手机号格式(静态方法) func IsValidPhoneFormat(phone string) bool // 检查是否为验证错误 func IsValidationError(err error) bool ``` ## 🔄 **Service 层重构** ### **优化前的问题** ```go // 业务逻辑集中在Service中 func (s *UserService) ChangePassword(ctx context.Context, userID string, req *dto.ChangePasswordRequest) error { // 验证新密码确认 if req.NewPassword != req.ConfirmNewPassword { ... } // 验证当前密码 if !s.checkPassword(req.OldPassword, user.Password) { ... } // 哈希新密码 hashedPassword, err := s.hashPassword(req.NewPassword) // 更新密码 user.Password = hashedPassword return s.repo.Update(ctx, user) } ``` ### **优化后的改进** ```go // Service只负责协调,业务逻辑委托给实体 func (s *UserService) ChangePassword(ctx context.Context, userID string, req *dto.ChangePasswordRequest) error { // 1. 获取用户信息 user, err := s.repo.GetByID(ctx, userID) if err != nil { return fmt.Errorf("用户不存在: %w", err) } // 2. 执行业务逻辑(委托给实体) if err := user.ChangePassword(req.OldPassword, req.NewPassword, req.ConfirmNewPassword); err != nil { return err } // 3. 保存用户 return s.repo.Update(ctx, user) } ``` ## 📊 **优化效果对比** | 方面 | 优化前 | 优化后 | | ---------------- | -------------- | -------------- | | **业务逻辑位置** | Service 层 | 实体层 | | **代码复用性** | 低 | 高 | | **测试难度** | 需要 Mock 仓储 | 可直接测试实体 | | **职责分离** | 不清晰 | 清晰 | | **维护性** | 一般 | 优秀 | ## 🧪 **测试覆盖** ### **单元测试** - ✅ 密码修改功能测试 - ✅ 密码验证功能测试 - ✅ 手机号设置功能测试 - ✅ 手机号脱敏功能测试 - ✅ 手机号格式验证测试 - ✅ 用户创建工厂方法测试 ### **测试结果** ``` === RUN TestUser_ChangePassword --- PASS: TestUser_ChangePassword (0.57s) === RUN TestUser_CheckPassword --- PASS: TestUser_CheckPassword (0.16s) === RUN TestUser_SetPhone --- PASS: TestUser_SetPhone (0.00s) === RUN TestUser_GetMaskedPhone --- PASS: TestUser_GetMaskedPhone (0.00s) === RUN TestIsValidPhoneFormat --- PASS: TestIsValidPhoneFormat (0.00s) === RUN TestNewUser --- PASS: TestNewUser (0.08s) PASS ``` ## 🚀 **新增功能** ### **1. 用户信息更新** ```go func (s *UserService) UpdateUserProfile(ctx context.Context, userID string, req *dto.UpdateProfileRequest) (*entities.User, error) ``` ### **2. 用户停用** ```go func (s *UserService) DeactivateUser(ctx context.Context, userID string) error ``` ### **3. 软删除支持** ```go func (r *UserRepository) SoftDelete(ctx context.Context, id string) error func (r *UserRepository) Restore(ctx context.Context, id string) error ``` ## 📈 **架构改进** ### **1. 更好的封装** - 业务规则与数据在一起 - 减少外部依赖 - 提高内聚性 ### **2. 更清晰的职责** - 实体:业务逻辑和验证 - Service:协调和事务管理 - Repository:数据访问 ### **3. 更容易测试** - 实体方法可以独立测试 - 不需要复杂的 Mock 设置 - 测试覆盖更全面 ## 🎉 **总结** 这次优化成功实现了: 1. **✅ 充血模型** - 实体包含丰富的业务方法 2. **✅ 职责分离** - Service 专注于协调,实体专注于业务逻辑 3. **✅ 更好的封装** - 业务规则与数据紧密耦合 4. **✅ 更容易测试** - 实体方法可以独立测试 5. **✅ 代码复用** - 业务逻辑可以在不同场景下复用 这是一个成功的"轻量级 DDD"实践,在保持架构简单的同时,显著提升了代码质量和可维护性!