Domain driven design 规范模式对象应位于哪一层;新';ed up";?
所以,我在这里查看了一些关于规范模式的帖子,但还没有找到这个问题的答案 我的问题是,在n层体系结构中,me规范究竟应该在哪里“更新”Domain driven design 规范模式对象应位于哪一层;新';ed up";?,domain-driven-design,specification-pattern,n-layer,application-layer,Domain Driven Design,Specification Pattern,N Layer,Application Layer,所以,我在这里查看了一些关于规范模式的帖子,但还没有找到这个问题的答案 我的问题是,在n层体系结构中,me规范究竟应该在哪里“更新” 我可以把它们放在我的服务层(也称为应用层,它有时被称为…基本上,一个.aspx代码背后的东西会与之对话),但我觉得这样做,我让业务规则泄漏出了域。如果以其他方式访问域对象(除服务层外),则域对象无法强制执行其自己的业务规则 我可以通过构造函数注入将规范注入到我的模型类中。但同样,这感觉“不对”。我觉得唯一应该注入模型类的是“服务”,比如缓存、日志记录、脏标志跟踪等
哪里是创建和使用规范的最佳位置?规范是对业务规则的实现检查。它必须存在于域层中 很难给出具体的操作方法,因为每个代码库都是不同的,但我认为任何业务逻辑都需要在域层,而不是其他任何地方。此业务逻辑需要完全可测试,并与UI、数据库、外部服务和其他非域依赖项松散耦合。所以我肯定会排除上面的1、2和3 4是一个选项,至少该规范将存在于您的域层中。然而,规范的更新实际上又取决于实现。我们通常使用依赖注入,因此几乎所有对象的更新都是通过IOC容器和相应的引导代码执行的(即,我们通常流畅地连接应用程序)。但是,我们永远不会将业务逻辑直接链接到UI模型类等。我们通常在UI和域等事物之间有轮廓/边界。我们通常定义域服务契约,然后可以由外部层(如UI等)使用
最后,我的答案是假设您正在使用的系统至少在某种程度上是复杂的。如果它是一个非常简单的系统,那么领域驱动设计作为一个概念可能太过分了。然而,在我看来,不管代码库是什么,诸如可测试性、可读性、SoC等概念都应该得到尊重。简短回答: 您主要在服务层中使用规范,因此存在 长答案: 首先,这里有两个问题: 你的规格应该放在哪里,新的应该放在哪里 就像您的存储库接口一样,您的规范应该位于域层,因为它们毕竟是特定于域的。关于存储库接口,有一篇文章对此进行了讨论 但是,它们应该在哪里更新呢?嗯,我在我的存储库中使用,并且在我的存储库中通常有三种方法:
public interface ILinqSpecsRepository<T>
{
IEnumerable<T> FindAll(Specification<T> specification);
IEnumerable<T> FindAll<TRelated>(Specification<T> specification, Expression<Func<T, TRelated>> fetchExpression);
T FindOne(Specification<T> specification);
}
以下是规格:
public class UserByEmail : Specification<User>
{
private readonly string email;
public UserByEmail(string email)
{
this.email = email;
}
#region Overrides of Specification<User>
public override Expression<Func<User, bool>> IsSatisfiedBy()
{
return x => x.Email == email;
}
#endregion
}
public类UserByEmail:规范
{
私人只读字符串电子邮件;
公共用户通过电子邮件(字符串电子邮件)
{
this.email=电子邮件;
}
#规范的区域覆盖
公共重写表达式IsSatifiedBy()
{
返回x=>x.Email==Email;
}
#端区
}
因此,为了回答您的问题,规范在服务层中是新的(在我的书中)
我觉得这是唯一应该注入模型类的东西
是“服务”
在我看来,您不应该向域实体注入任何内容
此外,相关规范还需要一个存储库
以确定是否“满意”
这是一个好主意。我会在那里检查你的代码。规范绝对不需要存储库。不太确定向规范中注入存储库是否是代码气味。检查此StackOverflow讨论:。规范和域服务之间的相似性可能非常相似,特别是当您试图实施/证明的规则恰好依赖于首先通过存储库获取信息时。您可以通过FindOne(spec)或FindAll(spec)将规范传递给存储库。如果将存储库注入规范,则有创建循环引用的危险,这可能会导致问题。仅供参考,我会在需要时将规范注入服务。
public class UserByEmail : Specification<User>
{
private readonly string email;
public UserByEmail(string email)
{
this.email = email;
}
#region Overrides of Specification<User>
public override Expression<Func<User, bool>> IsSatisfiedBy()
{
return x => x.Email == email;
}
#endregion
}