最近在公司内部做技术交流的时候,说起技能提升的问题,调研大家想要培训什么,结果大出我意料,很多人想要培训:面向对象编码。于是我抛出一个问题:你觉得我们现在的代码是面向对象的吗?有人回答:是,有人回答否。我对这个问题的回答是:语法上,是了,但是架构上或者思想上,不是。我们现在的大部分代码,如果要死扣一个名词的话,那就是:事务脚本。
1:最开始的事务脚本
在 Martin Fowler 的书中,存在一个典型的 应用场景,即“收入确认”(Revenue Recognition)。该“收入确认”的描述:
一家软件公司有3种产品,其售价策略分别为,第一种:交全款才能卖给你;第二种,付三分之一,就给你,60天后,再给1/3,90天后给完全部;第三种,付1/3,就给你,30天后给1/3,60天后给完。
但是,关于这个描述,我打算多啰嗦几句,而且个人觉的这个啰嗦非常之紧要,因为它影响到了我们的设计。以下是啰嗦的部分:
“收入确认”,在概念上,确实是产品的入账策略,实际上,Martin 的代码,也是这么去实现的,不同的产品有不同的入账策略。不过,数据库实现,RevenueRecognition 这个表记录的是“产品的某个合同根据产品类型所计算出来的:应该执行的入账日及金额”,即策略是跟着合同走的,而不是跟着产品走的。这很有意思,如果你精读此部分,这种矛盾就会一直纠结在你心头。同时,我们又不得不时刻提醒自己存在的这个需求。
现在,关于这个场景,如果我们理解了 产品 合同 RevenueRecognition 之间的关系,我们就很能理解了数据库是被设计成这样的:
其概念模型为如下:
好了,现在我们来看看什么是事务脚本,对的,就用代码来说话。在原文中, Martin 举了两个例子,但是精读之后,我打算将其颠个倒,把原文中的示例2讲在前头。因为示例2,很好的表达了什么才是作者或者译者眼中的“收入确认”,以及我眼中的“收入策略”。
第一个要实现的功能,即第一个事务脚本描述如下:
根据合同 ID,找到该合同,并根据合同类型得到应该在哪天收入多少钱,并插入数据库。
从该描述中,我们知道,这个脚本最应该发生在签订合同时。因为合同一旦签订,就应该记录什么时候应该收到客户端多少钱。代码如下:
class RecognitionService { dynamic dal = null; // 计算哪天该入账多少并插入 public void CalculateRevenueRecognitions(long contactNumber) { DataSet contractDs = dal.FindContract(contactNumber); double totalRevenue = (double)contractDs.Tables[0].Rows[0]["ID"]; DateTime dateSigned = (DateTime)contractDs.Tables[0].Rows[0]["DateSigned"]; string type = (string)contractDs.Tables[0].Rows[0]["Type"]; if(type == "S") // 电子表格类 { // the sql "INSERT INTO REVENUECONGNITIONS (CONTRACT,AMOUNT,RECOGNIZEDON) VALUES (?,?,?)" dal.InsertRecognition(contactNumber, totalRevenue / 3, dateSigned); dal.InsertRecognition(contactNumber, totalRevenue / 3, dateSigned.AddDays(60)); dal.InsertRecognition(contactNumber, totalRevenue / 3, dateSigned.AddDays(90)); }else if(type == "W") // 文字处理 { dal.InsertRecognition(contactNumber, totalRevenue, dateSigned); }else if(type == "D") // 数据库 { dal.InsertRecognition(contactNumber, totalRevenue / 3, dateSigned); dal.InsertRecognition(contactNumber, totalRevenue / 3, dateSigned.AddDays(30)); dal.InsertRecognition(contactNumber, totalRevenue / 3, dateSigned.AddDays(60)); } } }
本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/project/
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索面向对象
脚本
,以便于您获取更多的相关知识。