进来博客堂关于SOA的文章不少,呵呵,看来SOA进入大家的实际项目可能是指日可待啊。
因为SOA绝不是一种标准,而且也是刚刚发展推广开的一种架构,所以在网上对于一些细节(也许下面罗列的已经算不得是细节了)的地方, 各有各的看法,各有各的理由。
一、Service Façade公开Entity还是公开Argument?
比如,应该是这样:
CustomerService.AddCustomer ( CustomerInfo customer )
还是:
CustomerService.AddCustomer ( String name, String zipcode, Int32 level )
首先看张图,http://bbs.dotnettools.org/upload/1308-Architecture%20Design.jpg(此图取自.NET Tools评测网论坛redmoon的一个介绍产品架构的帖子,同时推荐大家可以去论坛看看redmoon、ccboy、jjx、JGTM2004关于SOA的精彩发言)。
从这张图可以看到,由Typed DataSet实现的Entity横跨了整个系统(也就是在整个系统间传递了,就像是我以前的那篇文章上所说的,DTO在模块间流动),甚至通过Service的边界传递给了Service Customer。如果你的整个系统都是.NET,并且能够把包含了Entity的Assembly部署到系统的各个模块(所以建议将系统中用到的所有Entity单独放在一个项目中,并被其他所有的项目引用),这样做绝对是简洁、明了、高效的选择。
但很多人会不同意这样(我估计JGTM2004会不同意,基于他发出的帖子所表达的观点来判断)。因为很多人认为作为一个独立的、自维护的、解耦的Service来说,你公开一个你自己才明白的Entity,别人(就是Service消费者了)根本不懂,何况说不定一个Java系统以后也想要调用这个Service呢。所以,很多人都说,“Services expose Schema and Contract, not Class and Type”,就是说,Service与Service之间要传递中立的,有良好Schema定义的Message。
再反过来说:好像是在今年二月份的《程序员》杂志上,有一篇文章讲到一个失败的案例,其中有一点就是各个模块间的调用都是通过参数,而不是Entity,结果后期客户增加了一个字段信息,所牵涉的要更改的地方非常之多(因为模块接口都要改),所以那篇文章的作者认为,为了能够在对象结构变化的情况下,接口相对固定,模块接口参数一定要是一个Class。
二、Entity自己维护相互的Relations吗?
比如,CustomerInfo这个纯数据Entity是否应该包含OrderInfo的集合(提供一个Orders属性来公开),同时OrderInfo包含一个CustomerInfo的引用(提供一个Customer属性)?
包含?那么当Service Customer向Service请求一个CustomerInfo时,其对应的OrderInfo集合也被自动同时从数据库中取出来,并打包到CustomerInfo一起传回来?还是用类似Lazy-Loading之类的方法先不取回来?一起传回来在某些场合是明显的浪费。哇,好像真是头疼的选择。
Lazy-Loading在SOA中应用可不是件简单的事。比如客户端请求一个OrderInfo,然后引用其Customer属性,Service用Lazy-Loading来载入正确的CustomerInfo对象并返回,然后客户端再引用这个CustomerInfo对象的Orders属性,这时Service应该能够正确判断出哪些Order已经被载入了而可以从缓存中直接取,哪些没有载入而需要从数据库中取…ORM可能是个不错的选择。
如果干脆让Entity不自己维护其Relations关系,那么客户端就要像这样调用Service了:
CustomerInfo customer = CustomerService.GetCustomer( “kaneboy” );
// …
OrderInfoCollection orders = CustomerService.GetOrders ( customer.Name );
// …
CustomerService.UpdateCustomer( customer );
CustomerService.UpdateOrder( orders[0] );
重复向Service请求,由知道其关系的Service来处理。而且客户端代码可麻烦了,因为CustomerInfo和OrderInfo“实际上”不知道他们之间有什么关系,在需要根据其Relations进行某些处理时,就需要代码来手工处理了。
好像文章没有做出一个结论,因为本身就无法做一个“绝对”正确的选择。我个人更喜欢Service公开Entity和Entity自己维护其Relations,但是,“Do right things in right place”,呵呵。
附注:第二点很多想法来自Udi Dahan - The Software Simplist