在3层架构中的验证

6
假设有一个员工类,业务需求之一是EmployeeName必须成为唯一的。现在使用3层架构,
第一层:表示层
第二层:域模型+数据服务类(业务逻辑层)
第三层:数据访问类+存储过程(数据访问层)
由于上述要求是业务需求,您认为最好将此规则放在哪里?
选项1: 数据库中的唯一键约束
选项2: 在业务层的数据服务类中检查条件,以便保留业务逻辑封装在该层中,而不管使用哪个数据层?
1个回答

8
在所有三个层面上,但重要的是,验证要求(即实际数据约束)因层而异。这是由于不同的上下文和设计系统边界造成的。
在您的示例中,验证可能如下:
1. 第1层:表示层 - 验证已输入名称,即用户界面中的文本框不为空,并且最多有100个字符。
2. 第2层:业务逻辑层 - 与上述相同,加上至少由一个空格分隔的两个标记,加上名字是真实的名字(检查某些名字数据库)。
3. 第3层:数据层 - 数据库完整性约束,使相应字段不为空并且长度最大为100个字符。
结果是,从数据库的角度来看,您会检查合理数量的约束以保持系统一致性,但不会假设什么是更高级逻辑的问题。实际上,您不会不必要地限制未来的更改。从业务逻辑的角度来看,强制执行完整的约束集。最后,从表示逻辑的角度来看,您不会过度验证:只执行简单的验证以减少对业务逻辑的不必要流量,可能防止异常来自业务逻辑层,并且不会复制任何更复杂的内容。
作为经验法则,在业务逻辑层的门面提供详细的验证始终是最佳实践。这就是(可能不受信任的)表示层和/或第三方(可能只是另一个公司系统)API消费者连接的地方。
此外,针对您在问题中概述的选项的一些特定评论:
选项1:数据库中的唯一键约束
不仅如此。从数据正确性的角度来看,它有效,但仅依靠数据库约束,您将失去语义,并且很难提供人类可理解的错误消息。此外,每个错误的输入都将传递到数据库,为DoS攻击打开潜在漏洞,可能会危及整个技术堆栈。
选项2:在业务层中的数据服务类中检查条件,以保持业务逻辑封装在该层中,而不管使用的数据层如何?
是的,请参见上文。但是,为了避免至少在表示层进行基本的、简单易于评估的验证,不要妥协安全性、性能和用户体验。

@Downvoter,感谢您的投票。请问有什么解释吗? - Ondrej Tucny
非常感谢您抽出时间撰写这篇详细的回答,对我非常有用。但是,在每次插入/更新之前增加额外的数据库流量以检查名称重复是否可以接受?我还有几个问题,您认为应该在数据库中放置哪些常见约束条件?此外,关于表示层验证和业务层验证之间的关系,您认为所有基于逻辑的验证(例如生日不应超过某个日期)都应放置在业务层? - Sisyphus
感谢那些给我点踩的人,现在我的账户已经不能再发布新问题了。我真的不明白我的问题有什么问题会导致被踩两次! - Sisyphus
  1. 不用担心任何额外的数据库流量,只要在表现层进行简单的验证,有效地防止无效数据进入业务逻辑层。
  2. 数据库中的约束:考虑“技术”约束以保持数据一致性。
  3. 所有验证都应该在业务层中完成,并且(其中一些或全部)在表现层中重复。
  4. 我不理解生日的例子。
- Ondrej Tucny
  1. 你能给我一些常见的例子来更清楚地说明吗?
  2. 例如,出生日期不能是2015年,因为我们还活在2014年,或者更严格的例子是员工必须至少18岁,那么出生日期必须早于今天减去18年等。
- Sisyphus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接