30-11 之Domain Layer - Transaction Script

接下来这一篇文章开始,我们要进入所谓 3-Tier 的『 Domain 』的部份,这个层级基本上就是专门处理每一间公司的『 domain knowledge 』,某些方面来说这个层级应该是最重要的。

接下来我们将要谈谈,在 《 企业应用架构模式- Martin Fowler 》这本书中所提 domain 的三种 patterns 的第一种『 Transaction Script 』。

Transaction Script 是什麽呢 ?

Transaction Script organizes business logic by procedures where each procedure handles a single request from the presentation.

假设我们要实作一个『 购物车结帐 』的功能,我们有 87 % 的情况下,程序码应该会写成如下,就是一个购物车用的 service,然後里面有结帐 ( checkout ),然後将结帐要做的每个 task 都写在里面。

备注 1 : 书中范例也是用 service 来做这个类别的分类。

备注 2 : dao 的概念你现在只要记它是去操作 db 就好,详细的定义会在後面 Data Source 层级拿出来说。

class CartService{

	async checkout(){
     // 取出购物车要结帐的商品
		 const products = this.cart.items
     
     // 建立订单
		 const order = await orderDao.create(orderBody)
     // 建立付款记录
     const payment = await paymentDao.create(paymentBody)
     // 建立发票 
		 const invoice = await invoiceDao.create(invoiceBody)
	}
}

『 购物车( Cart )结帐 ( checkout ) 』这就代表一个事务,然後它里面所要完成的事情为 :

  • 建立订单
  • 建立付款记录
  • 建立发票

这种最常见的写法,就是所谓的『 Transaction Script 』。

这里和资料库的 transaction 功能不一样 :

  • Domain - Transaction Script : 将要完成某个事务的任务都写在一起
  • DB - Transaction : 确保事务有要就全部完成,不会有事务中某个任务执行失败,导致资料不一致的事情。

备注: 资料库事务与 ACID 不太熟的建议去过我的几篇文章 :

那 Transaction Script 这种写法有什麽缺点呢 ?

书中是有提到 :

当 Transaction Script 越来越复杂时,会越来越难保持良好的设计,问题在於事务之间的冗余程序码,因为里面的程序码都是专门用来处理该事务的

我这里提出几个我觉得问题点 :

  • service 与 service 最後会变成有可能共用,而这样就机率发生 cycle dependency。
  • 每个事务可共用的程序码可抽出来,但要放那 ? 且它是给 service 用,但有没有可能它需要某个 service 用的东西。
  • 每个 service 要处理范围在那 ? 假设有两个 service 分别为 Cart 与 Purchase,那结帐流程是要写那 ? Cart.checkout 还是 Purchase.execute(products) 呢 ?

但书中也提到个重点

有些事务的逻辑本来就简单,硬要设计成 domain model 的写法,反而不是好事。

小总结

这个知识点可以用来解释什麽现象

这个模式简单、快速,所以这种模式事实上非常非常的常见,我几乎待过的公司都有看过,包含现在公司也是,我觉得也因为简单、快速这个优点,所以大部份专案一开始的时後,除非有专职的软件架构师在,不然大部份以 MVP ( minimum viable product ) 为导向的产品,大约 87% 都长这个样子。

但这个最後苦的一定是後人。

这个知识点可以和以前的什麽知识连结呢 ?

就是我现在碰到的程序码,就基本是前人遗留下来的 Transaction Script,然後我就是後人,我总於知道我接触那麽久的东西就叫『 Transaction Script 』。

我要如何运用这个知识点 ?

  • 在开发产品型的东西,不要为了快速与方便选择 Transaction Script,後人维护与改写成本非常的恐布。
  • 专案型的我觉得可以。
  • 小工具型的我也觉得可以。

书中有提到一句话 :

早期选择正确的策略,通常是最好的方法

参考资料


<<:  Day11 PHP数据类型--复合类型之阵列

>>:  Day 11 state & props -2

[Day 15] 实作 OpenAPI Plugin 产生 API 文件

为什麽我想自己实作 Ktor OpenAPI Generator? 大多数的 Web 框架都有官方或...

Multicasting for RxJava

在进入正题之前先让大家看看在 Reactive Programming 中的一种使用案例: val ...

[Day - 11] - Spring 注入式之Resource原理与开发

Abstract 在第八天我们已得知既有的Autowird与Qualifier等常用的注入方式,今天...

我跟你一百万,再大你一百万,再show hand - 跟庄家吃香喝辣 ?

今天在赌场中有听到某位赌徒问了一位老师问题,是关於庄家吃货的策略 简单来说就是根据买卖明细判断,当某...

Day 11:批次修改!!

昨天体验了一些快捷键和命令,今天要讲的是在 vim 中也很常用的搜寻与取代 搜寻与取代 vim 的搜...