论坛首页 Java企业应用论坛

是否应该让实体类具备丰富的业务逻辑?

浏览 67304 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (1)
作者 正文
   发表时间:2005-03-22  
downpour 写道
不同意把业务逻辑放到实体类中去,理由很简单,假设我在设计实体类,那么或许我正在考虑一个东西长什么样,而设计业务逻辑,或许我正在考虑一个东西的操作流程,这是两种不同的思维角度。


这句说的不错,很有启发性。实体类主要描述某个对象的静态构成,而业务逻辑则是描述如何按照一定的规则和时序对对象的内容进行特定处理。静态构成相对比较稳定,动态过程则比较多变,一般来说围绕一个实体类也会有多个对应的处理逻辑,所以将多变的逻辑和稳定的构成分离开来还是比较合适的,粒度和复用的问题可以通过其他机制解决。
0 请登录后投票
   发表时间:2005-03-22  
downpour 写道
不同意把业务逻辑放到实体类中去,理由很简单,假设我在设计实体类,那么或许我正在考虑一个东西长什么样,而设计业务逻辑,或许我正在考虑一个东西的操作流程,这是两种不同的思维角度,要求我把他们混合在一起,我做不到。
另外一个原因,按照我的想法,在一个庞大的系统中,业务逻辑的设计者和实体类的设计者未必就是同一个人,两者的混合则非常不利于维护和扩展,而两者分开,那么不同的人就只需要关注他们所在层次的那部分设计了。

嗯,沉思中!
      
0 请登录后投票
   发表时间:2005-03-22  
downpour 写道
不同意把业务逻辑放到实体类中去,理由很简单,假设我在设计实体类,那么或许我正在考虑一个东西长什么样,而设计业务逻辑,或许我正在考虑一个东西的操作流程,这是两种不同的思维角度,要求我把他们混合在一起,我做不到。
另外一个原因,按照我的想法,在一个庞大的系统中,业务逻辑的设计者和实体类的设计者未必就是同一个人,两者的混合则非常不利于维护和扩展,而两者分开,那么不同的人就只需要关注他们所在层次的那部分设计了。



啊!用C语言吧,为什么要用JAVA呢?
0 请登录后投票
   发表时间:2005-03-22  
partech 写道
robbin 写道

我个人是持第一种模型的观点,但是也很希望听取一下持第二种观点人的意见,了解一下该模型到底有什么实际的好处? 我想,这里搬出什么理论大道理,搬出什么Martin Fowler的话都不是我想听的,我想了解的是第二种模型究竟在实际软件开发中,能够给我们带来什么好处?

好吧,抛开业界的灵魂人物。来探讨具体问题。
好处就在于能够很方便的找到操作数据的方法,避免代码重复,防止非法操作。
用业务对象操作实体对象的方式实现业务逻辑的模式,会有多个业务对象操作同一个对象。
而从被操作的实体对象并不能明显的知道有多少对象操作了它。这就有可能出现代码重复,
特别是多人共同开发的情况下。
而且实体对象是裸露在业务对象面前的数据。对于已经有的
约束实体对象的规则,完全可以绕过,要操作某个实体正常途径是需要经过SecurityManager的检查。
但如果不封装在同一个类中,其实是没法阻止不调用SecurityManager,而直接操作实体对象的操作的

很精辟! 第一种方式,很容易陷入过程式的开发。
不过现在国内绝大多数的应用都是Transaction Script 模式的,这个本应该是缺点的东西反而已经逐渐变为“优点”了。 正如Robbin说的“分离关注点”,不过和 在Action或者Service中,为实现某一业务逻辑,频繁调用不同Service暴露的方法,这也不应该成为分离关注点的结果吧! 更甚的是,某几个业务逻辑 可能 一部分代码是重复的,这似乎也是顺期而然的事情!    
0 请登录后投票
   发表时间:2005-03-22  
引用
它的缺点在于往一个类里面放入了过多的职责,不符合单一职责的原则。

这个其实不见得会这样,最明显的就是实体对象起一个类似于facade的作用。

在很多的设计中存在service层,按照提供服务的观点去解析业务规则,如果我没有理解错,大多数的第一种模型都是将业务逻辑建在这一层(或者建在这层下面持久化层上面,如果是这样我想把包含了业务逻辑的那层也包含到这一层概念进来,主要是方便讨论,下面不复述乐)。

我认为第二种观点恰恰是立足在这个层次上,认为应按照实体对象的职责去解析业务规则,让实体对象起到类似于service facade的作用,但是相对service facade它的关注点完全不同,其目的是由一个一个具有生命的实体对象满足请求服务,而不是由一个抽象的系统概念来提供所需的业务请求服务(service层的概念感觉很类似于,我是系统,我为你们提供了这些服务,你可以通过访问这些开放的接口来获得相关的服务)。

我想从这个角度来看,由实体对象来管理业务逻辑,比提供service facade更符合职责单一的思想,因为相对service facade,你需要更细致地为service划分职责,让每个业务职责回归到具有相关职责的实体身上。

以上是从业务逻辑的角度来看第二种模型,而象持久层这样的非业务方面,我认为这个和第二种模型的观点在本质上并不冲突,该有的还有,该分层的还是分层。
0 请登录后投票
   发表时间:2005-03-22  
firebody 写道
partech 写道
robbin 写道

我个人是持第一种模型的观点,但是也很希望听取一下持第二种观点人的意见,了解一下该模型到底有什么实际的好处? 我想,这里搬出什么理论大道理,搬出什么Martin Fowler的话都不是我想听的,我想了解的是第二种模型究竟在实际软件开发中,能够给我们带来什么好处?

好吧,抛开业界的灵魂人物。来探讨具体问题。
好处就在于能够很方便的找到操作数据的方法,避免代码重复,防止非法操作。
用业务对象操作实体对象的方式实现业务逻辑的模式,会有多个业务对象操作同一个对象。
而从被操作的实体对象并不能明显的知道有多少对象操作了它。这就有可能出现代码重复,
特别是多人共同开发的情况下。
而且实体对象是裸露在业务对象面前的数据。对于已经有的
约束实体对象的规则,完全可以绕过,要操作某个实体正常途径是需要经过SecurityManager的检查。
但如果不封装在同一个类中,其实是没法阻止不调用SecurityManager,而直接操作实体对象的操作的

很精辟! 第一种方式,很容易陷入过程式的开发。
不过现在国内绝大多数的应用都是Transaction Script 模式的,这个本应该是缺点的东西反而已经逐渐变为“优点”了。 正如Robbin说的“分离关注点”,不过和 在Action或者Service中,为实现某一业务逻辑,频繁调用不同Service暴露的方法,这也不应该成为分离关注点的结果吧! 更甚的是,某几个业务逻辑 可能 一部分代码是重复的,这似乎也是顺期而然的事情!    


有关domain layer的3种模式,在Martin Fowler的Patterns of Enterprise Application Architecture 一书中有详细论述,3种模式确实都有其优势和生存之本,我想从本质上来说并不是一定有孰优孰略的。(SORRY  ROBBIN,提到Martin Fowler乐)
0 请登录后投票
   发表时间:2005-03-22  
希望大家讨论都结合自己的实践经验来谈论,不要高来高去的堆砌专业词汇,不要搞成一场引经据典的语文修辞比赛!

在这里我们不相信权威,我们只相信实践
0 请登录后投票
   发表时间:2005-03-23  
robbin 写道
希望大家讨论都结合自己的实践经验来谈论,不要高来高去的堆砌专业词汇,不要搞成一场引经据典的语文修辞比赛!

在这里我们不相信权威,我们只相信实践

或许吧! 实践总是最令人信服的!

不可否认的是, 现今国内绝大大多数的J2ee项目都基本采取你所说的第一种方式。 但大多数国人采取这种方式并不表明它就是正确的。  说句难听的话,这倒是反映国内软件开发水平的一个重要方面。

如今大多数的MIS项目都基本采用类似这样的Transaction Script方式完成,不仅因为大多数项目规模较小,问题领域较为简单,而且也因为大家基本默认了这种类似过程式开发的方式。 在这样的背景下,考虑这种模型的改进---即用更好的方式来组织 领域模型 似乎很少有人考虑过?? !

固然,实践可以检验很多东西,但是错误或者不好的实践倒是不做为基准为妙!
0 请登录后投票
   发表时间:2005-03-23  
昨天就看到了 “Hibernate实体类 == 领域模型 ? ” 这篇帖子,http://forum.iteye.com/viewtopic.php?t=11608&highlight= 。 看到今天的题目,就更明确了。



首先,表明一下立场,我是第二种方式的支持者,也就是说“实体类”里应该加入业务逻辑。



“实体类”这个称谓,感觉不是很好,因为它实际已经限制住了它的作用范围,做为“实体”,它更应该是和数据库相关的,更应该是没有业务逻辑的。MartinFowler所说的DomainModel,不应该是所谓的“实体”,DM更应该是业务层中的一部分。



举一个具体的例子吧,看看大家如何解决,无论是用 DM 还是用 实体:



在财务和金融行业的业务中,最常见的一个概念,就是金额,它几乎会出现在任何一张业务单据中,而金额这个概念,除了具体数值外,还会存在汇率,原币,本币,外币金额等相关数据。而对于金额的业务操作则会涉及到 加, 减 ,求平均值,金额折算 等相关的一些业务操作。


金额 : { 发生金额 , 发生币种 , 原币金额 , 原币币种 , 本币金额 , 折原汇率 , 折本汇率 }


由于金额几乎在每种类型的业务单据中都会出现,因此,也就是说,几乎每张业务单据的数据表上,都会存在着 上面所罗列的若干字段,甚至是倍数。 如果是用 实体 + Service 的方式,就一定会写一个 金额 Service 的这个东西。 如果纯粹从面向对象的角度来讲,这究竟是不是指责单一呢?我不觉得是,这让我仿佛又回到了 C 的年代, 数据 + 过程。


由于实际业务中, 金额 可能并不一定会有 上面所有的字段,也或者可能更多,因此,金额 实际也会有自身的集成结构体系的。


比如 : 在 分账财务 中 , 金额 : { 发生金额 ,发生币种 , 原币金额 ,原币币种 , 折原汇率 }
在 统账财务 中 , 金额 : { 发生金额 , 发生币种 , 原币金额 , 原币币种 , 本币金额 , 折原汇率 , 折本汇率 }
在 非核算业务 中, 金额 : {发生金额 , 发生币种}

对应这这种继承体系,同样,我们也要维护一套 金额 Service 的继承体系,这是否也是职责单一呢?是否更利于维护和扩展呢?


在不贫血的DM中,金额可以被认为是一种业务的元数据,具体的实现则可以表示为值对象(ValueObject),就像是 Numberic / Integer / BigDecimal 这样的结构一样。在分析模式或者其它的一些经典的业务建模书籍中,都可以找到具体的设计和实现。

如果把 BigDecimal 这样的类,也分为 数据实体和Service ,是否有些感觉诡异呢?



大概这样吧,不知道说的清楚不清楚,我只想通过这个例子表明,DomainModel 或者可以表示为 实体 + Service ,但这觉不是 DomainModel 最佳的实现方式,同时这也不是符合上面大家都在提到的职责单一原则的,恰恰相反,它破坏了对一个整体概念的封装。
0 请登录后投票
   发表时间:2005-03-23  
继续上面的话题,楼主的题目是“是否应该让实体类具备丰富的业务逻辑? ”。

实体是什么?

业务逻辑是什么?

这些都是很令人混淆不清的概念,到底是什么应该放入到什么之内呢?

0。实体,应该是指 EJB 或 Hibernate 下 ORMapping 与数据库ER关系图相对应的对象图,只做为数据的载体。

1。CRUD是业务逻辑吗?  不是,CRUD只不过是系统架构提供给业务实体的一种基础服务,就是是操作系统的IO一样,它不是业务。

2。复杂查询是业务逻辑吗? 是的,再自然不过了,复杂查询,所谓复杂,是有其业务含义的。但是,他应该放在实体之内吗? 不应该。就像Robbin在前一派帖子之内所提到的,象这种查询,是无状态的操作,并不会改变业务实体自身的状态或属性,所以更合适的位置,应该是 Service 或是 XXXBizObjManager 之内。

3。那倒是什么是业务逻辑呢?我无法给出准确的定义,在业务范畴之内,抛去前面两种所说的,剩下的这些,才应该是放入实体之内的业务逻辑。例如:业务校验,业务计算,业务规则等等。

通常我们的绝大多数的业务,可能抛去 1、2 之后,3 几乎就没有了,这也是为什么即使现在绝大多数都采用 实体 + Service ,而没有感觉到不爽的原因了,我想。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics