事务脚本是反模式的



有一个关于NoSQL数据库事务脚本的类似主题,但这是关于一般模式的。从我对事务脚本的发现来看,它根本不是面向对象的。它基本上是过程代码,尽管它可以在每一行代码中使用对象。

更好的解决方案是使用域模型,与活动记录或带有工作单元/身份映射/延迟加载/查询对象等的数据映射器相结合。事务脚本可能很容易使用,但它实际上是过程编程,因此应该被视为面向对象世界中的反模式。

你觉得怎么样?您同意事务脚本是反模式的吗?或者你真的有一种方法来设计一个面向对象的事务脚本,而不是伪装的过程?但我怀疑这是可能的。

Transaction Script绝对是不是反模式。

从我发现的Transaction脚本,它根本不是面向对象的。

你是对的,确实不是。然而,这个事实并不能使它成为反模式。虽然它是一种过程方法,但实际上,它在业务逻辑体系结构模式系列中仍然有其正确的位置—您只需要知道在哪种情况下使用它是最佳实践—而在哪种情况下不是。简单地说:如果你的问题领域非常简单,那么在你的业务逻辑中使用一个更复杂的模式是不值得的。

或者-正如福勒写的:

何时使用

Transaction Script的优点在于它的简单。对于只有少量逻辑的应用程序来说,以这种方式组织逻辑是很自然的,并且它在性能或理解方面涉及的开销很小。

你可能想到的反模式叫做贫血域模型。这就是当你打算并且认为正在构建一个领域模型时的情况——因为你的问题域已经足够复杂了——但是你实际上最终在一个事务脚本中结束——因为糟糕的代码组织/薄弱的OO技能。

不是反模式。事实上,大多数企业应用程序(我所见过的)使用事务脚本,而不是富域模型模式。

您提到的活动记录模式只有在您有相当简单的域实体到持久存储聚合(RDBMS表)的一对一映射时才方便。

数据映射器类似于ORM (Hibernate及其同类)。如果您的业务逻辑驻留在域实体中,那么这些实体必须改变自己。在我看来,这将改变状态的逻辑(在使用ORM时是固有的)与状态本身耦合在一起。从外部查看域模型并将业务逻辑放入服务(事务脚本)更为简单。此外,如果您的业务逻辑量很大,那么当它们分散在域实体中时(就像将事务脚本混合在一起一样)很难找到相关代码。

但是你不必以完全过程化的方式结束,因为你可以(也应该)把你的服务分解成自包含的高度内聚的"过程化容器"。

TS不是OO或非OO。您可以在域模型方法、服务方法或高级应用程序方法中使用它。它只是意味着你可以阅读程序的商业意图,而不必纠结于一百万回调和"黑魔法"。

这就是为什么微软引入async/await。它将看起来晦涩的send-a-callback (delegate)和exit、process-the-callback-in-separate-method (required)风格变成了一个可读的事务脚本

goto很糟糕,因为它们破坏了事务脚本的可读流程,使其成为一个糟糕的脚本。

a)事务脚本出错是一个反模式。例如,一个巨大的方法,没有或很少的方法调用,等等,同一方法中不同级别的操作(将它们重构为方法)。将业务流程的离散步骤放在一个方法中(将它们分解为方法或单独的类)。有很多业务对象?使用DDD服务模式)。

b)不正确使用TS是一个反模式。例如,大量的应用间消息传递、事件触发等,因此你无法通读并看到业务流程(技术应用的功能需求)。低层次的细节(技术)与功能性工作混合在一起。一个业务活动应该在一个页面上可见。

TS的使用应该是分形的,每个缩放到更详细的TS风格逻辑。高级:您看到方法调用和DDD服务的使用。中级游戏可能是一种混合。下面是域对象方法/属性调用,里面有最好的逻辑细节。

因为TS可能被滥用而把它扔到公共汽车下面,或者阻止它的使用,只是把问题推到后面——不能分组和分离,不知道SRP(单一责任)/内聚的开发也会搞砸其他风格。答案是对他们进行业务流程方面的培训,并给出分组和分离的示例——这应该由业务/功能需求(垂直部分)而不是技术(水平部分)来完成。

  1. 将只处理一个域对象或其类型的其他实例的逻辑放在DO中。不要从域对象(person.orders)中引用其他对象类型,也不要向域对象中注入任何东西。(其他DO或仓库等)。它违反了SRP,就这么简单。[方法中的低级事务脚本]
  2. 当你需要人之类的东西时。订单,或者感觉需要注入一些东西,创建一个DDD服务(未序列化,每次使用后没有持久属性)。注入例如,一个人,和其他集合(repository或IQueryable等)。在那里工作。[中级交易脚本]
  3. 将对域对象和DDD svcs的操作合并到DDD服务的"应用方法"类别中。
  4. 构造并从程序的最高层调用

在每个级别,它看起来像一个TX脚本,但要遵循规则。保持方法小。到那时你就能读懂了!

注意:在另一个答案提供的链接中,Fowler告诉你如何使交易脚本正确与错误:

https://www.informit.com/articles/article.aspx?p=1398617

他也确实认为它不是OO。我认为你可以把它和OO结合起来,使用TS的优点(可读性和成百上千的优点),以及成百上千的OO优点。也就是说,您可以将TS元素放在域模型中,并在更高级别的TS中组合域模型使用。

还考虑将事务脚本定义为单个数据库事务。因为你的域模型不应该注入存储库(将域对象注入到存储库中),你实际上可以这样组织它,调用相关的存储库在最高级别(de)持久化。但如果不是这种情况,关键是要有一个可读的代码流,而不是过度分隔。

痛斥TS的问题在于,它让人们认为SRP完全是关于SoC(关注点分离)的,而他们从来不必担心凝聚力(将相同的东西放在一起,这也意味着SoC,但需要组织)。因此,好心的工程师只是把东西分成一百万个部分(因为越多越好),很难辨别其中的逻辑。

相关内容

  • 没有找到相关文章

最新更新