论坛首页 Java企业应用论坛

用“主线+事件”的方式来编写代码

浏览 7197 次
精华帖 (0) :: 良好帖 (3) :: 新手帖 (1) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-06-26   最后修改:2011-06-26

      业务是主线和事件组合。

      主线是什么?主线就是在完成用户的业务目标时,所涉及到的活动。

      事件是什么?在每一个活动中,相关事物的状态变化。

 

      回顾以前的编程经验,我们关注活动,忽略事件。

      举一个常见的例子来说。小明在购物网站购物,进行支付并成功后,购物网站要做件事: 1 、更新订单状态, 2 、插入支付记录 3 、更新订单日志。 4 、通知支付系统,回调成功。

 

通常的做法如下:

    public void successToPay(PurchaseOrder order,PayResult result){
        //1、更改支付状态
     order.setPayStatus(PayStatus.SUCCESS);
        orderRepository.save(order);

        //2、插入支付记录
     PayRecord record= RecordFactory.getSuccessRecord(order,result);
        recordRepository.insert(record);

        //3、插入订单日志
     OrderLog log = OrderFactory.getPaidLog(order);
        logRepository.insert(log);

        //4、通知财务系统,支付成功
     NotifyLog notifylog= NotifyFacotry.getSuccessNotify(order);
        nofifyService.notify(notifylog);

    }

    上述做法没有合适的关注点,无法把主线找到,随着随着业务扩大,修改代码是一件高风险的事情。

 

    换另一种方式来处理这些问题。

    1、发现该业务的主线。

    2、分析主线中的每一个活动会给系统带来什么变化。而这些变化就是主线所要传递的消息。

    3、把事件通知给相关对象。

 

    以上述例子为例

    可以得知 【更新订单状态】和【插入支付记录】是整个业务的主线。 【更新订单日志】和【通知支付系统,回到成功】是由于订单支付成功而引发的。

    因此在代码实现中,可以这样写

public class PurchaseOrder {

    public void notifyOrderPaid(List<OrderListener> listeners){
        for(OrderListener listener:listeners){
            listener.onOrderSuccessPaid(listener);
        }
    }
}

public  interface OrderListener{

    public void onOrderSuccessPaid(PurchaseOrder order);
}

public class LogListener implements OrderListener{
    private  LogRepository logRepository;
    public void onOrderSuccessPaid(PurchaseOrder order){
        Log log = OrderFactory.getPaidLog(order);
        logRepository.insert(log);
    }
}
public class FinanceListener  implements  OrderListener{
    private FinanceService financeService;
    public void onOrderSuccessPaid(PurchaseOrder order){
        NotifyLog notifylog= NotifyFacotry.getSuccessNotify(order);
        nofifyService.notify(notifylog);
    }
}
public class OrderService{
      public void successToPay(PurchaseOrder order,PayResult result){
         //主线          

      order.setPayStatus(PayStatus.SUCCESS);
         orderRepository.save(order);
         PayRecord record = RecordFactory.getSuccessPaidRecord(order,result);
         payRecordRepository.sae(record);

         //事件
      List<OrderListener> listeners =new ArrayList<OrderListener>();
         listeners.add(new FinanceListener());
         listeners.add(new LogListener());
         order.notifyOrderPaid(listeners);
      }
}

 

   一旦有新的业务增加时,应该考虑到它是属于主线,还是属于事件。我们的代码就不容易走向混乱。

 

 

 

   发表时间:2011-06-26   最后修改:2011-06-26
如果所谓的“事件”中的异常能影响主线是否回滚的话,该如何清晰的处理?

如果“事件”用异步方式来做,这种情况又该如何处理
0 请登录后投票
   发表时间:2011-06-27  
同步事件:
    现阶段的Web请求都是基于Request/Response的方式,一次响应对应一个线程,利用Spring的OpenSessionInView,可以 保证 一个线程只有一个数据库连接。不管是【主线】还是【事件】都用同样的数据库连接,事务也会得到统一的控制。

异步事件:
    我还没有特别关注,但是曾经看奥金蝶的Apusic OperaMasks中有关异步事件的案例http://infocenter.apusic.com/help/index.jsp?topic=/operamasks-sdk/output/eclipse/message_bus.html。
    你可以查看下:)
0 请登录后投票
   发表时间:2011-06-27   最后修改:2011-06-27
如果 “主线”和“事件”是必然存在的一种业务关系。例如业务上发生主线,必然会触发事件。那你在设计domain的时候就应该将事件的动作封装到对应的save动作上。
这样,对与Action使用来说都只关系你的save动作。事件动作只不过是domain service中的某段业务代码,这时候在service内部你可以随意设计

如果你所谓的“主线”和“事件”不满足必然的关系,你搞这个就是搬起石头砸自己的脚,过度设计的一种
0 请登录后投票
   发表时间:2011-06-28  
通常的做法如下
所有人都看得懂
一看就知道系统做了啥.
Listener 看不懂.没办法.
Listener 和 通常做法区别在于:
主线和Listener是否是一个人去写;
如果2个人去写,用Listener,业务代码隔离.
一个人去写,还是通常做法,别人读得懂
0 请登录后投票
   发表时间:2011-06-28  
处理一般的业务逻辑可能会有先后顺序,你通过add Listener的先后顺序来控制Listener处理事件,我觉得不符合事件驱动模型。
0 请登录后投票
   发表时间:2011-06-28  
observer
0 请登录后投票
   发表时间:2011-06-28  

1、业务上发生主线,必然会触发事件。但是事件响应方没有必然的联系。比如iphone4上市,有人会抢购,有人无所谓,但这些都不应影响iphone上市这个主线。

2、add Listener(),并不是用来控制循序。而是把【对OrderPaid事件感兴趣的listener】添加PurchaseOrder ,以便于通知



0 请登录后投票
   发表时间:2011-06-28  
也只是玩玩,没什么实际价值,如果所有业务这么来写,那才叫混乱,不说别的,这样会难以理解,也不好调试等等
0 请登录后投票
   发表时间:2011-06-28  
sing100star 写道


2、add Listener(),并不是用来控制循序。而是把【对OrderPaid事件感兴趣的listener】添加PurchaseOrder ,以便于通知




既然不控制执行顺序,你能确保你的业务逻辑里没有这样的需求?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics