TS 不是 OO 或非 OO。您可以在域模型方法、服务方法或高级应用程序方法中使用它。这只是意味着您可以阅读程序的业务意图,而无需通过一百万个回调和“黑魔法”。
这就是微软引入 async/await 的原因。它将看起来晦涩难懂的 send-a-callback(委托)和 exit,process-the-callback-in-separate-method(必需)样式转换为可读的事务脚本。
GOTO 很糟糕,因为它们破坏了事务脚本的可读流程,使其成为一个糟糕的脚本。
a) 事务脚本出错是一种反模式。例如,一个巨大的方法,没有或很少的方法调用等,同一方法中的不同级别的操作(将它们重构为方法)。业务流程的离散步骤集中在一个方法中(将它们分解为方法或单独的类。很多业务对象?使用 DDD 服务模式)。
b) 不正确使用 TS 是一种反模式。例如大量的应用程序间消息传递、事件触发等,因此您无法通读并查看业务流程(技术应用程序的功能要求)。低层次的细节(技术)与功能性工作相结合。过度分离应该在一页上可见的业务活动。
TS 的使用应该是分形的,每次放大都会深入到更详细的 TS 样式逻辑。高级:您会看到方法调用和 DDD 服务使用。中等水平可能有点混合。下面主要是域对象方法/属性调用以及最精细的逻辑细节。
将 TS 扔到公共汽车下,因为它可能会被滥用,或者阻止它的使用,只会把罐子踢到路上 - 无法分组和分离并且不知道 SRP(单一责任)/凝聚力的开发人员会搞砸其他风格, 也。答案是对他们进行业务流程培训,并举例说明分组和分离——这应该通过业务/功能需求(垂直切片)而不是技术(水平切片)来完成。
- 将只处理一个域对象或其类型的其他实例的逻辑放在 DO 中。不要从域对象(person.orders)中引用其他对象类型或将任何东西注入到域对象中。(其他 DO 或存储库等)。就这么简单,它违反了 SRP。[方法中的低级事务脚本]
- 当你需要 person.orders 之类的东西,或者感觉需要注入一些东西时,创建一个 DDD 服务(不序列化,每次使用后没有持久属性)。注入例如一个人,以及其他集合(存储库或 IQueryable 等)。在那里工作。[此处为中级交易脚本]
- 在 DDD 服务的“应用程序方法”类别中组合对域对象和 DDD svcs 的操作。
- 从程序的最高级别构造和调用那些
在每个级别,它看起来像一个 TX 脚本,但要遵守规则。保持方法小。到时候你就可以阅读了!
注意:在另一个答案中提供的链接中,Fowler 告诉您如何使交易脚本正确与错误:
https://www.informit.com/articles/article.aspx?p=1398617
他也确实暗示它不是面向对象的。我认为您可以将它与 OO 混合并使用 TS 专业人士(可读性和一百个专业人士),以及数百名 OO 专业人士。也就是说,您可以将TS元素放在一个领域模型中,并在更高层次的TS中组合领域模型的使用。
还要考虑将事务脚本定义为单个数据库事务。由于您的域模型不应该注入存储库(将域对象注入存储库),因此您实际上可以像这样组织它,调用相关存储库以在最高级别(取消)持久化。但如果不是这样,关键是要有一个没有过度分离的可读代码流。
抨击 TS 的问题在于它使人们认为 SRP 完全是关于 SoC(关注点分离),而他们永远不必担心凝聚力(将相同的东西放在一起,这也意味着 SoC,但需要组织)。因此,好心的工程师只是将事物分成一百万个部分(因为越多越好),并且更难辨别逻辑。