database - DDD、数据库和数据列表
问题描述
我刚开始我的第一个“真正的”软件项目,我想从正确的开始。DDD 的概念似乎是一种非常干净的方法,可以将各个软件部分分开,但是在现实中我很难实现这一点。
我的软件是测量跟踪器,本质上存储测量数据列表,由时间戳和数据值组成。
我的领域模型
class MeasurementDM{
string Name{get;set;}
List<MeasurementPointDM> MeasurementPoints{get;set;}
}
class MeasurementPointDM{
DateTime Time{get;set;}
double Value{get;set;}
}
我的持久性模型:
class MeasurementPM{
string Id{get;set;} //Primary key
string Name{get;set;} //Data from DomainModel to store
}
class MeasurementPointPM{
string Id{get;set;} //Primary Key
string MeasurementId{get;set;} //Key of Parent measurement
}
我现在有以下问题:
1)因为我想保持我的领域模型纯粹,我不想或不需要这些类中的数据库键。从数据库构建我的域模型时这没问题,但我不明白如何存储它们,因为域模型不再知道数据库 ID。无论如何我应该将它包含在域模型中吗?当我从数据库中检索域对象时,是否应该创建一个将域对象映射到数据库 ID 的字典?
2)测量点本质上与测量本身具有相同的Id问题。此外,我不确定存储测量点本身的正确方法是什么。上面,每个 MeasurementPointPM 都知道它属于哪个 MeasurementPM。当我查询时,我只是根据他们的测量键选择测量点。这是存储此类数据的有效方法吗?随着越来越多的测量值被添加,这似乎会爆炸。将我的 MeasurementPoints 列表序列化为字符串并将整个列表存储为 nvarchar 会更好吗?这将使添加和删除数据点更加困难,因为 Id 总是需要反序列化、重新序列化整个列表
我很难找到一个处理这些问题的 DDD 的好例子,希望有人可以帮助我。
解决方案
我的软件是测量跟踪器,本质上存储测量数据列表,由时间戳和数据值组成。
您可能需要仔细考虑您是在描述服务还是数据库。如果您的主要用例是存储来自其他地方的信息,那么将域模型引入混合可能不会让您的生活变得更好。
当新信息与旧信息交互时,域模型测试变得有趣。因此,如果您所拥有的只是数据结构,那么很难找到一个好的模型(因为缺少关键元素——模型实体如何随时间变化)。
那就是说……
我不明白如何存储它们,因为域模型不再知道数据库 ID。
这不是你的错。文学很烂。
最常见的答案是 _people 允许他们的模型受到 O/RM 问题的污染。例如,如果您查看 Citerus 示例应用程序中的Cargo实体,您会发现这些行隐藏在底部:
Cargo() {
// Needed by Hibernate
}
// Auto-generated surrogate key
private Long id;
这是一个间接结果,即“存储库”模式提供了一种对象的内存集合的错觉,这些对象保持自己的状态,而幕后的现实是您正在内存和持久存储之间复制值。
也就是说,如果您想要一个干净的域模型,那么您将需要一个单独的内存表示来存储您的数据,以及在两者之间来回转换的函数。
换句话说,您遇到的是对单一职责原则的违反——如果您使用相同的类型来建模您用来管理持久性的域,那么结果将是这两个问题的混合.
所以基本上你会说域模型的一些最小污染,例如 ID,是标准做法。
较弱;我会说这是一种常见的做法。从根本上说,很多人,特别是在项目的早期阶段,不重视在他们的领域模型和他们的持久性管道之间建立边界。
让每个域模型都从基类继承或实现强制创建唯一 ID 的接口是否有意义?
它可能。网络上有很多示例,其中域实体扩展了一些通用Entity
或Aggregate
模式。
真正有趣的问题是
- 这样做的直接成本和收益是什么?
- 这样做的递延成本和收益是什么?
特别是,这会让事情变得更容易还是更难改变?
推荐阅读
- android - 在 Android Studio 中选择要被自动缩进忽略的代码
- python - 特征提取 TensorFlow Estimator
- java - 将多部分文件上传到 AWS,而不在本地保存
- c# - Unity如何将射击和子弹更新到自定义服务器?
- laravel - Laravel 5.5 通过 eloquent 模型获取数据的问题
- c# - Log4net 处理多租户的最佳实践(1 个输出文件)
- svg - 使用 SkiaSharp.Svg 从 svg 转换为 png 时添加了一些噪音
- javascript - 如何检测用户是否从当前位置滚动了 100px
- python - Pytest:在 python 中模拟/猴子修补内置 input() 和 print() 函数
- perl - 寻找棕枝主日