规范模式对象应该在哪一层“更新”?

2023-12-21

因此,我在这里查看了一些有关规范模式的帖子,但尚未找到此问题的答案。

我的问题是,在 n 层架构中,我的规范到底应该在哪里“更新”?

  1. 我可以将它们放在我的服务层(又名,应用程序层,有时被称为......基本上,.aspx 代码隐藏会与之对话的东西)中,但我觉得这样做,我让业务规则泄漏出来域。如果通过其他方式(除了服务层)访问域对象,则域对象无法强制执行自己的业务规则。

  2. 我可以通过构造函数注入将规范注入到我的模型类中。但同样,这感觉是“错误的”。我觉得唯一应该注入到模型类中的是“服务”,例如缓存、日志记录、脏标志跟踪等......如果可以避免它,请使用方面而不是乱扔模型的构造函数具有大量服务接口的类。

  3. 我可以通过方法注入(有时称为“双重调度”???)来注入规范,并显式地让该方法封装注入的规范以强制执行其业务规则。

  4. 创建一个“域服务”类,该类将通过构造函数注入获取规范,然后让服务层使用域服务来协调域对象。这对我来说似乎没问题,因为规范强制执行的规则仍然在“域”中,并且域服务类的命名方式非常类似于它所协调的域对象。这里的事情是,我觉得我正在编写很多类和代码,只是为了“正确”实现规范模式。

除此之外,所讨论的规范需要一个存储库来确定它是否“满意”。

这可能会导致性能问题,尤其是。如果我使用构造函数注入,b/c 消耗代码可以调用一个可能包装规范的属性,而该属性又调用数据库。

那么有什么想法/想法/文章链接吗?

更新和使用规格的最佳地点在哪里?


简短回答:

您主要在服务层中使用规范,所以就在那里。

长答案:首先,这里有两个问题:

您的规格应该放在哪里?它们应该在哪里更新?

就像您的存储库接口一样,您的规范应该存在于域层中,因为它们毕竟是特定于域的。有一个关于SO的问题 https://stackoverflow.com/questions/7164034/ddd-and-implementing-persistence在存储库接口上讨论了这个问题。

但他们应该在哪里更新呢?嗯,我用Linq规格 http://linqspecs.codeplex.com/releases/view/46498在我的存储库上,并且我的存储库上大多有三种方法:

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);
}

我的其余查询是在我的服务层中构建的。这可以防止存储库因 GetUserByEmail、GetUserById、GetUserByStatus 等方法而变得臃肿。 在我的服务中,我更新了我的规范并将它们传递给我的存储库的 FindAll 或 FindOne 方法。例如:

public User GetUserByEmail(string email)
{
    var withEmail = new UserByEmail(email); // the specification
    return userRepository.FindOne(withEmail);
}

这是规格:

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
}

因此,为了回答您的问题,服务层中的规格是新的(在我的书中)。

我觉得唯一应该注入到模型类中的东西 是“服务”

IMO 你不应该向域实体中注入任何东西。

除此之外,相关规范需要一个存储库 以确定是否“满意”。

那是一个代码气味 http://www.codinghorror.com/blog/2006/05/code-smells.html。我会在那里审查你的代码。规范绝对不需要存储库。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

规范模式对象应该在哪一层“更新”? 的相关文章

  • DTO 道 POCO BO

    事实上 我对这些术语以及它们之间的关系感到非常困惑 我读过有关其中每个人的一些内容 但我不了解工作流程 DTO 数据传输对象 传输值的对象BO 业务对象 域模型中的对象 用于制作业务逻辑的对象POCO 不知道 我在维基上读过定义 但什么也没
  • DDD 中哪一层应该包含查询

    我有一个简单的 DDD 服务 带有文章聚合根 我使用 MediatR 和 CQRS 来分离命令和查询 在 DDD 域中不应依赖于应用程序和基础设施层 我有一个存储库 IArticleRepository 用于从文章数据库中组合一些数据 我有
  • 使用 DDD 方法在 Python 中保留 POJO

    我正在尝试使用 DDD 模式创建 Flask 应用程序 DDD 的核心原则之一是将领域与持久性 基础设施 分离 我已在模块中定义了域模型 并将在基础设施模块中创建存储库 但是 我似乎找不到任何关于如何在 Python 中持久保存 POJO
  • 领域驱动设计中的 WCF 序列化和值对象模式

    Eric Evans 所著的 领域驱动设计 一书描述了称为值对象的模式 值对象的重要特征之一是它是不可变的 作为一个例子 我有一个值对象 Clinic 其中must有名字和id 为了使其成为值对象 我不提供名称和 ID 的设置器 另外 为了
  • DDD:我真的需要加载聚合中的所有对象吗? (性能问题)

    在 DDD 中 存储库加载整个聚合 我们要么加载全部 要么不加载 这也意味着应该避免延迟加载 我关心的是性能方面的问题 如果这导致将数千个对象加载到内存中怎么办 例如 聚合Customer一万回来Orders 在这种情况下 是否意味着我需要
  • 导入数据和事件溯源

    我目前正在开发一个整体系统 我希望将其引入现代并结合 DDD 和 CQRS 我收到了重新编写解决方案的导入机制的请求 并认为这可能是开始此重新架构过程的好机会 目前流程是 用户上传 CSV 系统解析 CSV 并在屏幕上显示每一行 对每一行以
  • 领域驱动设计和聚合参考

    我正在设计领域模型 但有些东西似乎不太好 我从一个主要的聚合开始 它引用了其他聚合 而其他聚合也引用了更多聚合 我可以从主聚合开始遍历孔域模型 我看到的问题是我将在内存中保存聚合的所有实例 这是一个好的设计吗 我可以通过延迟加载解决内存问题
  • DDD和应用层

    我在DDD中添加 Stateful Stateless WebService等是应用层 应用服务 吗 从下面的链接来看 这似乎是正确的 第二个问题 我创建了一个存储库类 所有涉及存储库的方法调用都应该包装在应用程序服务中吗 或者我可以直接在
  • n 层架构 - BLL、DAL 和接口。什么是最佳实践?

    我有一个关于 n 层架构的问题 在问这个问题之前 我想了很久 因为这里已经有很多类似的问题了 但是 在看了一天半并阅读了其他答案之后 我仍然不确定 各种看似相似的术语和不同的方法让我感到困惑 如果我在不同的类库中有一个 BLL 和一个 DA
  • 再次将服务注入域对象

    我有一个对地理数据进行操作的特定域 我正在 TypeScript 和 NodeJS 中实现这个项目 并有以下类 Point 包含纬度和经度的值对象 Area 包含点集作为形状定义的值对象 Sector 实体 它不是持久的 但它是可变的 包含
  • 定义具有多种消息类型的消息传递域

    到目前为止 我见过的大多数 F 消息传递示例都使用 2 4 种消息类型 并且能够利用模式匹配将每条消息定向到其正确的处理函数 对于我的应用程序 由于处理和所需参数的不同性质 我需要数百种独特的消息类型 到目前为止 每个消息类型都是其自己的记
  • 实体框架中的聚合根支持

    我们如何告诉实体框架骨料 http domaindrivendesign org node 88 保存聚合时 保存聚合内的实体 删除聚合时 删除聚合内的实体 当两个不同的用户尝试修改同一聚合中的两个不同实体时引发并发错误 加载聚合时 即使在
  • DDD:持久聚合

    让我们考虑一下典型的Order and 订单项目例子 假如说订单项目是的一部分Order聚合 只能通过订单添加 所以 要添加一个新的订单项目 to an Order 我们必须通过存储库加载整个聚合 将新项目添加到Order对象并再次保留整个
  • ASP.NET Web Api 的事件发布者

    我已经开始使用微服务 我需要创建一个事件发布机制 我计划使用 Amazon SQS 这个想法很简单 我将事件存储在与聚合相同的事务中的数据库中 如果用户更改他的电子邮件 事件UserChangedEmail将被存储在数据库中 我还有事件处理
  • 在域驱动设计中设置模型属性默认值的最佳实践?

    在 DDD 中为新实体设置默认属性的最佳方法是什么 另外 为复杂属性 例如集合 设置默认状态的最佳方法是什么 我的感觉是默认值应该在模型本身中 因为它们是业务规则的一种形式 默认情况下 我们希望 X 是 Y 和 Z 并且域代表业务 通过这种
  • NHibernate IQueryable 集合作为 root 的属性

    我有一个根对象 它有一个集合属性 例如 I have a Shelf object that has Books Now public class Shelf public ICollection
  • 在DDD中,值对象的实际优势是什么?

    到目前为止 我知道实体对象有 ID 而值对象没有 但在最常见的示例中 人员实体附加了地址值对象 创建单独的地址对象而不是仅将地址属性保留在 Person 实体中的最大优点是什么 除了已经提到的事情之外 格雷格 杨 http weblogs
  • EF 6:映射复杂类型集合?

    EF 6 代码优先 是否支持复杂类型集合 值对象集合 映射 我知道它支持复杂类型 但还没有找到我们拥有复杂类型集合的示例 例如 假设您有一个名为 Student 的实体 其中包含联系人集合 对于 NH 我可以简单地说 Student 有一个
  • 丰富的领域模型和 ORM

    Martin Fowler 认为贫血领域模型是一种反模式 将持久性模型作为域模型进行滚动似乎也严重偏离 因为对象关系阻抗不匹配 http en wikipedia org wiki Object Relational impedance m
  • 域驱动设计中输入验证应该放在哪里?

    我想知道我们到底应该在哪里放置输入验证 想象一下 API 调用发送输入以应用用户的空闲时间 在服务层注入验证类并在服务内部调用验证方法是否正确 或者最好将其放在基础设施层甚至领域模型中 我只是想看看在域驱动设计方法中实现 API 输入验证的

随机推荐

  • 最好的 Python GIS 库? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Laravel Passport - 测试密码授予

    我使用 Laravel 5 7 和 Passport 为第一方客户端创建 API 我有一个登录表单 它接受用户的电子邮件和密码并将两者发送到自定义 LoginController 然后 LoginController 创建一个 oAuth
  • NSPredicate 不适用于字典数组

    我有一个 NSPredicate 其格式如下 Status CONTAINS cd shipped 我有一个字典数组 这是一个例子 Category Category 4 Comp Category 4 Depth 02 Grade New
  • 具有空间数据的 3D 交互式曲面图

    我想创建一个湖泊深度的交互式 3D 表面图 最好使用plotly or rgl图书馆 我已经从一个中提取了我的数据SpatialLinesDataFrameGauss Krueger EPSG 31468 CRS 中的等高线 即公制单位 现
  • 2010 年 .NET Compact Framework 是否更新?

    这个问题 net 紧凑框架 4 0 https stackoverflow com questions 245566 net compact framework 4 0 在VS 2010发布之前就问过这个问题 答案基本上都是说等待发布 现在
  • 请求的资源node.js上不存在Access-Control-Allow-Origin标头[重复]

    这个问题在这里已经有答案了 我在尝试通过 ajax 请求与我的 node js 服务器通信时遇到问题 我已经这样配置我的服务器 var allowCrossDomain function req res next res header Ac
  • 无法从 xml 定义中找到 Activity 中的 onClick 方法

    我试图将一个函数链接到 AndroidStudio 中按钮的 onClick 属性 但由于某种原因 系统无法识别我编码的方法 有趣的是 当我用 Java 编写代码时 它可以正常工作 在 Kotlin 中则不然 我更新了 Kotlin 并检查
  • ul 左侧​​的浮动图像忽略边距/填充

    我有一个段落 后面是一个无序列表 其中有几个列表项 我还有一个图像浮动在其左侧 我遇到的问题是列表项边距 填充与该图像重叠 我希望图像旁边的项目符号按应有的方式缩进 这是一个测试 http testing gorocketfuel com
  • 包含 std::string 的 memset 结构

    我有一个庞大的结构 其中整个内容是标量变量 枚举和标量数组 基于堆栈 但一个 std string 变量除外 现在 这是我的问题 我可以将结构的整个大小设置为 0 就像我会的那样 如果它只是所有标量 或者 std string 在那里是不可
  • 速记类构造函数字段初始化

    我忍不住觉得有一种简写方法可以写成这样 public abstract class MessageBase public String Destination Sender Uid public MessageBase String des
  • 在 F# 中实现受限数字类型的习惯用法/实践?

    假设需要一种数值数据类型 其允许的值落在指定范围内 更具体地说 假设要定义一个最小值为 0 最大值为 5000 的整数类型 这种情况在很多情况下都会出现 例如在对数据库数据类型 XSD 数据类型等进行建模时 在 F 中对此类类型进行建模的最
  • android 在将数据插入数据库之前检查重复值

    String new recorded lastname a lastname record to database Cursor cursor db rawQuery SELECT lastname FROM people null if
  • 如何在 C 中一次清除多个位?

    我如何将所有这些简化为一行 REG BITA REG BITB REG BITC REG BITD REG BITE 您可以使用 按位或 运算符 REG BITA BITB BITC BITD BITE
  • 如何从 Map> 创建 Multimap

    我没有找到这样的多重映射构造 当我想这样做时 我会迭代映射 并填充多重映射 还有其他办法吗 final Map
  • NSOutlineView 组间距

    我正在开发 NSOutlineView SourceList 并希望用我自己的样式替换当前样式 以便更好地查看我的应用程序 我已经使用自定义 NSTableViewRows 更改了默认标题和内容单元格 这很好用 但现在我可以看到组之间有一个
  • 在 WebView 中禁用邮寄地址的自动链接

    android WebView 将自动检测 html 中的邮寄地址 并允许您单击它来启动地图 有没有办法在不更改本机代码的情况下禁用此功能 我可以在 html 标记中添加一些内容或取消 javascript 事件来防止这种情况发生吗 如果我
  • Angular 6 / 在 tsconfig.lib.json 中声明库的路径

    我正在尝试配置路径Angular 6库 我已经成功配置了以前的 Angular 项目的路径 这是我以前的应用程序的工作原理tsconfig json file compilerOptions baseUrl src paths class
  • 变量多态性的初始化

    假设您有以下代码 class A int i 4 A print void print System out println A class B extends A int i 2 this line public static void
  • 更新后的状态值不会在反应函数内部更新

    反应状态更新值显示在使用效果中 但内部函数仅显示旧值 const counter setCounter useState 0 我正在尝试更新设定间隔函数内的计数器值 const handleIncrease gt clearInterval
  • 规范模式对象应该在哪一层“更新”?

    因此 我在这里查看了一些有关规范模式的帖子 但尚未找到此问题的答案 我的问题是 在 n 层架构中 我的规范到底应该在哪里 更新 我可以将它们放在我的服务层 又名 应用程序层 有时被称为 基本上 aspx 代码隐藏会与之对话的东西 中 但我觉