代码改变世界

【讨论】服务层(Service)的功能参数列表的粒度

2011-06-12 11:19  bugfly  阅读(2002)  评论(8编辑  收藏  举报

我们一般在设计服务层的时候总会有这种情况,究竟参数列表是简单类型还是对象类型?

首先我们从比较常见的场景入手,修改订单。这里我们先不考虑它是否应该归属于领域对象。

根据场景很自然就能提炼出一个功能:EditOrder(XXX),我们开始看看参数列表的写法的种类。我大概想到3种。

1.void EditOrder(string orderName,string orderText,float Money);

2.void EditOrder(Order order);

3.void EditOrder(OrderDTO dto);

先看看我对这三种设计的见解。

第一种:很直观,也是最早被我们使用的方式,但这种设计有很多弊端。

1)容易造成参数组合爆炸,因为对象的属性有很多,一个参数组合列表不定,两个参数组合列表不定,三个四个组合列表等等若此类推,理论上有人脑处理不能的组合,也就是很难适应变化,你只能不断地加入重载功能到服务层接口里面,并且会出现很多类似的代码段,果断后期悲剧。

2)使用简单类型作为参数列表,在一定数量级的情况下,会出现重载冲突,如

void EditOrder(string orderName,string orderText,float Money);

void EditOrder(string orderNumber,string orderTitle,float Money);

显然这个重载方法会有编译错误,为了迎合这种需求,你只能通过修改方法名字来满足,十分别扭。

第二种:直接使用领域对象作为数据载体,好处是能够适应所有围绕领域模型的需求变化,解决了第一种情况不断重载的局面,也随理成章地解决了重载冲突的局面。然而这里存在一些弊端。

1)由于数据载体是一个领域对象,调用端传送回来的数据可能只有几个属性,也就是很可能存在大量的null值和默认值的属性,面对这种情况,我们要在功能实现里面对对象属性进行筛选验证,当然只有几个属性这不能当一回事,但领域对象大起上来,有几十个属性或以上,这部分工作就变得痛苦起来了。

第三种:使用DTO代替领域对象作为数据载体,其实我也用过这种做法,但我找不到其好处,引用别人的观点就是,隔离了领域对象对UI的影响,安全性得到保证,从我的实践经验来看,确实是把领域对象隔离出UI,但换来的是大量的DTO管理和适配问题,这些问题比维护问题还头痛,如果是单纯从分布式的角度来解决问题,结合第二种和第三种做法可以产生一变种,前端返回给后台的数据载体用领域对象,而前端接收的数据载体用DTO。

结论:第二种做法是暂时面对非分布式开发是下比较好的做法,但总感觉有点别扭,所以把问题拿出来,集思广益!希望大家积极参与!我相信你们的经验中一定有更好的解决办法。