You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用DDD实践:聚合根与应用服务的通信方式探讨

关于Android项目中DDD实现用户姓名修改的问题解答

你当前的实现不建议在领域实体(User)中直接注入应用服务(AccountService),这违反了DDD中领域层与应用层的职责边界——领域实体应专注于表达业务规则、维护自身状态,而与外部系统(如后端)的交互属于应用服务的职责范围。

以下是两种更优的实现方式:

方式一:将外部交互职责转移到应用服务

应用服务作为协调者,负责串联领域实体的业务逻辑与外部后端的同步操作,领域实体只处理自身状态变更和业务规则。

// 领域实体User:仅关注业务规则与状态维护
class User(var name: String) {
    fun changeName(newName: String) {
        // 这里可添加姓名格式校验等业务规则,比如长度限制、非法字符检查
        name = newName
        // 触发领域事件,用于后续可能的业务联动
        fireEvent(UserNameChanged(name))
    }
}

// 应用服务:协调领域逻辑与外部交互
class AccountAppService(
    private val accountService: AccountService,
    private val userRepository: UserRepository
) {
    fun updateUserName(userId: String, newName: String) {
        val user = userRepository.findById(userId)
        
        // 先调用后端接口完成同步
        val syncSuccess = accountService.changeName(newName)
        if (syncSuccess) {
            // 同步成功后,修改领域实体状态
            user.changeName(newName)
            userRepository.save(user)
        } else {
            // 处理同步失败逻辑,比如抛出异常、记录告警日志
            throw SyncFailedException("同步用户姓名到后端失败")
        }
    }
}

方式二:基于领域事件的异步同步

如果业务允许本地状态变更与后端同步存在短暂延迟,可通过领域事件解耦两者,提升系统响应速度。

// 领域实体User
class User(var name: String) {
    fun changeName(newName: String) {
        // 业务规则校验
        name = newName
        // 触发领域事件
        fireEvent(UserNameChanged(name))
    }
}

// 领域事件监听器(属于应用层/基础设施层)
class UserNameChangedListener(private val accountService: AccountService) {
    @EventListener
    fun handleUserNameChanged(event: UserNameChanged) {
        // 异步调用后端接口完成同步
        accountService.changeNameAsync(event.newName)
            .exceptionally { e ->
                // 同步失败处理:重试、记录错误日志、触发告警
                log.error("同步用户姓名失败:${event.newName}", e)
                null
            }
    }
}

// 应用服务
class AccountAppService(private val userRepository: UserRepository) {
    fun updateUserName(userId: String, newName: String) {
        val user = userRepository.findById(userId)
        user.changeName(newName)
        userRepository.save(user)
        // 事件发布后由监听器自动处理后端同步
    }
}

核心原则总结

领域实体需保持"纯净",不依赖任何外部服务或基础设施,将外部交互、流程协调的职责交给应用层或基础设施层,这样既符合DDD的分层设计思想,也能让代码更易于测试、维护和扩展。

内容的提问来源于stack exchange,提问作者rayworks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 21:24:26