【问题标题】:DDD Architecture - Where To Put Common Methods/HelpersDDD 架构 - 通用方法/助手的放置位置
【发布时间】:2014-07-16 04:40:29
【问题描述】:

根据 Stack Overflow 上的this question,在 DDD 架构中,“帮助器”类可以根据其用途位于不同的层中。例如,以用户友好的方式格式化某些内容的助手将进入 UI。数据库助手将进入基础设施。

但是可以被多个层使用的助手呢?例如年龄计算。业务逻辑的模型层可能需要年龄。它被多个实体使用,因此不应位于特定实体中。还有一些地方需要年龄只是为了在 UI 中显示。同样,我有多个层可以使用的字符串函数。例如,我的自定义 Right 和 Left 方法可用于 UI 中的格式设置,但它们也可能用于模型中,例如基于前缀的条件逻辑。

那么这些常用的方法应该去哪里呢?我的设置是这样的:

  • 用户界面
  • 应用
  • 型号
  • 基础设施

模型是核心,不依赖于基础设施,所以普通助手不能进入基础设施。我正在考虑两种选择:

1) 有另一个层,称为 Common 或类似的层,任何层都可以使用。这会在 Model 和 Common 之间创建依赖关系。

2) 在任何需要的层中复制辅助逻辑。例如,在 UI 中有一个 Age helper,在 Model 中有一个 Age helper。这会违反 DRY,但不需要域依赖于“公共”层。

哪个选项更好?模型层是否可以依赖“公共”层?

更新:

在提出这个问题后的 2.5 年里,我得出结论:

  1. 诸如 Right、Left 等弥补框架限制的事物属于“通用”实用程序/帮助组件,甚至模型/域层都依赖它。
  2. “通用”实用程序/帮助程序组件不应很大。随着经验的积累,我发现很多我认为是帮助者的东西实际上都属于领域模型。
  3. 年龄属于领域层中它自己的类。就像地址、电话号码和金钱之类的东西一样,我认为这些东西是价值对象。理解值对象确实是我理解创建可合并到其他类中的可重用领域类的关键。

【问题讨论】:

  • 你有比年龄计算更好的例子吗?或者您能否详细说明该示例的复杂性?
  • @MattDavey 我还提到了字符串示例,其中我在 UI 中使用自定义的 Right 和 Left 方法进行格式化,但也在域中使用,例如基于前缀的条件逻辑。实际上并没有多少“帮助者”会落入这种需要不止一层的场景中。我的大多数助手都可以整齐地插入特定层,但正如我所提到的,有一些是跨层所必需的。

标签: architecture domain-driven-design


【解决方案1】:

我认为字符串助手略有不同 - 在这种情况下,您的自定义 Right 和 Left 方法实际上是在补偿您的语言/平台的内置字符串类型的限制 - 它与您的应用程序本身,因此在这种情况下,可以全局访问它。

年龄计算示例更有趣一些,因为它封装了行为/逻辑,这在很大程度上是您的应用程序/域的固有部分。在这种情况下,可能值得根据具体情况评估是否值得在每一层中复制行为(违反 DRY 而支持 SRP)。这是一个艰难的决定。尽管它们现在可能是相同的,但通过复制行为,您可以让这两种方法在未来有机会相互分歧。如果他们有改变的不同理由,通常会发生这种情况。

【讨论】:

  • 是的,它是 C#,没有原生的左右函数。年龄计算非常简单。只需喂它一个 DOB 并转换为年龄。我不认为未来会发生这种变化。如果我需要更复杂的东西,我想我会创建一个不同的方法。
  • 查看 2.5 年后的更新。谢谢你把我送到正确的方向
【解决方案2】:

根据我的经验,拥有一个包含所有辅助类/方法的 CommonInfrastructure(或类似的)组件/层是正确的方法。 您描述的 String 助手和 Age 助手都可以进入那里(以及 DateTime 助手、字典、动态、Linq 等等)。

它应该是一个可以很容易地用于下一个项目的库,因为它非常通用并且不依赖于当前的域逻辑,并且包含用于所有目的的有用代码。

违反 DRY 的唯一原因是如果您需要 UI 上的 Javascript 代码和后端上的 C# 代码,在这种情况下,您需要复制该通用基础架构代码(除非您想出更精细的解决方案保持干燥)。

【讨论】:

  • 您是否将所有帮助程序类/方法都放在这里,甚至是那些不需要共享的,例如仅适用于 UI 的 cookie 帮助程序和 html 扩展?
  • 是的,我愿意。我会将它们分成不同的文件夹,并将所有与 UI、Web、DateTime、String、Encryption 等相关的类放在一个文件夹中。通常你没有数百个助手,只有少数......
  • 虽然我最初倾向于每一层都有自己的实用程序的想法,但在实践中我发现有太多次我需要不止一层的东西和/或我会忘记哪一层特定实用程序。因此,为了维护简单起见,我将按照您的建议将整个射击比赛放在一个公共层中并完成它。
  • 我们在哪里保留帮助器,例如配置帮助器,它是特定于域的,但由存储库和服务层使用
  • @Thunder,配置可以拆分为存储库配置和服务配置,然后每个配置都可以与该层的所有其他文件一起保存。如果它们共享可以作为通用配置助手的通用代码,该代码保存在所有其他层(“基础设施”、“通用”、“通用”等)都可以访问的层中。这实际上取决于配置的作用以及它的通用性或特定于域的程度。
猜你喜欢
  • 1970-01-01
  • 2021-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-16
  • 1970-01-01
  • 2010-10-25
相关资源
最近更新 更多