在 DDD 或 Clean Architecture 里,请问数据验证代码该放在哪层?是用异常还是返回值?

2022-06-17 21:38:19 +08:00
 skinny

背景:假设有一个 API 项目用的是 aspnetcore ,然后项目各个功能拆分成独立的组件库了(比如 identity 、user profiles 、sessions 、posts ),都有各自独立的接口,UI 层( API )需要哪个就引用哪个库配置哪个库。

比如有一个创建用户的接口,首先框架会自动基于 Model 属性和数据类型对请求数据做基本的数据验证,比如是不是一个有效的 int 、Guid 、Email 等等。

假如接下来我要验证这个电子邮件是不是符合某些规则,然后是不是唯一的没有被别人注册使用,这个逻辑我该在组件的 Service 里做还是数据存储层 Repository 里做,还是就在 Controller 那验证?

我搜了下外网的回答,各种观点的都有,总结下来就是都觉得自己的是好的,别的都不建议,然后都有一点点道理。

有的说应该确保从 Repository 存进和取出的数据都应该是有效的,否则世界就会变得太复杂,所以在 Repository 里验证;(到底有没有必要再在这里做一次验证?)

有的说应该在 Entity 或 Model 做(里面还分成很多派系);

有的说在 Service 做;

有的在 Specification ;有的在 Command ;有的在 Event ;

有的说在最开始创建或修改的地方做(通常是 Controller 那里);

还有,数据无效(比如有非法字符,或这个电子邮件已经被使用)该使用异常还是返回值?

有的观点是如果大量数据需要验证,使用异常会打断流程,但如果我在那层做完全部验证在把这些问题整合抛出一个异常呢?而且接口返回值也不需要再套几层对象包装。

比如我觉得

Task<User> Repository.AddAsync(User user)

就比

Task<IdentityResult> Repository.AddAsync(User user)

清晰简单,我也不用考虑这个 IdentityResult 怎么来兼容其它类型的操作,外面的那层也可以不用套上这个返回值类型的枷锁。

为什么我会需要考虑这个 IdentityResult 怎么来兼容其它类型的操作,比如我有一个接口,给用户添加一个 Claim ,然后返回完整的信息而不需要再查询一次,接口为这样:

Task<UserClaim> AddClaimAsync(User user, Claim claim)

如果改成返回 IdentityResult 就需要给 IdentityResult 增加属性,但是大部分时候是不需要这个属性的。

你们会怎么做的?

1046 次点击
所在节点    问与答
4 条回复
chihiro2014
2022-06-17 21:46:58 +08:00
在入口 Controller 做验证不行么?毕竟 Dao 层取出来的数据都是规范的。保证 Controller 的出和入的规范就好了
crysislinux
2022-06-17 21:47:17 +08:00
一般来说我倾向于不依赖别的服务能同步验证的,就放在 entity 里,比如 email 格式。其他的就搞个 factory ,在创建 entity 的时候验证,比如保证 email 唯一
leoskey
2022-06-18 14:04:20 +08:00
Abp 推荐的是 Email 校验在 EmailEntity 里完成对自身的校验。
如果 User.Email 是 string ,那么就在 User.SetEmail 里完成。(ps: 添加 SetEmail 方法 或 属性的 set 访问器都可以)。
email 唯一校验已超出 Entity 职责范围,应使用领域服务 UserManager 完成: userManager.SetEmailAsync(user, email)
DreamStar
2023-03-01 11:40:54 +08:00
非空, 非负, 长度啥的在应用服务就搞定.
email 之类的实体数据, 用值对象解决, 构造的时候就判断了, 不可能有非法的.
唯一类验证交给 repo 服务做 exist 判断, 并发创建唯一交给数据库唯一索引就行

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/860381

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX