Trim方法通常应该在数据访问层中还是在域层中?

时间:2010-05-11 11:16:26

标签: formatting domain-driven-design n-tier-architecture business-objects trim

我正在处理一个包含不一致数据的数据库,例如白色前导和尾随空格。

总的来说,我看到许多开发人员通过修剪几乎所有来自数据库的字符串来实施防御性编码,这些字符串可能是某个时候用户输入的。在我的oppinoin中,最好在数据持久化之前进行这样的格式化,这样它只能完成一次,然后数据可以处于一致且可靠的状态。不幸的是,情况并非如此,这导致我使用修剪方法找到下一个最佳解决方案。

如果我将所有数据作为数据访问层的一部分进行修剪,那么我就不必担心自己的域层业务对象中的防御性修整。如果我将修剪责任放在我的业务对象中,例如使用我的C#属性的set访问器,我应该获得相同的净结果,但是修剪将对分配给我的业务对象属性的所有值进行操作,而不仅仅是来自来自不一致的数据库。

我想这可能是一个有点过敏的问题,可以决定我可以问的答案“域层是否应该对数据的防御性/强制性格式负责?”有一个集合访问器是否有意义对于业务对象上的PhoneNumber属性,接受未格式化或格式化的字符串,然后尝试根据需要对其进行格式化,或者是否应将此责任推送到表示层和数据访问层,使域层对其接受的数据类型更加严格?我认为这可能是一个更基本的问题。

更新:以下是我认为应该分享的有关该主题的一些链接。

Information service patterns, Part 3: Data cleansing pattern

LINQ to SQL - Format a string before saving?

How to trim values using Linq to Sql?

3 个答案:

答案 0 :(得分:3)

我建议“清理”应用层中的数据。你想在这里做的原因(是的,像Dev Art建议的那样在堆栈中更高)是因为你的域模型应该尽可能地“模拟”域。如果在某个时间点所有数据都“干净”怎么办?好吧,那么你可能想要删除执行'清理'的辅助方法。更容易将其从应用程序堆栈中较高的位置删除。

使用一种使用反射的优雅扩展方法(不要先告诉我反射很慢until you know how it works)或者挖掘你的域对象图的所有“字符串”属性(例如)。 Here is an example that uses this technique to adjust DateTime values到固定偏移量 - 请注意它将如何“抵消”所有DateTime值甚至深入集合或其他自定义类型。在你的情况下,抵消将是你的修剪。这肯定比在节目中添加.Trim()更容易,并且可以很容易地解耦。

请记住,不良数据是您网域的一个跨领域问题,因此不应直接与其相关(请AOP)。

答案 1 :(得分:2)

必须在保留数据之前清除数据。现在它被持久存在,你有不洁净的数据,可能需要在数据库中清理。考虑按名称寻找客户。如果我存储的是“John”,“Doe”,我可以找到“John”,“Doe”。

在靠近UI的位置清理数据可以让您拥有更简单的代码。防御性代码可以从清理代码更改为断言。 (即断言string = trimmed(string))。要达到这一点,您需要清理数据库以及UI代码。

答案 2 :(得分:0)

  

最好在数据保留之前进行此类格式化

绝对

  

域名后来应该对数据的防御/强制格式负责吗?

使用当前存储的数据,您将找不到引入修剪的正确位置。这是因为存储的一致性被破坏了。

您可以尝试自我修复方法。在显示对话之前,先读取数据并将其修剪到某处。一旦用户保存此对话框,数据库中的数据就会“固定”。

对于新输入,我倾向于认为修剪数据是既不属于域层也不属于数据层的清理操作。在您真正开始使用该数据之前,用户输入应该在靠近UI层的某处“清理”。