OOPAA

Focusing on OO, Patterns, Architecture, and Agile
posts - 29, comments - 75, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

日历

<2009年1月>
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

公告


本blog原创文字只代表本人某一时间内的观点或结论,与本人所在公司没有任何关系。第三方若用于商业用途的转载,须取得本人授权。一般的引用、转载请标明出处!


博主简介:

金明
ThoughtWorks 咨询师
InfoQ中文站编辑
SCJP, 系统分析师

 

 
 
 

搜索

  •  

积分与排名

  • 积分 - 115847
  • 排名 - 504

最新评论


 play! framework 是一个面向小型网站开发的 rails-like 的 Java 框架,不仅在目录结构上,在系统 skeleton 生成上,也把 rails 学了个七七八八。最近和同事也在做一个 rails style 的 Java Web 应用开发框架,参考了 rails 的很多 feature,但更多的是按照自己的开发理念和哲学思想“拿来” rails 里面有借鉴意义的思想。面对号称 rails-like 的 play! framework,这几天身在海滩上,于是花了一些时间好好研究了 play! 的源代码一番。“看上去很美”,是读完代码后脑海中第一下涌现出来的想法,我承认我是OOafarian。
 
 play! framework 5个“酷”的东西,看上去很美,但这些大都是建立在对 Java class 文件 hack 的基础上的。以 JPAModel 为例,任何它的子类 model 都是可以使用 rails style 的语法:User.findAll()。表面上看和 activerecord 的语法一样的,但实际上 play! 是通过在 JPAModel 里面定义这些静态方法,默认实现是抛出 RuntimeException,然后在 classloader 载入子类 class 文件的时候,通过增强每个 model class,使之具有这样类型安全的类方法。且不说这样实现是多么暴力和对开发人员不可理解,这与 rails 的实现是完全不一样的。ruby 因为是提供了 class 的继承体系,使得类方法也成为可以 override 的 class 类的实例方法,但是 Java 不提供 class 的继承和覆盖:这是 Java 的优势也是劣势。有人说这是语言的天性,但其实语言也是人们对世界进行抽象建模的一种折射,也反映的是人们的世界观和哲学思想。如果是我,如果依旧选择 Java 来做,我更倾向于保留 Java 的静态方法的优势和优雅,通过模式或者设计方法使之具有类似于动态语言的灵活性。这也是我和几位同事一致的看法。
 
 那么,从一位受 OO 和 pattern 熏陶很深的 Java 程序员看来,看上去很美的 play! framework 华丽的袍子下有多少虱子呢?待我细细数来:
 1. controller 里面充斥的 static void 方法,不 OO,不 testable,完全是过程化的代码。作者也是说了:
 
 The Java code from the Controller class isn't really Object Oriented : it's mainly some procedural code.
 
 当然,过程化还是面向对象,这个争论不是今天才有,不同的人在不同的上下文情景下都会选择最适合自己的开发方式。但是,作为受 OO 熏陶很深的我,这是不可接受的。
 
 2. view 的 render 实现是继承自 RuntimeException。记得很早之前,还有人争论 Exception 作为程序出口和条件判断分支的使用,但自《Effective Java》一书以及其他编码风格介绍的书籍出来之后,这样的争论早已不知何处。Exception 和 Error 会有自己适合的场所,也有它们自己的正确含义,被滥用可不是它们的错。我想,即使是 JVM 被优化得性能完全不用考虑了,这样的处理思路也是不可以被团队成员理解、认同和接受的吧?
 
 3. 暗地里修改代码,使用自己的classloader来大量增强或者修改class,甚至反编译 class。这样就导致很多增强的东西都是框架来强制性加入的,开发人员没有办法进行测试,也没有办法修改默认的实现。也许有人会觉得这样也挺好,觉得这样也够用,那也 OK。但是如果这些都建立在抛弃 Java 强大的静态类型安全,强大的 IDE 支持,强大的社区支持的基础之上,我是不能接受。
 
 当然,play! framework 也是体现了一些很新颖的创新。比如使用 Http Server 来取代 J2EE Server,甚至是 Application Server。又比如通过动态编译代码来实现 hot swap。还比如使用 java.lang.instruments API 来定位 Exception 的位置。这些创新在一定程度上减轻了 Java web 应用开发过程中的“重”,给开发人员带来“轻”的感觉。但是,如果这些需要付出 Java 社区积累到几天的成果,完全重头再来,我想我会宁愿选择 ruby on rails。
 
 当我们选择了 Java,我们看重的是强大的静态安全,看重的是强大的 IDE 支持和社区支持。虽然这些会给开发过程带来一定的“重”,但是米兰昆德拉说过,
 
    可是,沉重便真的悲惨,而轻松便真的辉煌吗?
    最沉重的负担压得我们崩塌了,沉没了,将我们钉在地上。可是在每一个时代的爱情诗篇里,女人总渴望压在男人的身躯之下。也许最沉重的负担同时也是一种生活最为充实的象征,负担越沉,我们的生活也就越贴近大地,越趋近真切和实在。
    相反,完全没有负担,人变得比大气还轻,会高高地飞起,离别大地亦即离别真实的生活。他将变得似真非真,运动自由而毫无意义。

 rails 之所以能轻,是因为它有 runit,有 rspec 来作为它的安全网,使之不会偏离方向。而 Java 也可以变得很轻,但这个轻却绝不是以抛弃 Java 的优势作为代价的。这也是我和几位同事在做 rails style 的 Java web 应用开发框架的过程中一直坚持的,希望到时能展现给大家一个高效率而有符合编程哲学的好框架。


评论

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-01 21:14 by 7047
Play! 应该是借鉴django吧

# re: 看上去很美 --OOafarian对play!框架的几点看法[未登录]  回复  更多评论   

2009-01-01 21:17 by woods
web 开发总是以rails 是一件很恐怖的事情

就像当年ejb一样

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-02 19:09 by mingj
@7047
django我倒是不熟,只是 play!宣称rails-like,所以也是这样理解的

能详细比较一下django和play么?

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-02 23:10 by hcom
我认同Play作者的做法,在Controller 中写大量的static方法没什么不好的。

一个很新颖的框架。

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-02 23:13 by hcom
请问博主,关于play的效率,有没有研究过?不知道play效率如何?

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-03 10:59 by mingj
@hcom
这个就是见仁见智了,也没有唯一答案
作为坚持OO 和 Testable的“狂热分子”:)
我是不能接受的

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-03 11:01 by mingj
@hcom
这个倒没有研究
因为我只是想研究里面一些比较新颖的东西和想法

如果你能花些时间做这方面测试
那对于我们就再好不过了:)

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-03 16:57 by hcom
博主:
“但是如果这些都建立在抛弃 Java 强大的静态类型安全,强大的 IDE 支持,强大的社区支持的基础之上,我是不能接受” 这句话我不认同。

我大体看了一下play!的文档,拿他的例子试验了一下,(但可能没有像你这样深入的了解),发现play并没有抛弃Java 强大的静态类型安全,也可以很方便的使用Eclipse啊?比如他有一个命令:eclipsify,可以很方便的生成Eclipse工程,导入Eclipse后跟普通的Eclipse工程没啥区别......导入的Play app的代码,就是普通的java代码,Eclipse照样会进行检查的。与使用Tomcat不同的是,Debug的时候需要使用Eclipse的远程调试功能,也是可以很方便的进行debug调试。

关于Testable,我没有细看,我看他有一个test的命令,另外文档中也专门有关于Test的说明。Play是推崇领域模型的,对领域模型可以很方便的测试的..

另外强大的社区支持是指的什么?是优秀的第三方开源产品吗?貌似Play并不排斥这些东西.

我是刚刚接触play,希望共同探讨。



# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-03 17:04 by hcom
我看过一点Grails,:)总是不能深入,感觉Grails才是抛弃了“Java 强大的静态类型安全,强大的 IDE 支持”..而Play并没有...

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-04 18:09 by ajf
play play俺整地java快速平台ajf
http://www.blogjava.net/ajf/archive/2009/01/03/249618.html

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-05 13:51 by pythonfly
但实际上 play! 是通过在 JPAModel 里面定义这些静态方法,默认实现是抛出 RuntimeException
JPAModel是实现了值和操作合二为一的富对象。至于里面的静态方法这也是符合OO标准的吧。难道rails的不是静态方法吗?User.save()这样的用法不是静态方法?User是一个实例而非class?
JPAModel里面有异常,那是防止你在调用没有的方法的时候而抛出的异常,这样使用异常没有什么不妥当。
JPAModel没有使用修改字节码增强,没有任何增强的地方。只是单纯的对JPA的一种封装而已。

java是没有可以动态给一个对象增加一个方法的功能,而且无论如何也没有办法获得这个功能。

1. static是OO的大敌。可是我觉得controller静态方法没有什么不妥当。它没有什么不可测试性,你只需要提供一个mock它一样能很好的运行。
2.不合理的使用异常这个倒是真的,但是除了文字上的,它不应该是一个异常之外似乎不会对系统造成什么问题。
3.没理解~~~play没有用任何修改字节码的手法。它有的只是借助eclipse的jdt对java文件进行即时编译。仅仅如此而已。

play最不好玩的地方就是它不能在标准的web容器下运行。这也许是作者有意为之的。
java的轻不在于如何做设计,在于如何在开发人员的思想上给予一次洗礼。他习惯了有DAO,Service,习惯了返回的时候配置一个返回文件,所以你给他一个简单的做法,他会郁闷,会奇怪,这能行吗?万一以后修改XX怎么办?这是的他恨不能把所有的东西都是变成配置文件。

另外,play的是一个python迷。所以用异常渲染页面的办法并非独创而是来自cherrpy。controller不满了static的方法也不是独创,python的web框架中很多都是如此,gae之类的甚至干脆就脱掉对象的皮就是一个函数而不是类。

上面有朋友提到了django,这个估计在不久的将来如果不出什么意外的话,它会成为python的"java",走上一条复杂与复杂的不归路,从此你再也不必为它庞大,臃肿,的代码而烦恼。世界将恢复一片美好。;-)~~~

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-13 15:33 by mingj
@pythonfly
看来老兄对python颇有研究啊
对python,我倒是不熟
希望以后能有机会请教python:)

1. play的JPAModel实现的机制是这样的:
基类里面的静态方法(User.save)默认实现抛出异常,只有在子类上生命@Entity之后,play框架自动帮你的子类实现字节码增强。
其实,这个方案也是在java平台的约束上实现class.save方法的无可奈何之举,但这个过程是用户不可控的,所以也是我比较反感的地方。

2. java是没有可以动态给一个对象增加一个方法的功能,而且无论如何也没有办法获得这个功能。
嗯,对的。因为java里面的class不具备ruby里面的概念,只能是修改字节码修改默认实现。而这也是play的实现方式。

3. 习惯了有DAO,Service,习惯了返回的时候配置一个返回文件,所以你给他一个简单的做法
嗯,没错。传统的web mvc开发模式已经限定了很多开发人员的思路,laying/iop 这些好的开发模式被僵化成为教条。但是play如果致力于消除laying/iop,那就找错靶子了:
1). 这些开发模式都只是形式,而不是本质,本质是后面的分离关注点、SRP或者DIP。
2). play开发一个简单的domain,肯定是很顺手的。但是面对复杂domain,以及团队里面的开发,这时候静态方法、修改字节码就成了它的软肋了。

所以,面对程序开发被教条化的时候,我们更多的是要考虑通过回归OO,使用OOA/OOD来重新评估项目框架的优劣。如何保证既提供一定的限制和约定,又提供充足的自由让开发人员挥洒设计?
我觉得play并没有很好的做到这一点。

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2009-01-15 14:55 by shinewang
@mingj
那么,博主有什么具体的解决方法,那个rails style 的 Java web 应用开发框架开发得怎么样了

# re: 看上去很美 --OOafarian对play!框架的几点看法  回复  更多评论   

2010-06-05 23:03 by bluegene
controller的静态方法在play里其实就是一个个入口,相当于普通java程序里主类的main函数,它不也是静态的吗,误伤大雅啊。其实play里面最关键的是领域模型,这个可是OO的。

只有注册用户登录后才能发表评论。


网站导航:
 
51La