Johnny's Collections

生活总是有太多的无奈与失望,让我们以在努力学习和工作中获得的成就感和快乐来冲淡它们。

BlogJava 首页 新随笔 联系 聚合 管理
  10 Posts :: 0 Stories :: 80 Comments :: 0 Trackbacks

我的评论

@isnumeric
PO应该是我系列博文所说的DTO,它是实体的信息封装对象,本质上与“实体的查询信息封装对象”是不同的,因此最好提供一个Criteria来封装查询属性。

HQL绝对不能封装在Service中,因为HQL涉及数据访问逻辑,应该封装在数据访问层中,业务层可以传入生成HQL的相关数据,由DAO把这些数据转换为HQL,但Service绝对不要传入任何与数据访问实现细节有关的数据,否则Service就被耦合了。
@DDD
对,但页面查询用的VO,与表示某个实体的VO不是同一样东西,如果按我的博文中合并VO与DTO的说法,举个例子,User,对应的信息DTO应该是UserInfo,而对应的查询User的DTO应该是另外一个,通常我用UserSearchCriteria来代替,为什么要把UserInfo和UserSearchCriteria区分开来?你可能认为,UserInfo中大部分属性,都是可以用于查询的,所以没必要弄多一个UserSearchCriteria,但事实上,它们本质上是两样东西来的,比如,UserInfo有一个birthday的属性,但对于查询来说,系统可能要求查询某个时间段内出生的User,这个时候,UserSearchCirteria就要定义两个属性birthdayFrom,birthdayTo了,所以可以看出,两者只是“表面上相似”,本质上是两样东西,为了设计上的灵活性和扩展性,即使当前情况下两者的属性一致,也需要分别进行设计。
@Aidan
联系方式已经发到你的邮箱,请查收
@Aidan
呵呵,谢谢你的持续关注,你这个问题同样很好,我也曾经被这个问题困扰,你所说的从构造函数传入,从技术角度来讲,是一种可行的办法,但我不建议这样做,原因是:
1)DO(即你所说的BO)从业务上来讲,不应该与DAO有关联,因为DAO对于业务来说是没有意义的,它属于应用方面的东西。DO构造函数只能包括用于构造它的所必须的元素(我后面的博文会提及)。
2)这样做会让DO与你的具体实现耦合,试想,如果某天有某种更好的方法让你动态注入DAO,意味着你不再需要通过构造函数传入DAO了,那么你是继续保留这个参数,还是修改构造函数,从而让所有调用该构造函数的客户程序受到影响呢?

事实上,可行的做法有两种:
1)利用Spring提供的“动态注入”方式,这种方式的原理是,通过一个Annotation,告诉Spring容器,这个DO是需要注入对象的,即需要受到SpringIoC容器管理,那么Spring就会利用“编译时织入”或“启动时织入”的技术来为DO的Class类织入注入相关对象的代码,这种技术依赖于AspectJ,前者更加需要在编译环境加入AspectJ的增量编译器,这种方案是相对麻烦的,而且我曾经在OSGi中应用,会出现一些不可预知的问题导致无法注入。

2)在你的应用(通常是Web应用)加载SpringContext的时候,设计一个用于保持SpringContext的ContextHolder,利用某种机制(例如Spring提供的Servlet)来在加载SpringContext的时候,把SpringContext的引用保留在该ContextHolder中,然后在你的DO里面,就可以在实现代码里面通过ContextHolder提供的静态方法,获取到你所需要的Bean了。
@Aidan
很好的问题,我逐个回答:
1.我所说的不需要password,是值在DTO层面,同一个UserInfo(我在一篇博文中建议以***Info命名DTO,意为***信息),其实对于不同的场景,本质上是不同的,例如,我有个注册用户的方法,需要传入UserInfo,那么逐个DTO必须拥有一些用户认证或隐私信息的属性,但对于查询用户的方法,它返回的也是一个UserInfo,但这个UserInfo,从需求来说,它不应该包含密码和隐私信息,那么这两个虽然都是UserInfo,但理论上应该定义为两个独立的DTO,但实际上,这样做带来的负面影响会更大,因为我在一个系统中可能要为一个实体定义太多的DTO,所以我建议定义一个包罗万有的DTO,但在返回数据时,如果有些数据不应该返回,就把属性设置为null即可,当然SOA中的SDO有另外的做法,这里不详说,本人也不甚精通。

2.对于VO,DTO,DO,PO的命名,我个人的建议(纯属个人意见),还是不要太过技术化,VO可以叫***View,代表一个”视图“,DTO用***Info,代表”***的信息“,DO由于是就是业务实体本身,所以直接给它一个释意名称,如User、Customer……,至于PO,正如我所说,现在的ORM框架已经可以把这个东西在实现层面通过配置文件(xml)或annonation隐藏起来,所以在实现层面基本不需要存在,如果确实需要的话,我觉得”持久化“本身就是计算机世界的一个非业务领域,这里用技术化命名完全没有问题,因为它确实是”技术化产物“,在业务领域没有这个概念。这相信也同样回答了你在另外一篇博文提出的问题。

希望我的回答能让你满意。
@潇湘振宇

支持原创
@菠萝大象
Jdon框架采用DDD了么?没有关注,不过个人觉得不解,DDD主要是针对企业应用的,一个纯技术框架,为什么要使用DDD。
re: 开放平台两三点感悟 Johnny.Liang 2010-05-29 00:26  
谢谢楼主,很不错,希望多一些这类文章。
@spell007
您好,这个问题问得非常好,我之前在应用DDD做一个项目的时候,就跟项目成员做过讨论,我们发现,DO和Repository(即DAO,我习惯用非技术化命名来让思维集中与业务而不是技术)两者是双向依赖的。原因是:
1)Repository必须依赖DO,因为它要知道DO的数据结构,这无可厚非。
2)为什么DO需要依赖于Repository呢?从实现角度来说,我的账户转账业务就可以看出这种依赖的存在,另外有些场景,比如有些领域业务逻辑需要查询一些数据,例如一个Order最多允许10个OrderItem,那么在order.addOrderItem的方法里面,就需要判断当前Order有多少个OrderItem,这就需要查询(为了性能不全部加在OrderItem),从设计角度来看,我们想想,在计算机世界,由于DO在大部分情况下是必须持久化的,所以DO从功能上本身就对其Repository存在依赖关系,当然,我们可以只依赖于接口,所以,基于 种种原因,我们不得不让DO与Repository形成双向依赖关系。

这个问题值得详细讨论,我会考虑在后面的系列博文增加一篇专门针对这个问题进行分析讨论,非常感谢你提出这样好的问题。
从设计的角度来看,通过了解一些底层机制,绕过OSGi的类加载策略来直接访问不对外公开的类,不见得是一件好的事情,作为技术研究,了解这些底层机制有助于更熟悉一个框架,以更灵活的运用它,但作为软件开发,这些做法可能会导致很多隐患和风险,个人认为不值得推崇。
@何杨
工具有很多,我用的是Enterprise Architecture试用版,还可以用Jude等。
re: Java RMI 入门指南 Johnny.Liang 2010-05-15 00:14  
期待你的下一篇博文,特别是关于OSGi,缓存技术的博文
re: “设计”你的代码 Johnny.Liang 2010-04-30 17:50  
@onkyo
明白你的意思,谢谢你的意见,我往后会发表一些针对如何使用面向对象思维进行设计,及其真正的好处的博文,当中就会详细的说明使用面向对象思维在某些场景中的好处。
re: 编写高质量的代码——从命名入手 Johnny.Liang 2010-04-30 12:45  
@BearRui(AK-47)
我是这样想的,做开发人员,基础英语知识是必备的工具,很多技术文档、规范、API都是英文的,即使有翻译,也是读英语的比较好,因此在我参与过的项目中,包括我曾经工作过的公司,都是严禁使用拼音的。
@wpskl
前台验证主要看需求和用户体验,如果希望用户填写信息时出现错误马上得到提醒,就需要做前台校验,不过现在的软件强调以用户为中心(UCD)所以你的做法我是赞同的。
re: “设计”你的代码 Johnny.Liang 2010-04-29 09:40  
@onkyo
呵呵,回复一下这为同学的两个评论,首先,你说得对,static就不是面向对象,纯面向对象是没有static函数的,但我要解释两点,上面的代码纯属演示如何改变一种思维方式,我并没有过于斟酌于代码的细节,如果要纯面向对象的话,我可以把static声明为对象方法,然后让这个类变成Singleton;其次,如果所有东西都要考虑继承的话,就是过度设计对了,正如我在本博文的最后的特别说明,设计是要针对需求的,假如我这个流程相当稳定,不存在多态的情况,那么我就(至少在目前)不需要过度的把它设计为接口,然后再提供实现类,再通过依赖注入,而关于你提到的private方法不能继承和重用,这也是一个好问题,假如根据实际情况,我不希望我的类或方法被继承或重写,我就需要声明其为final/private了,君不见JDK的很多类都是final的吗?这同样也回答了你第二个评论的问题,没需要多态,或没需求切换实现,就没必要接口。

总之,谢谢你的发言,我只能强调,上面的代码纯属表达一种思维方式,况且,不考虑现实环境和实际需求,孤立的去讨论一个类是否有接口,一个方法是否需求继承,一个静态方法是否必须设计为对象方法,都是没有实际意义的,搞不好就是一种“过度设计”。
@问楼上的人
我非常同意你的看法,设计是需求权衡的,设计是一种选择,我写这篇博文是发现很多开发人员没有这种思想,并不是一刀切的要求都必须按设计方式生搬硬套。谢谢你的意见。