DDD中的数据访问层设计
请原谅我糟糕的英语。
好的,我现在正在考虑 DDD 方法,听起来不错,但是……有一个小问题。 DDD 表示领域模型层与数据访问层(以及所有其他层)完全解耦。因此,当 DAL 将保存某些业务对象时,它只能访问该对象的公共属性。现在的问题是:
我们如何保证(一般情况下)对象的一组公共数据 我们稍后需要恢复该对象吗?
示例
我们有以下业务规则:
- 创建时必须为业务对象提供用户和域。
- 用户和域在对象创建后无法更改。
- 业务对象具有电子邮件属性,类似于“user@domain”。
这是一个描述这些规则的纯 POCO:
public class BusinessObject
{
private string _user;
private string _domain;
public BusinessObject(string user, string domain)
{
_user = user;
_domain = domain;
}
public string Email
{
get { return _user + "@" + _domain; }
}
}
因此,在某个时刻,DAL 会将这个对象保存到外部存储(即 SQL 数据库)。显然,DAL 会将“Email”属性保存到 DB 中的关联字段中。一切都会正常进行,直到我们要求 DAL 恢复对象为止。 DAL 如何做到这一点?该对象必须至少有一个“电子邮件”字段的公共设置器。实际上
public string Email
{
set
{
string[] s = value.Split("@");
_user = s[0];
_domain = s[1];
}
}
,该对象将具有“用户”和“域”字段以及 GetEmail() 方法的公共 getters/setters。但停下来。我不希望我的 POCO 有这样的功能!没有相关的业务规则。必须这样做才能保存/恢复对象。
我看到另一个选择。作为 DAL 一部分的 ORM 可能会被要求存储恢复对象所需的所有私有字段。但如果我们想让领域模型与 DAL 分离,这是不可能的。 DAL 不能依赖业务对象的某些私有成员。
我能看到的唯一解决方法是拥有一些系统级工具,它可以为我们创建对象转储,并可以随时从该转储中恢复对象。除了对象的公共属性之外,DAL 还必须将此转储放入存储中。因此,当 DAL 需要从存储中恢复对象时,它将使用转储。当 DAL 执行不需要实例化对象的操作(即大多数 link2sql 查询)时,可以使用保存到存储的公共属性。
我做错了吗?我需要阅读更多内容吗?关于某些模式,ORM 可能吗?
Excuse me for my poor English.
Ok, I'm thinking about DDD approach now and it sounds great but... There is one little question about it. DDD says that the domain model layer is totally decoupled from the data access layer (and all other layers). So when the DAL will save some business object it will have access to public properties of this object only. Now the question:
How can we guarantee (in general) that a set of public data of an object
is all we need to restore the object later?
Example
We have the following business rules:
- User and domain must be provided for the business object on create.
- User and domain cannot be changed after object creation.
- The business object have the Email property which looks like "user@domain".
Here is a pure POCO which describes those rules:
public class BusinessObject
{
private string _user;
private string _domain;
public BusinessObject(string user, string domain)
{
_user = user;
_domain = domain;
}
public string Email
{
get { return _user + "@" + _domain; }
}
}
So at some moment the DAL will save this object to the external storage (i.e. SQL database). Obviously, the DAL will save the "Email" property to the associated field in DB. Everything will work just fine until the moment when we'll ask the DAL to restore the object. How the DAL can do this? The object must have a public setter for the "Email" field at least. Something like
public string Email
{
set
{
string[] s = value.Split("@");
_user = s[0];
_domain = s[1];
}
}
Actually, the object will have public getters/setters for both "User" and "Domain" fields and method GetEmail(). But stop. I don't want my POCO to have such functionality! There are no business rules for it. This must be done for the ability to save/restore the object only.
I see another option. The ORM which is a part of the DAL could be asked to store all of the private fields needed to restore the object. But this is impossible if we want to keep the domain model separated from the DAL. The DAL cannot rely on certain private members of the business object.
The only workaround I can see is to have some system-level instrument which can create the dump of the object for us and can restore object from this dump anytime. And the DAL must put this dump to the storage in addition to public properties of the object. So when the DAL needs to restore the object from storage it will use the dump for this. And the public properties saved to storage can be used when the DAL is performing operations that don't need the object to be instantiated (i.e. most of link2sql queries).
Am I doing it wrong? Do I need read more? About some patterns, ORM's maybe?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为你把这部分弄错了:
域模型不依赖于 DAL。相反,DAL 依赖于域模型。
ORM 对领域对象(包括私有字段)有深入的了解。这绝对没有错。事实上,这是在 DDD 中实现持久无知的最佳方式。这就是 Domain 类的样子。请注意,
DAL/ORM 唯一需要的是私有无参数构造函数:
而神奇的事情发生在 ORM 中。 Hibernate 可以使用此映射文件从数据库恢复此对象:
持久性无知的域代码的另一个方面是 DDD 存储库:
Repository接口属于Domain,应该尽可能基于通用语言。另一方面,存储库实现属于 DAL(依赖倒置原则)。
I think you got this part wrong:
Domain model does not depend on DAL. Its the other way around, DAL depends on Domain model.
ORM has intimate knowledge of Domain Objects, including private fields. There is absolutely nothing wrong with that. In fact this is the best way to implement persistent-ignorance in DDD. This is how the Domain class can look like. Note that
The only thing DAL/ORM needs is private parameterless consturctor:
And the magic happens in ORM. Hibernate can restore this object from database using this mapping file:
Another aspect of persistence-ignorant domain code is DDD Repository:
Repository interface belongs to Domain and should be based on Ubiquitous Language as much as possible. Repository implementation on the other hand belongs to DAL (Dependency Inversion Principle).
一种简单的解决方案是让 DAL 调用 new BusinessObject(email)
One simple solution is to just have your DAL call new BusinessObject(email)