应用和Framework最大的不同在于写Framework都是你在提要求,应用中则有那些让你猛然一惊的需求,即所谓“业务特点”,你还真都得去满足。比如下面这个:
对于系统里的重要对象,要能够看删除记录,知道是谁删的,删了什么。
设系统中有一个Order对象
class Order {
long oid;
String orderNo;
List<OrderItem> items;
User creator;
Date createTime;
// ... getter, setter
}
这个需求是说,为避免纠纷,对于被删除的Order,要能够根据orderNo,删除时间等作查询,并能够查看Order被删除时的样子。一般这种功能不会开放给用户,但后台管理总会有这样的需要。
好了,问题清楚了。那么我们该怎么作呢?
第一种方法最直接。假设Order和OrderItem分别存在 m_order表和m_order_item中,这种方法需要建立b_order和b_order_item表,并为需要删除的Order和OrderItem各创建一个子类
class DeletedItem extends Item{
};
class DeletedOrder extends Order{
private List<DeletedItem> items;
@Override
public List<Item> getItems{
return this.items;
}
}
这样, Service在删除一个Order对象时,只需要new 并register 一个DeletedOrder就好了
void deleteOrder(Order order){
DeletedOrder delOrder=new DeletedOrder();
delOrder=getBaseDto.register(delOrder);
delOrder.setOrderNo(order.getOrderNo());
// ... deep clone order to delOrder;
}
这种方案,对于DeletedOrder采用了单独一张表,查询也没有问题。
那么,这个方案的可行性怎么样呢?不怎么样!
1)DeletedOrder映射为一张物理表的方案,意味着对N个要查询删除的对象,系统中要建立N张表,这有很大的维护开销。如果以后Order结构变化,则m_order和b_order表都要按照相同的schema更改,开销更大。为这么点破事就搞出这么多表来,这种设计太重。
2)假设系统中有N种要查询删除的对象,这个方法需要service写N段分散的代码。想要知道一个对象是否会被备份,只有一个个查看引用,这种设计不符合开闭原则。
针对以上两个缺点,一个最终的方案应该包括以下两个特点
1)最好数据库中一张表能搞定
2)对于Service层透明,维护时要阅读和修改的代码尽量少,责任明确。