(转)贫血和富血

转自: https://blog.csdn.net/t0404/article/details/51865174 

 

贫血vs富血 

我们来回顾一下。在企业架构模式中,业务层的实现一般有两种模式:一种是事务角本模式(Transaction script),另一种是领域模型模式(Domain Model)。这两种分别对应贫血和富血。好吧,我们不说这些扯淡的东西,我们简单点说。 

所谓贫血,就是一个对象里只有属性,如java中的pojo,要实现业务,要依靠service层来实现相关方法,service层的实现是面向过程的,也就是所谓的transaction script.我们现在大量的分层应用action->service->dao->entity的方式就是这种贫血的模式实现。 
 

Java代码  收藏代码

  1. //贫血代码示例:  
  2. Account.java  
  3. Public class Account{  
  4.     private String name;  
  5.     private Long num;  
  6.     get set…  
  7.   
  8. }  
  9.   
  10. AccountService.java  
  11. Public class AccountService{  
  12.     public List findAccountBySomething(String abc){}  
  13.     public void addAccount(Account a){}  
  14.     public void  otherBiz(){}  
  15.   
  16. }  



所谓的富血就是属性和方法都封装在Domain Object里,所有业务都直接操作Domain Object。Service层只是完成一些简单的事务之类的,甚至可以不用service层。也就是直接从action->entity. 
 

Java代码  收藏代码

  1. //富血代码示例  
  2. Account.ava  
  3. Public class Account{  
  4.     private String name;  
  5.     private Long num;  
  6.   
  7.     public List findAccountBySomething(String abc){}  
  8.     public void addAccount(Account a){}  
  9.     public void  otherBiz(){}  
  10. }  



前人总结的一些贫血和富血的对比: 
贫血模型的优点: 
1.被许多程序员所掌握,许多教材采用的是这种模型,对于初学者,这种模型很自然,甚至被很多人认为是java中最正统的模型。 
2.它非常简单,对于并不复杂的业务(转帐业务),它工作得很好,开发起来非常迅速。它似乎也不需要对领域的充分了解,只要给出要实现功能的每一个步骤,就能实现它。 
3.事务边界相当清楚,一般来说service的每个方法都可以看成一个事务,因为通常Service的每个方法对应着一个用例。 
其缺点为也是很明显的: 
1.所有的业务都在service中处理,当业越来越复杂时,service会变得越来越庞大,最终难以理解和维护。 
2.将所有的业务放在无状态的service中实际上是一个过程化的设计,它在组织复杂的业务存在天然的劣势,随着业务的复杂,业务会在service中多个方法间重复。 
3.当添加一个新的UI时,很多业务逻辑得重新写。例如,当要提供Web Service的接口时,原先为Web界面提供的service就很难重用,导致重复的业务逻辑(在贫血模型的分层图中可以看得更清楚),如何保持业务逻辑一致是很大的挑战。 

富血的优点是: 
1.领域模型采用OO设计,通过将职责分配到相应的模型对象或Service,可以很好的组织业务逻辑,当业务变得复杂时,领域模型显出巨大的优势。 
2.当需要多个UI接口时,领域模型可以重用,并且业务逻辑只在领域层中出现,这使得很容易对多个UI接口保持业务逻辑的一致(从领域模型的分层图可以看得更清楚)。 
富血的缺点是: 
1.对程序员的要求较高,初学者对这种将职责分配到多个协作对象中的方式感到极不适应。 
2.领域驱动建模要求对领域模型完整而透彻的了解,只给出一个用例的实现步骤是无法得到领域模型的,这需要和领域专家的充分讨论。错误的领域模型对项目的危害非常之大,而实现一个好的领域模型非常困难。 
3.对于简单的软件,使用领域模型,显得有些杀鸡用牛刀了。 
4.对于事务等的处理,如果完全DDD,java支持得不够好。 

关于Spring roo 
引子中小胖公司就是采用Roo完成DDD富血开发。Spring Roo is a popular open-source rapid application development (RAD) tool for Java developers. ,使用命令行或工具操作来生成自动化项目,操作非常类似于rails。Roo可以很好的支持富血的Java DDD。关于roo我也不想说太多,因为我也没有亲自实战过,大家可以google一下。 

如果采用roo,只需要 
对于一个业务实现 

Java代码  收藏代码

  1. @Entity    
  2. @RooEntity    
  3. @RooJavaBean    
  4. @RooToString    
  5. public class Employee {     
  6.     @NotNull    
  7.     @Size(max = 200)     
  8.     private String name;     
  9.     
  10.     @Temporal(TemporalType.TIMESTAMP)     
  11.     private Date birth;     
  12. }    
  13.   
  14. //EmployeeController代码如下:   
  15. @RooWebScaffold(automaticallyMaintainView = true, formBackingObject = Employee.class)     
  16. @RequestMapping("/employee/**")     
  17. @Controller    
  18. public class EmployeeController {     
  19. }   



在这里出现了一行@RooWebScaffold注解,做过rails的人会想,这不是rails里面的scaffold吗?没错,通过@RooWebScaffold注解,EmployeeController自动获得了curd的所有功能。 

好了,就这么简单,一个domain,一个Controller,我们就可以发布到tomcat中运行了。 
 

引用

Roo功能目前还不很强大,比如还不能根据配置的数据库链接直接从数据库表来生成Entity,以及前端表示层使用JSP和绑定Spring MVC(基于Spring 3.0支持REST)等,但是这些改进目标已经纳入其roadmap中。说一下另一个框架Seam对于富血也做得不错了,但还不是完全富血,同样也绑带了JSF。


这两天又看了一下spring roo,修正一下观点,新的spring roo版本已经可以用DBRE reverse from db.并且好像也很强大。 

1.一个entity只需要写属性就行,get set免。 
2.简单的增删改查功能,一键生成。 
3.通过aspectJ实现编译时aop,完全不影响性能。 
4.可以动态查询:如findPersonByNameAndMinMax(),相当于like name,between min to max这样的功能。 
5.用Spring roo实现DDD,只有两层Controller层和Entity层。另外Service层(可选),Dao不推荐用了。 
6.jms,email,json序列化支持 
7.其它说明:开发需要JDK1.6以上。 
8.不想用roo时,可以快速删除annotation和相关的jar包等文件。 
... 

Spring roo架构overview: 

 


AspectJ实现编译时AOP 

 


自动动态查询,自动生成 

 



想了解更多roo内容,可以看看此文:使用Spring Roo ,感受ROR式的开发 
http://www.iteye.com/topic/443059 
还有看官方文档: 
http://www.springsource.org/roo 

关于ruby 
Ruby我没有使用过,只是有所了解。所以不敢评价。但是当spring roo等框架成熟起来后,java语言就能很好的支持富血,更好的OO,更好的DDD,也能支持web快速开发了。那么我们能不能斗胆问一句:基于Java的开发者,想实现ror一样的web开发,还需要ruby吗?我们没必要向ruby转了吧? 


小结: 
我们对于新的东西,总是会有一种天生的阻抗性。就如我习惯了贫血的开发模式,有了更OO的spring roo出现时,我内心里还是不大看好它。正如前些天一些人说spring越来越庞大,不好一样,我想他们也是内心的阻抗性在起作用。但一个人要有一个更高的视野,时刻准备一些东西,当风暴来临时,可以从容面对。 

ps:说一下我的观点: 
我是多年的贫血模型的实践者,基本上并没什么特别觉得不适的地方,虽然贫血模型不那么OO。其实我对于这个spring roo并不是特别看好。但是需要去了解它,和关注它。(可能又要修正了,看发展情况吧) 

国外有一篇文章对spring roo的观点,我是比较赞同的: 
When to use Spring roo? 
http://java.dzone.com/articles/when-use-spring-roo?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+javalobby%2Ffrontpage+(Javalobby+%2F+Java+Zone) 
我抽出几个重要的出来: 
What is Spring Roo? 
“Spring Roo is a lightweight developer tool that makes it fast and easy to deliver instant results. Best of all, you code 100% in Java and get to reuse all your existing Java knowledge, skills and experience. 

Spring Roo is awesome for CRUD-Clients! 

Spring Roo is good for learning Technologies! 

Spring Roo is NOT good for complex Projects (yet)... 

Conclusion: Spring Roo is a nice Tool => Become a Part of the Community! 
My final conclusion: You should know Spring Roo, because it is nice, but you should also know when to use it and when to use something else. Use it to create CRUD applications or to learn technologies. Do not use it (yet) for complex, large projects. 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330358.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JDK8的排序大法!!

转载自 屌炸天,JDK8的排序大法!! 今天总结了下JDK中排序的方法,包括JDK8中强大的lambda表达式及函数式接口运用,不废话,请看下面示例。 public class Test {public static void main(String[] args) {Lis…

康复题11

定义一个二维数组: int maze[5][5] {0, 1, 0, 0, 0,0, 1, 0, 1, 0,0, 0, 0, 0, 0,0, 1, 1, 1, 0,0, 0, 0, 1, 0,}; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求…

JDK8新特性之函数式接口

转载自 JDK8新特性之函数式接口 什么是函数式接口 先来看看传统的创建线程是怎么写的 Thread t1 new Thread(new Runnable() {Overridepublic void run() {System.out.println("t1");} }); t1.start(); 再来看看使用了函数式接口是怎么写的 Thread t2 new Thre…

hashCode和identityHashCode的区别你知道吗?

转载自 hashCode和identityHashCode的区别你知道吗?hashCode 关于hashCode参考之前的文章,点击参考之前文章。 identityHashCode identityHashCode是System里面提供的本地方法,java.lang.System#identityHashCode。 /*** Returns the same ha…

转:drop、truncate和delete的区别与选择

转自: https://blog.csdn.net/shadow_zed/article/details/78252494 (1)日志与事务 1.delete语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。 2.truncate tab…

Java高级篇——深入浅出Java类加载机制

转载自 Java高级篇——深入浅出Java类加载机制类加载器简单讲,类加载器ClassLoader的功能就是负责将class文件加载到jvm内存。类加载器分类从虚拟机层面讲分为两大类型的类加载器,一是Bootstrap Classloader即启动类加载器(C实现)…

康复题21

For a positive integer n lets define a function f: f(n)   - 1  2 - 3  ..  ( - 1)nn Your task is to calculate f(n) for a given integer n. Input The single line contains the positive integer n (1 ≤ n ≤ 1015). Output Print f(n) in a …

转: databasemetadata 无法获取数据库表备注的解决方法

转自: https://blog.csdn.net/10km/article/details/77389038 mysql/jdbc:设置useInformationSchematrue读取表注释信息(table_comment) 问题描述 今天在读取表的注释信息(COMMENT)时,发现返回的REMARKS字段返回居然是null. 以下是代码示例: DatabaseMetaData me…

IntegerCache的妙用和陷阱

转载自 IntegerCache的妙用和陷阱 考虑下面的小程序,你认为会输出为什么结果? public class Test {public static void main(String[] args) {Integer n1 123;Integer n2 123;Integer n3 128;Integer n4 128;System.out.println(n1 n2);System.ou…

转:线性代数知识汇总

https://blog.csdn.net/MyArrow/article/details/53365048 1. 线性代数知识图谱 线性代数是代数学的一个分支,主要处理线性关系问题。线性关系意即数学对象之间的关系是以一次形式来表达的。例如,在解析几何里,平面上直线的方程是二元一次…

康复题25

都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼。说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内。馅饼如果掉在了地上当然就不能吃了,所以gameboy马…

2020-09-17

https://www.zhihu.com/question/32729130

高级JAVA码农必须搞清楚它们的区别:instanceof、isInstance、isAssignableFrom

转载自 高级JAVA码农必须搞清楚它们的区别:instanceof、isInstance、isAssignableFrominstanceof、isInstance、isAssignableFrom这几个有没有接触过,或者接触过部分?定义a instanceof B a是B的实例,B是类或者接口、父类或父接口&…

康复题12

An elephant decided to visit his friend. It turned out that the elephants house is located at point 0 and his friends house is located at point x(x > 0) of the coordinate line. In one step the elephant can move 1, 2, 3, 4 or 5 positions forward. Deter…

Java架构师必看的10本书

转载自 Java架构师必看的10本书1、大型网站系统与JAVA中间件实践 本书围绕大型网站和支撑大型网站架构的Java中间件的实践展开介绍。 从分布式系统的知识切入,让读者对分布式系统有基本的了解;然后介绍大型网站随着数据量、访问量增长而发生的架构变迁&a…

转: Spark 的核心概念 RDD

转自: https://juejin.im/post/6844903826953076750 1.RDD 概述 1.1 什么是 RDD ? RDD(Resilient Distributed Dataset) 叫着 弹性分布式数据集 ,是Spark 中最基本的抽象,它代表一个不可变、可分区、里面元素可以并行计算的集合。 RDD …

SpringMVC @Transactional的陷井大坑引发No Session found for current thread

一、TransactionManager事务配置 &#xff08;1&#xff09;注解配置 配置spring的xml加Transactional<tx:annotation-driven transaction-manager"transactionManager" proxy-target-class"true" /> &#xff08;2&#xff09;xml配置 <tx:adv…

POJ3904(BFS算法)

Problem Descrption Promble Description 定义一个二维数组&#xff1a; int maze[5][5] { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫&#xff0c;其中的1表示墙壁&#xff0c;0表示可以走的路&…

转:SparkConf 配置的用法

Spark应用程序的配置&#xff0c;用于将各种Spark参数设置为键值对。 大多数情况下&#xff0c;将使用新的SparkConf(),创建一个SparkConf对象&#xff0c;该对象将从您的应用程序中设置的任何spark.*的Java系统属性加载值。 在这种情况下&#xff0c;** 直接在SparkConf对象上…

Spring MVC 基于URL的拦截和映射规则

转载自 Spring MVC 基于URL的映射规则&#xff08;注解版&#xff09; url-pattern 如果看过前一篇入门的帖子&#xff0c;应该了解到spring mvc在启动前必须要在web.xml中配置servlet&#xff0c;这样才能拦截到想要映射的url地址。 <servlet><servlet-name>Spr…