你在用什么思想编码:事务脚本还是面向对象

最近在公司内部做技术交流的时候,说起技能提升的问题,调研大家想要培训什么,结果大出我意料,很多人想要培训:面向对象编码。于是我抛出一个问题:你觉得我们现在的代码是面向对象的吗?有人回答:是,有人回答否。我对这个问题的回答是:语法上,是了,但是架构上或者思想上,不是。我们现在的大部分代码,如果要死扣一个名词的话,那就是:事务脚本。

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/

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索面向对象
脚本
,以便于您获取更多的相关知识。

时间: 2024-11-16 05:57:11

你在用什么思想编码:事务脚本还是面向对象的相关文章

PHP面向对象之事务脚本模式(详解)

如下所示: /* 事务脚本模式: 类似于thinkphp中的model层,或者说就是操作数据库的类. 个人觉得实践中使用起来还是挺简单方便的,就是SQL语句写死了的话,灵活性就不够. 示例代码如下: */ namespace woo\process; abstract class Base{ static $DB; //pdo对象 static $stmts = array(); //sql语句句柄 function __construct (){ $dsn = \woo\base\Applic

.NET应用架构设计—表模块模式与事务脚本模式的代码编写

阅读目录: 1.背景介绍 2.简单介绍表模块模式.事务脚本模式 3.正确的编写表模块模式.事务脚本模式的代码 4.总结 1.背景介绍 要想正确的设计系统架构就必须能正确的搞懂每个架构模式的用意,而不是胡子眉毛一把抓.现在有一个现象是什么呢,项目的结构从表面上看是很不错,层分的很合理,其实对业务系统来说也就那么几种层设计方法,但是现在很多项目的逻辑架构的设计不是理想,有很多概念大家并不是很了解,当然也许每个人对技术的追求不同罢了.不管你追求不追求,事实我们还是要去往正确的方向努力才对的. 很多人包

GBK编码PHP脚本导致语法错误

这个是因为, 在GBK环境下, "玕"的编码是"0xab 0x5c, 所以, 又是一个'5c'引发的问题.. 一般来说, 还是建议大家用unicode作为代码文件的字符集, 如果要使用GBK, 再主动转换下. 不过, 就问题说问题, 如果你的脚本非要GBK编码, 那怎么避免这个问题呢? 从PHP5.3开始, PHP引入了Zend Multibyte来支持多字符集编码. 对于上面的代码, 我们修改如下: 然后, 在php.ini中配置: mbstring.internal_en

javascript 面向对象思想 附源码_js面向对象

复制代码 代码如下: <html> <head> <script type="text/javascript"><!-- ClassModel = //类模型,用于创建类 { create: function() { return function(){this.construct.apply(this,arguments);} } } Extend = function(desc, src) //模拟类继承, 将一个对象的所有成员 复制到 另

使用iconv批量改变文件编码的shell脚本_linux shell

这篇文章主要介绍了编写shell脚本,使用iconv批量改变文件编码的脚本代码,需要的朋友可以参考下. 用法示例: cd ~/workspace/XXXProject ~/iconv_shell.sh ./ *java 好了,直接上代码~~ #!/bin/bash if [ "$#" != "2" ]; then echo "Usage: `basename $0` dir filter" exit fi dir=$1 filter=$2 ech

Spring框架与AOP思想的研究与应用

摘要 本文对Spring框架中所包含的AOP思想以及事务管理进行了分析,并通过对一个业务对象实现加锁/解锁的操作,说明了动态代理模式的可行性与有效性. 关键词 AOP:横切关注点:控制反转:动态代理 引言 Aspect Oriented Programming(AOP)是近年来计算机技术中比较热门的话题之一.其发展历史从学术领域和研发机构的运用开始,目前流行的Spring应用程序框架将AOP思想融入了整个框架的设计开发与应用当中.使用Spring框架固然给我们的编程带来了好处与便利,但是同时存在

PHP脚本测试

我们经常会遇到这种情况:将一些没有经过任何测试的遗留代码进行重新编写测试,甚至这些代码还是用面向对象写的.要对这样的代码进行测试,我的建议是把代码分解成块,这样就容易测试了. 然而,这些遗留代码并不是那么好重构的,比如:测试前,你不能在把代码重新编写,这是为了避免影响原有程序,当然也不好进行单元测试. 在PHP程序中,通常有一部分代码是写在几个index.php和script.php文件中的,这些.php文件存放在几个不同的文件夹里.如果不找到它们的入口点,是无法直接由Web服务器访问的. 测试

Microsoft 脚本编码器Script Encoder介绍(2)全中文

使用脚本编码器 脚本编码器只对脚本代码进行编码,文件的其他内容不动且以普通文本形式显示.要使用脚本编码器,以通常方法对文本进行开发和调试,然后使用该实用程序对最终的脚本进行编码. 脚本编码器在源代码中使用标记来标识编码开始的位置.对于 Visual Basic Scripting Edition (VBScript),如下示例显示了如何使用编码标记来显示普通文本的版权信息: <SCRIPT LANGUAGE="VBScript">'Copyright 1998. XYZ P

Microsoft 脚本编码器Script Encoder介绍(2)

encode|编码|脚本 使用脚本编码器 脚本编码器只对脚本代码进行编码,文件的其他内容不动且以普通文本形式显示.要使用脚本编码器,以通常方法对文本进行开发和调试,然后使用该实用程序对最终的脚本进行编码. 脚本编码器在源代码中使用标记来标识编码开始的位置.对于 Visual Basic Scripting Edition (VBScript),如下示例显示了如何使用编码标记来显示普通文本的版权信息: <SCRIPT LANGUAGE="VBScript">'Copyrigh