谈谈我的看法:
1. 关于那段原文。因为我手上没有中文版,网上也找不到。只能找到英文版来看了一下,文章中其实已经解释得很详细了。
You can organize your Transaction Scripts into classes in two ways. The most common is to have several Transaction Scripts in a single class, where each class defines a subject area of related Transaction Scripts. This is straightforward and the best bet for most cases. The other way is to have each Transaction Script in its own class (Figure 9.1), using the Command pattern [Gang of Four]. In this case you define a supertype for your commands that specifies some execute method in which Transaction Script logic fits. The advantage of this is that it allows you to manipulate instances of scripts as objects at runtime, although I've rarely seen a need todo
this with the kinds of systems that use Transaction Scripts to organizedo
main logic. Of course, you can ignore classes completely in many languages and just use global functions. However, you'll often find that instantiating a new object helps with threading issues as it makes it easier to isolate data.
使用命令模式是为了提供一个灵活性,让你在编写界面代码时不用考虑具体由哪个类去实现这个事务,只需要同过高层的接口向事务对象丢command。但原文也提到,实际上这样做的案例是很少的。因为既然选择用事务脚本,说明业务逻辑很简单。既然很简单,有变动的时候直接去改事务脚本逻辑就可以了,这层灵活性显得多此一举了。原文最后提到,在事务脚本模式中,你甚至可以完全不用面向对象方法,直接把事务脚本做成全局过程。不过,作者最后还是推荐做成对象,不是为了结构清晰,重用性的原因,而是做成对象在做多线程时处理并发访问时比较方便。
所谓事务脚本,说白了就是把“删除用户”,“转帐”,“存款”这些业务上的事务做成一个单位,可以是过程,可以是类方法,甚至直接放在Button1OnClick中。这个过程负责这个事务的一切事情,获取数据库连接,计算结果,生成SQL语句,提交,归还(用了连接池的时候)或者关闭连接。这里的“负责”,是指你在写事务脚本时“要考虑到这些事情”,你可以把获取数据连接的代码抽取出来做成一个全局的GetConnection()的函数,或者是使用DataModule里某个TDataBase.Connection.但你在写脚本时必须要知道用这个函数(或者知道要从这个DataBase对象)取得连接。相对来说,用DomainModel这样的模式时,业务逻辑部分是完全不管这些东西的。
读取数据,验证,数据集事件这样的分类是从数据集本身去考虑,因此与事务上的分类是交叉的。一个事务可能包括了读取数据,验证,计算字段等等事情。例如,一个提款机提款的事务Withdraw(AccountNum: integer;
Amount : Currency) : boolean;
(Amount是用户输入的金额),包括了读取余额,比较余额与提款金额,做减法,更新余额,向提款机驱动程序发消息让它吐钱并打印单据等。
关于是否要与界面分离,原文也做了解释:
My preference is to separate Transaction Scripts as much as you can. At the very least put them in distinct subroutines;
better still, put them in classes separate from those that handle presentation and data source. In addition,do
n't have any calls from the Transaction Scripts to any presentation logic;
that will make it easier to modify the code and test the Transaction Scripts.
作者说:建议尽量分离事务脚本,至少应该把它们放在独立的子程序中。(我的理解是,作者甚至认为没有分离成独立子程序的一段代码也可以看作是一个“事务脚本”,他建议把这些代码分离出来。)更好一点的做法是,把它们放在独立的类中,从界面代码与数据源代码中分离出去。(我的理解是,这个分离是代码上的分离,而不是概念上的分离。象上面提到的,可以把数据源代码都抽离出去做成独立函数或类。但在编写事务脚本时,需要知道这些函数和类)。更进一步,他建议在事务脚本中不要调用任何在表达层的子程序,也就是说,在事务代码中最好不要出现 s = Form1.Edit1.Text这样的东西。这样测试和修改起来会方便一些。
我对事务脚本的理解是,事务脚本是组织业务逻辑的最简单的形式。只要你不是跟自己过不去,故意把做同一件事的代码漫无目的地分散开,同时又没有专门考虑分层结构。最终自然就会做成一个事务脚本。作者只是把这种最直观最常用的做法称为事务脚本而已,并且说明,在系统很简单的时候,可以不考虑分层呀,框架呀之类种种,直接用事务脚本,方便快捷,避免过度设计。