计费中的抽象1

        花了几天的计费模块的领域对象图了,还是很零乱,相比我对于其他部分的抽象和建模,计费这个部分好像更难。想采用TDD的方式,就是Kent写的那个多币种相加的例子一样,从一个简单的Dollar对象,发展成包含Expression,Money,currency,Sum等对象的模型。我以前编写退休提醒特性时使用过这个方法。不过,我觉得对于整个计费模块而言,还是需要一个由领域驱动出来的领域模型,这样比较安稳。这也是我在写本科毕设时讨论的问题。
计费中都有些什么抽象呢?下面一一列举:
     1 结算清单 ,大概就是长这个样子:
         费目 计费吨 费率 金额
        觉得像什么,其实觉得挺像是商店打出来的帐单,区别是,那个上面还有支付和找零两个字段。那么这个算什么呢?有点像订单。反正其本质记录了,港口为你服务产生了哪些费用。结算清单(管它叫Billing?)和结算清单条目(BillItem)是两个可以看出来的对象。
        2 费目和费用 ,一个对象是FeeItem,一个是Charges(阿达说他们公司的费用用这个单词表示)。FeeItem可以理解为Product,而 Charges被理解为Item,FeeItem中指定义了那些恒久不变的东西,比如费目代码(FeeCode),费目名称(FeeName);而 Charges里则包含了费目和费率(Rate)。对于产品而言,其价格一般是固定的,但是在这里,费率(实际上就是个单价)是根据一定的规则得出的。不过,也有些费率是固定的,比如港口建设费(你想到机场建设费了?)。
       3 计费吨。 计费吨不代表一定是重量,也可以是体积,件数。一般而言,费用=费率*计费吨。如果把重量体积件数定义为计费吨,会出现费用=费率*计费吨*时间,比如停泊费。而有的费用是要乘以折扣(discount)的,或者是倍数,这里可以统一称为reduce。把时间看成倍数?还是算了吧。那么就是有不同的计费公式,公式?哦,和表达式是一个单词,就是expression,看来我也需要引入这个概念。 expression=rate*ton*time*reduce。它也是个接口,money是实现类。
       4 计费策略。 隐隐的觉得应该使用策略模式,因为不同的费用计算公式不同,参考的计费规则也不同,那么每个费目都应该对应不同计费策略,在这些策略里实现不同的公式和去参考不同的计费规则。
       5 计费规则。 我隐隐的觉得规则这个东西的概念很大,我在合同和交通部的费规里定义了计算每笔费用的规则,但是,实际上我在这里指的应该是那些动态变化的规则,而那些诸如停泊费=船舶净吨*停泊时间*费率的规则,放到计费策略里。这引出了一个问题,我应该把哪些规则算作计费规则,哪些放在计费策略里,还有些规则应该放在?我还没想好。我还是先将这些规则分一下类吧:
      1)确定费率的规则 。前面说了,费率是根据规则动态确定的。这个很平常,就是If Then规则。
比如:If 重量<100,长度<12,交货条款=FO,作业方式=卸船入库装火车 Then 费率=34.33。这条规则包含了几个问题,当If中出现重量,长度,交货条款,作业方式时,我需要调用相应的方法(Method)去获得相应的值;然后,我才能将这个值与规则中的值去匹配。
再进一步抽象,我首先需要知道规则中的匹配项(Matching Item)是什么,然后每个匹配项都有自己的去寻找数据的方法,和如何与该项匹配的方法。那么,可以这样设计,每个Rule,都有一个 MatchingItem列表,每个MatchingItem都引用一个RetrieveMatchingItemDataStrategy,和一个 Matching Rule方法。Matching Rule方法应该有很多不同的实现,现在能想到的是三类,第一类是按范围(Range)匹配,比如重量,长度之类的;一类是按值比较,比如作业方式,交货条款;还有一类是按Boolean值匹配。
If后面的东东在IBM WID中叫做Expression,我想在这里使用它很合适,可以设计一个ConditionExpression接口,然后MatchingItem是它的实现,这里可以运用组合模式。我从合同中取得某个费目的确定费率的规则列表,然后放入 ConditionExpression中,系统就可以自己去识别其中的匹配项,然后根据匹配项取数并进行匹配,以返回True或者False。然后将规则中的费率放入到一个叫Result的对象中。这样看,一条规则=ConditionExpression+Result,也就是一个Rule对象包含一个实现了ConditionExpression接口的ConditionExpression对象,和一个Result对象。ConditionExpression对象由很多实现了ConditionExpression接口的对象组合而成。然后Rule有一个方法是读取合同中的规则,并将ConditionExpression和Result分离开。
          2) 确定折扣或加倍的规则。 If 两港作业=true Then discount=0.8。
          3) 确定费用结果的规则。 比如计费结果保留位数的规则(即精确到元?角?分,或者说小数点位后几位,从扩展性的角度去考虑,显然按小数点保留比较合理,因为如果换算成美元的话,难道还有美角?)写到这,想起来,在WID中,Then后面的地方也叫Expression,可以说是结果表达式,在这里可以定义要对这个结果进行怎样的处理。不过它与刚才说的ConditonExpression有什么共性吗?似乎没有,继承关系不能乱用啊~~我们还是把这个也算作 If Then规则就好了~~
           4)确定计费吨的规则。 计费吨包含两个方面,一个是单位,是按体积,重量还是件数,一个是数据来源,包括理货单,提单和商检数。每个规则,都要对应一个方法。比如获得理货单数,当然不是简简单单的去那取个数就搞定的。其实这个规则对于确定费率的规则是有影响的。比如在确定费率的规则中规定了不同重量范围,这时,就要根据计费吨的规则了解到底是去取哪个重量,商检数?理货单数?还是提单数。

          刚瞅了一眼JBoss Rules,其实也一样,规则这东西,在这个层面上都可以归结为If Then,等等,慢着,似乎不准确,计算公式算规则吗?If A+B+C Then Sum=?还是不去论述这个问题了。
好,回到前面,我想说的是,在计费那个公式里,费率和计费吨,都是基于一定的规则确定的,然后为了满足这个规则,都要做这么两件事,一件是找到想要知道是否满足规则而必须的获得的数据,一件是获得数据后如何去跟规则匹配。

         在合同中还规定了,费用在该合同中对应的规则列表。因此每个费用(Charges)都应该引用一个规则列表。然后,我们还可以给规则分类,就按上面的四个方面来进行分类。意味着,有四个大的规则实现类。

         我想可以在Charges的计费策略里,确定Charges引用的规则列表,即charges.setRuleList(List<Rule> ruleList)。

         Charges里还会有个方法叫做计算费用,哦,就是调用计费策略的计算费用的一系列方法。当然,Charges里一定会有个方法是setChargeStratege。

        6 组合费目。 这里面是指包干费,包干费就是包含了其他费目的费目,那么这正好应该使用包干费。问题的关键是建立Composite FeeItem还是Composite Charges?后者更准确吧。因为FeeItem在这里只是个Product。

        7 客户端。 我想象中的计费应该是这样的,从Bill中取出要计算的Charges,然后统一调用其calculate方法,就可以什么都不管了,它就会超级智能的计算。然后每一点改动,都只是去改动上面所讨论的抽象的一个实现类。我尽量设计出符合OCP的系统 ,这个想法还是不连贯。我或许应该画些类图。

                我所能想到的计费的抽象大概就是这些了,他们应该是比较稳定而且独立的,不过这个想法还相当初级。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值