DDD解决方案结构
DDD solution structure
我正在尝试为新的 DDD 项目创建一个很好的解决方案结构。我创建了一个 "Core" 项目,我在其中添加了实体、ValueObjects 和存储库接口,然后我添加了一个 "Infrastructure" 项目,其中包含之前 IRepository 的实现。
现在,由于我的数据库将是 MongoDb,我需要在实体的某些字段中添加“[BsonDateTimeOptions]”等属性,这将需要添加对 MongoDb核心工程中的驱动包。
由于核心项目不应包含对 MongoDb 的任何引用,因此应仅包含业务逻辑,并且应可在任何其他项目(移动 - Xamarin)中重复使用,在这种情况下最佳做法应该是什么?
我能想到的是:
- 实体将不包含对 MongoDb
的任何引用
- 在基础设施项目中为每个实体创建一个模型,即相关实体的副本,但具有 MongoDb 属性。
- 创建一个层(在存储库中?)能够使用模型在数据库中查询,然后在实体中转换它并返回实体,将模型对象隐藏在存储库中。
这种方法有一个问题,我将拥有实体模型的副本,它只有 MongoDb 属性,当向实体添加一些字段时,我将不得不修改模型太。这是正确的做法吗?
一切从this解决方案结构开始。
是的,您描述的方法是正确的,但是您在 repo 中称为层的东西只是基础设施层中的一个适配器。 Adapter使用mongodb技术实现repo接口,并使用一个mapper在两种模型之间进行转换。映射器也属于基础结构层。
注意:我不使用 C#,但这在 PHP 中有效,也许对您有帮助
我这样做的方法是将聚合根、嵌套实体和值对象创建为普通对象(数据 + 行为,不依赖于 infrastructure/technology)。然后,当 persisting/rehydrating 时,我使用反射 store/load 来自存储库的聚合。存储库将任何已知的域对象映射到基础结构对象。例如,基本类型(string、bool、int、float、null)在没有任何转换的情况下存储。 Date is transformed to ISODate, the Guid is transformed to ObjectId等等。
这是可能的,因为反射并且很容易,因为 MongoDB 将对象存储为 JSON 并且几乎没有(或 none)阻抗不匹配。
不要在您的域中使用属性 类,而是在基础结构层中编写配置代码。
这似乎总是 MongoDB.NET 的一个选项,例如
BsonClassMap.RegisterClassMap<MyClass>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.DateOfBirth).SetSerializer(new DateTimeSerializer(dateOnly: true));
}
而不是
[BsonDateTimeOptions(DateOnly = true)]
public DateTime DateOfBirth { get; set; }
我正在尝试为新的 DDD 项目创建一个很好的解决方案结构。我创建了一个 "Core" 项目,我在其中添加了实体、ValueObjects 和存储库接口,然后我添加了一个 "Infrastructure" 项目,其中包含之前 IRepository 的实现。
现在,由于我的数据库将是 MongoDb,我需要在实体的某些字段中添加“[BsonDateTimeOptions]”等属性,这将需要添加对 MongoDb核心工程中的驱动包。
由于核心项目不应包含对 MongoDb 的任何引用,因此应仅包含业务逻辑,并且应可在任何其他项目(移动 - Xamarin)中重复使用,在这种情况下最佳做法应该是什么?
我能想到的是:
- 实体将不包含对 MongoDb 的任何引用
- 在基础设施项目中为每个实体创建一个模型,即相关实体的副本,但具有 MongoDb 属性。
- 创建一个层(在存储库中?)能够使用模型在数据库中查询,然后在实体中转换它并返回实体,将模型对象隐藏在存储库中。
这种方法有一个问题,我将拥有实体模型的副本,它只有 MongoDb 属性,当向实体添加一些字段时,我将不得不修改模型太。这是正确的做法吗?
一切从this解决方案结构开始。
是的,您描述的方法是正确的,但是您在 repo 中称为层的东西只是基础设施层中的一个适配器。 Adapter使用mongodb技术实现repo接口,并使用一个mapper在两种模型之间进行转换。映射器也属于基础结构层。
注意:我不使用 C#,但这在 PHP 中有效,也许对您有帮助
我这样做的方法是将聚合根、嵌套实体和值对象创建为普通对象(数据 + 行为,不依赖于 infrastructure/technology)。然后,当 persisting/rehydrating 时,我使用反射 store/load 来自存储库的聚合。存储库将任何已知的域对象映射到基础结构对象。例如,基本类型(string、bool、int、float、null)在没有任何转换的情况下存储。 Date is transformed to ISODate, the Guid is transformed to ObjectId等等。
这是可能的,因为反射并且很容易,因为 MongoDB 将对象存储为 JSON 并且几乎没有(或 none)阻抗不匹配。
不要在您的域中使用属性 类,而是在基础结构层中编写配置代码。
这似乎总是 MongoDB.NET 的一个选项,例如
BsonClassMap.RegisterClassMap<MyClass>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.DateOfBirth).SetSerializer(new DateTimeSerializer(dateOnly: true));
}
而不是
[BsonDateTimeOptions(DateOnly = true)]
public DateTime DateOfBirth { get; set; }