精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2005-03-17
partech 写道 想告诉我什么?是支持我的观点还是反对我的观点? 业务逻辑就应该放在Domain Model中实现,不存在尽可能的问题。 薄不薄是最后看起来的效果,不是对设计的要求。 服务层负责协调应用请求到Domain Model的映射,只是工作量不大,所以觉得薄。 partech 写道 嗯,如果你所写的方法是在Customer中,那么恭喜你,你会后很多机会来重构Customer,因为客户签订的协议会与日俱增。 Customer是很底层的业务对象,不要老是去变动它! 这个变动是谁导致的,属于业务变动吗? partech 写道 业务层对象的结构是有可能重构的,比如客户状态的实现。 最初比较简单,设计的结果就是在Customer中添加一个LostReportFlag字段。 public class Customer { ... private boolean lostReportFlag;//挂失标志 ... } 后来发现挂失其实是一种协议,这样需要把它挪出Customer。另外建立一个 协议。 public class LostReportAgreement { ... private Customer customer; private Date createDate; private Date fromDate; private Date toDate; private String remark; ... } 这样原来获取客户状态的getStatus方法就不能放到Customer中了。 直接传递PO意味着客户端也需要做相应的变更。 为什么不能放在Customer中了? |
|
返回顶楼 | |
发表时间:2005-03-17
To All
我没有实际使用过DTO和ViewObject, 不是很清楚比较好的实践做法是如何, 在此想请教一下大家: 有这样的模型: 一个人(Person)属于某个公司(Company), 这个人有联系地址(Address) 那么如果我传递给Remote Client显示的话, 是否需要根据显示内容的不同, 而构建多种View Object? 比如显示Person的名字和他所在公司的名字, 那么就要构建一个PersonCompanyViewObject: 然后在client调用: PersonCompanyViewObject.personName, PersonCompanyViewObject.companyName 如果还需要显示Person的名字和他的联系地址, 那么还得另外构建一个PersonAddressViewObject: 在client调用: PersonAddressViewObject.personName, PersonAddressViewObject.addressZipCode 假如我能够把Person这个对象直接传递到client的话, 我可以利用对象关系, 直接写: Person.name, Person.company.name 和Person.name, Person.address.zipCode 不知道我理解得是否正确? To jackyz 我觉得透明的分布式lazy load是可行的, 考虑利用net.sf.hibernate.Interceptor的onLoad方法, 对于每个被Hibernate load的对象加上代理(可以用CGLIB),代理它所有getLazyCollection类型的方法, 让这个proxy remote invoke server的某个指定方法: session.refresh(proxy, LockMode.NONE);; Hibernate.initialize(proxy.getLazyCollection(););; 这样对于客户端就是透明的了, 你怎样看待这种做法? |
|
返回顶楼 | |
发表时间:2005-03-17
pufan 写道 domain model即不属于后台也不属于前台,domain model的设计是在各层划分前实现的,也就是说当domain model的接口确定下来l时系统的层次尚未划分(可能是bs,可能cs,可能是三层也可能是n层),domain model 是在各层之上的,应该贯穿于各层之间。
我的想法就是这样的,各个层次上的DomainObject都是一样的,可能他们在各层的具体实现并不一样.但接口一样就行. partech 写道 Service层负责实现Service层的接口,它当然要输出VO(Value Ojbect -- 不知道你的ViewObject是什么东东?)给应用层用。
Service层负责实现Service层的接口,但它的输出格式为什么就天经地义的必须是VO(Value Ojbect)呢? 如果传输方面代价不高,应用层为什么不可以得到一个DomainObject来用呢?或者说,传过来的VO为什么不能包装(适配)成为一个DomainObject来供应用层使用呢?----这么做显而易见的好处就是屏蔽了VO带来的限制. 当然,要满足这样的条件,VO显然已经不能是之前提到的"经过特定裁减的扁平的传输对象". 关于ViewObject请看前面这一句: jackyz 写道 DTO中所传递的东西其实就是显示中要用到的数据,我认为它就是ViewObject(实际上ViewObject也受限于DTO所定义的方法).比较两者,区别在于DTO是将DomainObject->ViewObject的Mapping放在Service端,而非DTO将这个过程放在Client端.
或者说,ViewObject是view层Model的"数据部分". partech 写道 Service层对应用层的功能不可知,那它是为谁服务呢?如果你说的是特定的应用层,那么确实Service层对它一无所知。Service层对可能的所有应用提供统一的服务接口。
partech 写道 Web客户端和Rich客户端我认为某些VO确实是可以复用的,特别当你在把他们统一考虑的时候。
我说的就是"特定的应用层","Service层对可能的所有应用提供统一的服务接口".在这一点上,我们的看法相同.但我认为,比较理想的情况是"所传递的对象"到了应用层能被"还原(或者模拟)"出一个实现DomainObject接口的对象.那么,在"对于所有的应用提供统一的服务接口"这个目标上,要做得更彻底一些. 即使这里在传输上的确是存在着一个DTO层,但我们也可以将它作为一个实现来隐藏,对调用者(应用层代码)屏蔽它的存在,而在客户端提供一个使用统一DomainObject接口的实现. |
|
返回顶楼 | |
发表时间:2005-03-17
youcai 写道 partech 写道 想告诉我什么?是支持我的观点还是反对我的观点? 业务逻辑就应该放在Domain Model中实现,不存在尽可能的问题。 薄不薄是最后看起来的效果,不是对设计的要求。 服务层负责协调应用请求到Domain Model的映射,只是工作量不大,所以觉得薄。 partech 写道 嗯,如果你所写的方法是在Customer中,那么恭喜你,你会后很多机会来重构Customer,因为客户签订的协议会与日俱增。 Customer是很底层的业务对象,不要老是去变动它! 这个变动是谁导致的,属于业务变动吗? partech 写道 业务层对象的结构是有可能重构的,比如客户状态的实现。 最初比较简单,设计的结果就是在Customer中添加一个LostReportFlag字段。 public class Customer { ... private boolean lostReportFlag;//挂失标志 ... } 后来发现挂失其实是一种协议,这样需要把它挪出Customer。另外建立一个 协议。 public class LostReportAgreement { ... private Customer customer; private Date createDate; private Date fromDate; private Date toDate; private String remark; ... } 这样原来获取客户状态的getStatus方法就不能放到Customer中了。 直接传递PO意味着客户端也需要做相应的变更。 为什么不能放在Customer中了? java代码: public class CustomerModel { ... public boolean lostReport; //挂失标志 public void onInit() { Customer c = service.getCustomer(); lostReport = getLostReportFlag(c); } // 增加新的转换方法 private boolean getLostReportFlag(Customer c) { Date sysDate = new Date(); LostReportArgreement lra = c.getLostReportAgreement(); //上面c.getLostReportAgreement的设计是有问题的 //因为客户可能会有很多种协议,如果都通过c.getXXXAgreement的方式取得的话。 //因为Customer同协议是使用关系,也就是说是Customer依赖于这些协议,、 //这样稳定的对象就依赖上不稳定的对象了,新的协议会层出不穷。 //这是很大的问题,依赖应该朝着稳定的方向去做而不是相反。 //所以即Ê挂ª做也该是下面这样: // //LostReportArgreement lostReportAgreement = LostReportArgreementRepository.findbyCustomer(c); // //Customer对象无论如何都不应当知道直接签订了多少的协议。 // if (sysDate.after(lra.getFromDate()) && sysDate.before(lra.getToDate())) { return true; } else { return false; } } ... } |
|
返回顶楼 | |
发表时间:2005-03-17
Quake Wang 写道 To All
我没有实际使用过DTO和ViewObject, 不是很清楚比较好的实践做法是如何, 在此想请教一下大家: 有这样的模型: 一个人(Person)属于某个公司(Company), 这个人有联系地址(Address) 那么如果我传递给Remote Client显示的话, 是否需要根据显示内容的不同, 而构建多种View Object? 比如显示Person的名字和他所在公司的名字, 那么就要构建一个PersonCompanyViewObject: 然后在client调用: PersonCompanyViewObject.personName, PersonCompanyViewObject.companyName 如果还需要显示Person的名字和他的联系地址, 那么还得另外构建一个PersonAddressViewObject: 在client调用: PersonAddressViewObject.personName, PersonAddressViewObject.addressZipCode 假如我能够把Person这个对象直接传递到client的话, 我可以利用对象关系, 直接写: Person.name, Person.company.name 和Person.name, Person.address.zipCode 不知道我理解得是否正确? 基本上是这样的,但是ValueObject的名称不是那样的,因为你写的这些名称。 隐含的意味着Client知道Domain Model的结构。 之所以会有不同的ValueObject的需要,那一定是在业务上的目的不同。 最好根据不同的目的来命名ValueObject,比如PersonInCompanyInfo。 PersonPrivateInfo等等。 对于前台开发人员来说它确实是不同的概念。对于用户来说也是这样的。 从客户和前台的观点来看,它们是交互的输入输出对象。而不是复杂的DomainObject结构。 |
|
返回顶楼 | |
发表时间:2005-03-17
Quake Wang 写道 To All
我没有实际使用过DTO和ViewObject, 不是很清楚比较好的实践做法是如何, 在此想请教一下大家: 有这样的模型: 一个人(Person)属于某个公司(Company), 这个人有联系地址(Address) 那么如果我传递给Remote Client显示的话, 是否需要根据显示内容的不同, 而构建多种View Object? 比如显示Person的名字和他所在公司的名字, 那么就要构建一个PersonCompanyViewObject: 然后在client调用: PersonCompanyViewObject.personName, PersonCompanyViewObject.companyName 如果还需要显示Person的名字和他的联系地址, 那么还得另外构建一个PersonAddressViewObject: 在client调用: PersonAddressViewObject.personName, PersonAddressViewObject.addressZipCode 假如我能够把Person这个对象直接传递到client的话, 我可以利用对象关系, 直接写: Person.name, Person.company.name 和Person.name, Person.address.zipCode 不知道我理解得是否正确? To jackyz 我觉得透明的分布式lazy load是可行的, 考虑利用net.sf.hibernate.Interceptor的onLoad方法, 对于每个被Hibernate load的对象加上代理(可以用CGLIB),代理它所有getLazyCollection类型的方法, 让这个proxy remote invoke server的某个指定方法: session.refresh(proxy, LockMode.NONE);; Hibernate.initialize(proxy.getLazyCollection(););; 这样对于客户端就是透明的了, 你怎样看待这种做法? 我们的看法一致. 我想尽量避免的就是前面的做法而采用后面的"利用对象关系"的方式. 那么,最适合的DTO粒度就是Hibernate没有LazyLoad之前的内部对象. 这样的话,问题就变成如何在PO上加入透明的RPC机制了. |
|
返回顶楼 | |
发表时间:2005-03-17
to partech,
如果Customer对象无论如何都不应当知道直接签订了多少的协议。那么客户状态会和谁有关? 只要明确这个状态就是Customer的,那么Customer.getStatus();是最自然不过的表达.至于具体的实现如何获得状态,那就跟据实际情况做吗. |
|
返回顶楼 | |
发表时间:2005-03-17
jackyz 写道 Service层负责实现Service层的接口,但它的输出格式为什么就天经地义的必须是VO(Value Ojbect)呢?
如果传输方面代价不高,应用层为什么不可以得到一个DomainObject来用呢?或者说,传过来的VO为什么不能包装(适配)成为一个DomainObject来供应用层使用呢?----这么做显而易见的好处就是屏蔽了VO带来的限制. 那么请问你在什么时候才能定义出这服务接口呢? 如果按照你的设计,必须要等到DomainObject都稳定后,该接口才能定义出来。 但是你的DomainObject的设计又依赖于它使用的情况(也就是服务接口提供的功能),这样你的DomainObject同服务接口就双向依赖了,你会先处理哪一个呢?你如何处理这种问题? 或者,你会采用交替的方式开发两者,那么你就会频繁的重构接口,因为你会不断地 重构DomainObject。 |
|
返回顶楼 | |
发表时间:2005-03-17
Quake Wang 写道 假如我能够把Person这个对象直接传递到client的话, 我可以利用对象关系, 直接写: Person.name, Person.company.name 和Person.name, Person.address.zipCode 不知道我理解得是否正确? 同意这种,对于数据结构近似的地方尽量采用一个dto,真有特殊的时候,再考虑增加新的dto.结果会类似于domain model,但应更简单和直接. 这里没有明确的标准,需要自己把握. |
|
返回顶楼 | |
发表时间:2005-03-17
youcai 写道 to partech,
如果Customer对象无论如何都不应当知道直接签订了多少的协议。那么客户状态会和谁有关? 只要明确这个状态就是Customer的,那么Customer.getStatus();是最自然不过的表达.至于具体的实现如何获得状态,那就跟据实际情况做吗. 是的是和客户相关,但是Customer对象确实是不知道任何一个协议的,协议自己 知道自己属于那个客户。在这里强制了一个关联方向即协议 ---〉客户。 现实中的关联都是双向的,但在程序里我们可以将它实现为单向的。 |
|
返回顶楼 | |