Domain driven design 聚合不变量是否可以包含基于其他地方信息的规则?
在DDD中,聚合不变量是否可以包含基于另一个聚合中的信息的规则?现在我不这么认为,但是这给我带来了一个问题,我不知道如何解决它 我有一个名为资产(设备)的实体,我将其建模为聚合的根。它有一个标签(属性)列表,描述制造商、型号等。它存储称为AssetType的第二个聚合的标识,AssetType有一个标签类型列表,其中一些可以标记为必需的 现在,我觉得Asset的一个不变条件应该引用关联的AssetType,以强制强制强制标记列表中的非空值。但我的内心充满了如何加强一致性的想法 这是否意味着总量真的应该包括所有四个实体?如果根目录是AssetType,并且它下面有一个资产列表,那么它可以解决我的问题,但是这不太适合具有其他集合维护不同类型资产列表的核心用例。资产必须是根本,否则我会有问题 资产类型也不能很好地进入资产聚合。这似乎同样荒谬 我的直觉仍然认为Asset和AssetType是两个独立的聚合,但是我如何解决一致性问题呢?还是我的不变量搞错了 聚合不变量是否可以包含基于其他地方信息的规则 聚合始终可以使用其自身状态中的信息以及接收到的参数 有人过去常常通过单例、服务定位器等访问应用程序服务,但在我看来,这是一种紧密耦合的应用程序的味道。他们忘记了方法的参数是有效的依赖关系注入器!:-) 在DDD中,聚合不变量是否可以包含基于另一个聚合中的信息的规则 否。Domain driven design 聚合不变量是否可以包含基于其他地方信息的规则?,domain-driven-design,aggregate,modeling,invariants,Domain Driven Design,Aggregate,Modeling,Invariants,在DDD中,聚合不变量是否可以包含基于另一个聚合中的信息的规则?现在我不这么认为,但是这给我带来了一个问题,我不知道如何解决它 我有一个名为资产(设备)的实体,我将其建模为聚合的根。它有一个标签(属性)列表,描述制造商、型号等。它存储称为AssetType的第二个聚合的标识,AssetType有一个标签类型列表,其中一些可以标记为必需的 现在,我觉得Asset的一个不变条件应该引用关联的AssetType,以强制强制强制标记列表中的非空值。但我的内心充满了如何加强一致性的想法 这是否意味着总量真
当然,除非第二个聚合是通过命令的参数提供的 警告强> 我有一个名为资产(设备)的实体。
... (和a)第二个聚合称为AssetType 上一次我不得不处理类似的结构,那是一种痛苦 很可能您选择了错误的抽象 我的不变量搞错了吗 也许。。。您是否向领域专家询问过?他是否谈论“标记类型” 持有对
X-type
实例引用的X-type
类型的实体几乎总是一种过度抽象的味道,为了重用,这使得模型变得僵化且不灵活,无法适应业务发展
回答
如果(且仅当)领域专家实际用这些术语描述了模型,则可能的方法如下:
AssetType
类,该工厂方法将IEnumerable
转换为TagSet
,MissingMandatoryTagException
或UnexpectedTageException
,如果某些标记丢失或意外李>
Asset
类中,命令RegisterTags
将接受AssetType
和IEnumerable
,抛出MissingMandatoryTagException
和ErrorAssetTypeException
(注意异常对于确保不变量有多重要)类似于此,但有更多的文档记录:
公共类资产类型
{
专用只读词典_tagTypes=new Dictionary();
公共资产类型(资产类型名称)
{
//在这里验证。。。
名称=名称;
}
///
///允许将标记类型指定给此类型的资产。
///
///
public void EnableTagType(标记类型)
{
//在这里验证。。。
_tagTypes[type]=false;
}
///
///要求为此类型的任何资产定义标记类型。
///
///
public void RequireTagType(标记类型)
{
//在这里验证。。。
_tagTypes[type]=false;
}
公共资产类型名称{get;private set;}
///
///生成标记集。
///
///标签。
///当前资产类型的一组标记。
///为null或空。
///至少需要一个标签
///中缺少按当前资产类型列出的。
///至少有一个
///不允许用于当前资产类型。
///
公共标记集BuildTagSet(IEnumerable标记)
{
if(null==tags | | tags.Count()==0)
抛出新的ArgumentNullException(“标记”);
标记集标记集=新标记集();
foreach(标记中的标记)
{
if(!\u tagTypes.ContainsKey(tag.Key))
{
string message=string.Format(“不能在资产类型{1}中使用标记{0}。”,tag.Key,Name);
抛出新的意外异常(“tags”、tag.Key、message);
}
tagSet.Add(tag);
}
foreach(tagTypes中的TagType标记类型,其中(kvp=>kvp.Value==true)。选择(kvp=>kvp.Key))
{
如果(!tagSet.Any(t=>t.Key.Equals(tagType)))
{
string message=string.Format(“必须向类型为{1}的资产提供标记{0}。”,tagType,Name);
抛出新的MissingMandatoryTagException(“标记”、标记类型、消息);
}
}
返回标记集;
}
}
公共类资产
{
公共资产(资产名称、资产类型名称类型)
{
//在这里验证。。。
名称=名称;
类型=类型;
}
公共标记集标记{get;private set;}
公共资产名称{get;private set;}
公共资产类型名称类型{get;private set;}
///
///注册标签。
///
///标记的类型。
///Th