一种一站式的Java Web框架的设计和实现

这次,我采用对话,FAQ问答方式陈述,因为我觉得它更容易从用户角度去思考问题。
MiniFramework:就是我指的框架,或者说一种思想,Mini的意思是精悍,也就是说开发量小,代码少,开发快。
RoR:Ruby on Rails用Ruby语言写的Web开发框架,非常有潜力,号称比Java开发快10倍。
SSH:Struts(Webwork)+Spring+Hibernate,JavaWeb开发最流行的组合。

[b]MiniFramework和业界已有的框架有什么特别之处吗?[/b]

从Java EE(J2EE)分层来划分,有分层和整合框架,譬如表示层的Struts,Webwork,JSF,持久层的Hibernate和 IBatis,JDO。但整合的有Spring和PicoContainer容器。

从开发角度来说,有整合和快速代码生成,前者如AppFuse和SpringSide,后者如JET Emitter。我认为,这两者都没有去解决软件开发的复杂性,更多的只是减少了一点敲代码的时间,而不是减少理解代码的时间,而后者远远大于前者。

MiniFramework综合了上面两者,既是对分层各框架的整合,也是对框架的整合,但是,它会让你的代码量减少到原来的30%左右。更少的代码意味着可以更快开发和变更,更易实现敏捷过程。它是技术和过程的结合。

MiniFramework框架用到了Webwork+Spring+Hibernate,但是,对于开发人员,它们更像是封装好的类库,这意味着你需要了解它们很少,我只用其中我认为最值得的地方。并且是你会发现新的用法,就如同Tapestry框架在html标签中设指令。

MiniFramework是严格遵守MVC职责分离和分层架构的,并且很多都是自动的,譬如透明持久化,页面输入获取。遵循上面的约定,是因为我让它们成为项目开发最佳实践。

[b]你觉得MiniFramework能够真正提高生产率吗?[/b]

高质量的软件,有三个因素:Team、Technology、Process:
[list]
[*]Team:MiniFramework可以让开发人员避开技术引起的复杂性,而专注于业务,并且节省培训成本。
[*]Technology:MiniFramework整合了流行框架最有价值部分,譬如Spring的事务处理和IoC,Hibernate的透明持久化,Webwork的control-view关系配置。
[*]Process:MiniFramework让J2EE快速开发成为可能,改变了J2EE不适合敏捷过程的论断。敏捷,意味着快速开发,快速变更,快速响应需求。
[/list]

MiniFramework将会对整个项目开发周期和流程都有很大的改进。

但是,客观的规律,如Brooks 20多年前所说:“没有银弹”。MiniFramework只能解决次要复杂性(Accident),而不能解决软件本质(Essence)复杂性。

原文如下:没有任何技术或管理上的进展,能够独立地许诺十年内使生产率、可靠性或简洁性获得数量级上的进步。
我认为,研究快速开发,必须先了解这个“没有银弹”理论。Brooks先生给我们提供了一些解决方案,很多现在都在用:

技术方面:
[list]
[*] Ada和其它高级语言
[*] OOP编程
[*] 人工智能和专家系统
[*] “自动”编程
[*] 图形化编程和IDE工具
[/list]
另外还有一些解决方案,我认为现在都在流行
[list]
[*] 购买构建 vs 自行开发
[*] 需求精炼和快速原型
[*] 增量开发
[*] 优秀的设计人员
[/list]
但是,大多数企业应用,特别是外包项目,软件的本质复杂性并不大,因为应用软件,特别是商业软件毕竟不同于系统软件,技术往往不是根本的障碍,而是背后的商业需求(怎样才能够最大程度盈利?譬如业务流程再造)。也就是说,我们可以避开“没有银弹”。

关于语言对开发的影响,OO教父Martin Fowler先生的“督导”和“授权”见解,是考虑开发语言选择的重要依据:http://blog.csdn.net/mfowler/archive /2006/07/29/997103.aspx 。

MiniFramework兼顾了这两种。

[b]MiniFramework有哪些核心思想,或是原理?[/b]

1、元数据编程
这是MiniFramework中减少代码量和快速开发的一个很重要方面。
MiniFramework中有两类元数据,都非常简单:
Map和数据库映射 同时我们会避开Hibernate那种复杂的关联映射。而且这种映射可以自动生成。

JSP页面表单元素类型映射 因为http GET和POST提交数据都是文本key-value键值对,它们和数据库字段类型不匹配,我们必须还原其本来类型,但这个过程是自动化的。我打算开发 eclipse插件,让这个映射代码也自动生成。

所有容易变更的信息,譬如sql,页面导航,对象实例引用…

2、领域对象的表示:Map和List
MiniFramework里面没有具体的对象,譬如Account,Department,Book,而是以另外一种形式体现:Map,这是它最核心的思想。它可以实现所有具体对象的功能,包括对象图。并且易扩展、灵活。

为什么Map这么关键呢?因为它是领域模型的载体,也是自动持久化的目标对象。了解JSON、YAML和REST对MiniFramework中的map 载体理解很有帮助:

REST:区别于Web Services SOAP协议的另外一种轻量级格式,更是一种Idea。REST和ajax协作开发,简直是绝配。REST是未来Web Services的发展趋势,更倾向于SOA,因为REST是以Resource为导向,而SOAP是以Action为导向,并且简单、易用。

JSON:这是ajax流行起来后,一种轻量集的数据交换格式。参考http://www.json.org/json-zh.html

YAML:在Ruby on Rails和Python这类动态语言最常用的一种文本数据格式,类似于Java最常用的XML,但更适合人读。参考:http://wiki.nirvanastudio.org/wiki/YAML/5%B7%D6%D6%D3%C8%CF%CA%B6YAML

从技术的角度考虑,所有的MIS系统,无非是CRUD增删改查,而CRUD的对象,一种载体形式,就可以是Map和List(Map的复数形式)。

关于数据流的处理,可以参考《面向模式的软件架构:卷一》中的“管道模式”,异曲同工。

当然,复杂的MIS就不只是数据流,更倾向于业务流,譬如ERP中的物料管理,SCM的进销存,OA中的工作流。但它们底层都需要数据流支持。

3、Map和List对象的展现技术:JSTL

当然,我并没有提出什么新东西,我只是提出一种新用法。JSTL是map和list的最好展现方式。如user.department.name,通过具体对象,或是Map对象图,都可以实现。但后者很少人用,因为所有的教程上面都会演示对象模型,用map是忌讳,不OO嘛。 Really?

对象展现技术和对象载体是两个非常关键的部分,关于对象展现的idea,可以参考:

OGNL:这是xwork里面对象属性存取的核心, OGNL也是EL(Expression Language)的一种实现方式。
Associative model of data:不同于关系模型和对象模型的另一种idea。

4、 Map 对象持久化技术:Hibernate
几乎我们所见的大多数Hibernate用法,都是持久化POJO,也就是JavaBean,但是Hibernate也支持另外一种持久化技术:Map持久化(dynamic-map)。

需要特别注意的是:对于Hibernate Map持久化,我只使用它的最基本功能,这意味着开发人员几乎都不需要理解hibernate,我已经将对象的CRUD和基本的List操作都封装起来的,调用工具方法就ok了。

这样,数据的四个最重要的方面中的三个被轻易解决了:对象的载体,对象的呈现,对象的持久化。还有一个,就是对象的复杂查询。

5、对象数据查询技术:Spring JDBC Framework

应该说,这个方面对象的概念是最弱的,因为查询的往往是结果集。Spring的JDBC framework为我们提供了很好的封装的,另外,我在它的基础上再封装一下,开发人员的学习成本就更低了,它返回的也是Map或List。

6、 业务对象BO的CRUD抽象

每个业务对象,譬如UserBO,我们要求它实现其CRUD操作,R(Read or Retrieve)包括Load和ListAll两种。这些方法都是框架自动完成的。

Load:根据ID标识加载对象,以及其相关对象,形成一个Object Graph,但对外是Map(对象标识是OO的基本四特征之一)。
ListAll:List该对象的所有信息,List里面的item是Map。
Insert:可以创建该主对象,如User,但也许需要创建相关对象,如Contact信息。
Update:创建对象。也可以支持不同级别的更新:更新用户信息,更新密码,更改用户角色等不同操作。像审批流程的通过和驳回,都是update操作。当然,从性能角度考虑,可以分解。
Delete:删除指定对象,以及相关对象,如删除User,其Contact也必然要删除。

任何业务对象都可以这么抽象划分并且实现,但是,复杂查询就需要单独的sql,利用MiniFramework提供的查询helper类处理,返回Map 或List。

7、 敏捷开发过程

更少的代码,意味着更快的开发速度,这和敏捷过程是呼应的。现在流行的Ruby on Rails,既是一种快速开发框架,更是实践了敏捷开发的idea。MiniFramework做快速原型非常方便,而且这种原型可以直接用做后续开发。快速原型是理解需求的一大利器!

而且,我们严格要求测试驱动,分层架构为容器外测试提高了保证。

Note:个人也觉得,Rails框架比较适合于互联网开发,Java更适合企业开发。因为企业开发很重视事务处理、团队协作、可维护性、语言的简单性,某些方面是Rails所欠缺的。我现在用Rails和MiniFramework开发同一个demo,我觉得它们的开发效率相差不大。

关于语言的设计和比较,请参考书籍《Concepts of Programming Language》

[b]你在MiniFramework中选择框架的依据是什么?[/b]

需要特别说明的是,MiniFramework并不依赖于具体的框架,那些框架只是这种思想的一种实现罢了,可以在.net下实现,也可以自行开发一套,都不难。

而且,我认为没有开发轮子的必要。

我并没有提到Webwork,因为它可以轻易被替换掉,而且我用自己前段时间开发的一个web框架,也完全够用,用Webwork主要为了应对不可预期的复杂性和健壮性,另外,Webwork的易用性,比起Struts,Tapestry,JSF等要简单得多。

用Spring,应该说差不多是个必须,因为它提供的声明式事务处理,为开发节省了大量代码,让代码更清晰。结合JOTM,可以实现分布式事务。另外,项目中业务对象引用复杂时,Spring的IoC容器还是很管用。Spring的AOP,为MiniFramework的扩展,提供了便利。

用Hibernate,是因为它把我想做的工作都做好了,它让我放弃了自己开发一个持久化Map框架,另外,Spring整合了Hibernate事务。而且,Hibernate支持数据库移植,这是一个特别关键的特性。

对于技术人员,知道一种框架什么时候用与不用,比学会用一种框架更重要。

[b]MiniFramework的架构,你能够大致描述一下吗?[/b]

为了保证开发的简单、灵活性,MiniFramework在架构上做了极大的简化,方便、实用、快速是它的原则,在MiniFramework架构考虑中,我们会在常用的J2EE架构上做减法,而不是做加法。但我们会恪守几个设计的基本原则:松耦合、高内聚、职责分离。

在参考常用的架构模式和设计模式过程中,我一直在思考这个问题:为什么我需要XX模式,我可不可以不要XX模式?

下面是我认为在MiniFramework设计过程中几个核心概念:

MVC(Model 2):为什么我需要MVC?因为MiniFramework是定位在交互式的GUI应用上。经验和理论告诉我,MVC是GUI应用设计的基本原则,它保证了清晰职责分离,方便开发、测试和维护。在MVC架构模式理论中,一般遵循Change->Publish,也就是Observer模式,类似于 message系统,但Web应用的本质(HTTP无状态协议,它怎么可能知道客户端的你?),可以用Request->Push(推模式),区别于Pull(拉模式)。我更倾向将MVC说成Model 2,区别于Model 1,也不同于MVC。在实际开发中,JSP是作为html模板,只被动接收Request中push过来的对象,决不主动去pull。

Note:Push和Pull,同步和异步,对软件设计很多时候有决定性的影响。

分层架构:分层架构有助于将大系统分解成子任务,每个子任务限制在一个特定的层次上,层间从上到下依赖,从下到上是松耦合。TCP/IP分层模型是它的最好证明。正如OSI 7层模型的实用模型是TCP/IP 4层模型。MiniFramework中,用户接触到的是两层:表示层和业务层,是J2EE和.NET架构的一种折中。在用MiniFramework开发时,持久层被封装起来,成为一些简单的Helper类,不是独立的一层。

严格的分层,可以让表示层的UI用Dreamweaver开发,业务层容器外测试,实现敏捷开发。

接口:在分层模型中,一般都非常强调接口,因为可以让上层只依赖于下层的接口,而不是实现,这样实现可以任意替换和变更,在网络开发,特别是和协议打交道的时候,我们会体会到这种设计的优雅。另外,在组件式开发中,我们也倾向于提供接口。

但是,应用MiniFramework,我们倾向于纵向开发,也就是说,某个模块从表示层到持久层都是一人开发,而不是横向:表示层的去调用业务层开发人员的业务层。这时候,纵向开发就不太适合用接口了,因为接口规范完全由本人把握。这时接口很可能只会带来臃肿,和难维护,一点改动往往牵一动百。当然,在某些情况,如开发Mock测试,Web Services,接口还是很有必要。另外,有人说,我用接口可以实现任意层替换啊?譬如我现在用Hibernate,以后换成IBatis。这完全是一个谎言,至少我看到的大多数应用,将Hibernate换成IBatis的成本绝不亚于重新开发,因为耦合太大。另外,我有个疑问:需要更换的可能性有 1%吗?

个人觉得,接口比较适合于系统软件开发,而不是商业软件开发;而抽象类的继承机制比较适合商业软件开发,而不是系统软件开发。为了复用,系统软件开发倾向于组合,而不是继承。

Business Object、ActiveRecord和ORM:不同于常用J2EE开发的ORM,也不同于RoR的ActiveRecord, MiniFramework用Business Object来调用持久化的Helper类,而且它是stateless的。没有ActiveRecord的高耦合,也没有ORM的复杂性。

主要参考文献:
《Pattern-Oriented Software Architecture: Volume 1》
Model 2:http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html
《Patterns of Enterprise Application Architecture》
《Core J2EE patterns》

[b]
用MiniFramework开发,它的驱动模式是什么?[/b]

现在做项目,一般有三种开发模式:
[list]
[*] 数据驱动:倾向于从E-R图来设计系统,早期的两层架构,如VB、PB。现在的Web开发也很多选择这种。因为数据才是企业的核心。数据驱动往往为性能考虑很周到。
[*] 领域驱动:在复杂的业务系统,譬如物流、金融领域,都有自己的领域模型,分析这些业务本质的抽象,是进行大规模开发和后期维护的保证。
[*] 页面驱动:倾向于交互式系统(不同于电信那种以业务为核心的系统),GUI往往就是需求本身。而且,先做出页面原型,和客户交流,对于理解需求非常关键。另外,一般的MIS系统,页面驱动很容易理解,譬如电子政务。
[/list]

MiniFramework更倾向于页面驱动和数据驱动,而且MiniFramework很容易将Model Driven Design转化为实际可运行代码。象银行系统,底层多是C写的,并没有对象的概念,但并不是说没有领域模型。

[b]MiniFramework现在很完善了吗?[/b]

还是beta阶段,但是我认为对一般的项目应该够用,我已经做了完整的CRUD例子,其中有三表关联,还是有一定复杂性和代表性。

但是,我现在也在思考一个真正的企业级框架,如果说它是1.0版本的话,MiniFramework就是0.1版了,距离还很远。但我大致上思路很明确,除了以上的idea外,我还会加入以下idea和功能:
[list]
[*] Event Driven:提高系统的可扩展性和灵活性,将Map数据作为Event的一个部分,而不是现在的全部。
[*] Business Controller(Interceptor):相同职责统一控制,譬如权限;所有关键数据的 createdTime,createdBy,updatedTime,updatedBy统一处理;Audit等。
[*] Micro Kernel:为应用开发提供良好的适应性和扩展性,适应需求,譬如Message-based。
[*] Service Engine:为一些常用的服务提供统一的调用方式,譬如报表系统特别强调的订单号相关服务,如作业调度,消息系统
[*] 支持分布式协议:SOAP,REST,RMI,
[*] 支持多种客户端:WAP,Browser,Client,PDA
[*] 对集群、安全的灵活支持
[/list]
上面的很多概念并不是来源于MIS系统,但是我想将其思想引入到MiniFramework中,但还要保证MiniFramework的简单、易用。

你也知道,公司都是利润驱动的,MiniFramework对公司提高利润有那些帮助呢?

从上面的“生产率”FAQ我已经解答了部分,现在我要从整个软件生命周期的角度考虑:

[list]
[*] 需求调研和需求分析阶段 MiniFramework可以帮助快速开发原型,和用户确认,了解客户真实的需求。
[*] 架构和设计阶段 MiniFramework可以简化架构,因为MiniFramework里面蕴含了一种架构思想。
[*] 编码和测试阶段(开发阶段) 这是MiniFramework最强劲的地方,下面会代码演示。
[*] 集成和交付 前期工作都做好了,这个会难吗?
[*] 维护阶段 这可能是项目周期中耗时最多的部分,用MiniFramework写出的代码简洁,灵活,应该不会让维护的代价呈几何级数增加。
[/list]
但是,在项目开发过程中,一般不建议瀑布模型,因为那样风险太大。MiniFramework倾向于敏捷UP,这是由MiniFramework设计决定的,也就是增量迭代、测试驱动、快速开发,及时反馈。

再说利润的问题吧。
如果从公司盈利点出发,我们可以抛开维护这个漫长的过程(绝不是逃避),因为它往往在合同之外。

因为开发可能只是占项目整个周期中的50%左右,而且在开发过程中,梳理业务和团队沟通可能占去开发的30%,那么另外的70%,也就是 MiniFramework和其它流行组合,如SSH的可比较之处。

虽然我认为代码量可以减到原来的30%,但并不意味着开发速度可以提高70%。如果和SSH传统的使用的方式带来的复杂性比较,MiniFramework可以将开发效率提高50%。

计算一下,就是1 * 50% * 70% * 50% = 17.5%, 也就是说可以提高17.5%, 不敢象RoR宣称10倍的提高,那可是1000%啊!而且,在demo讲解的时候,我会把开发实现方式,和RoR、SSH一一比较。

但是,我已经多次强调,MiniFramework不只是对开发产生影响,还有伴随它的敏捷流程,它让这种流程的实现成为可能,这也是节省成本的方式。

我认为,RoR对开发效率的提高,更倾向于个人,而不是团队,个人开发极大的减少了沟通成本。RoR是框架和过程完美结合的典范,我认为它对开发效率的级数提高,和它所推荐和采用的敏捷过程联系极为紧密。


[b]开发演示[/b]
这部分很长,所以由另外一份文档提供,只有看了代码,才真正领会了MiniFramework的Idea,但看懂所有代码,也许只需要你30分钟时间。

你可能感兴趣的:(IT技术,框架,Web,Java,设计模式,Hibernate)