個人檔案人行道逆行部落格清單 工具 說明

部落格


2006/10/4

Spring 2.0定版发布

Spring2.0昨天最终发布了,新版本在原基础上强调了三个理念:简洁、强大、健壮。较之前版本做了以下增强:
1、IOC的增强,可以自定义Beans的应用范围
2、XML增强,支持namespace
3、AOP的增强,采用了AspectJ的优点更加高效地识别程序中需要应用的切点
4、JMS的增强,优化JMS消息的conusme以及本地事务处理
5、支持多种web开发语言,ruby,groovy以及beanshell
6、MVC的增强,增强了form表单校验功能
7、增加了对门户的支持
8、引入了Java5的metadata功能间接增强了对OR工具的增强
接下来又有事情可以做了
2006/8/16

DIC之创新观点

IPv6与神州数码网络
  随着信息化建设进程的加快,基于历史原因等因素,绝大部分的IPv4地址资源一直被欧美等国家控制着,而我国用户在IPv4地址的应用上一直处于极度匮乏的状态。于是乎,IPv6成了解决IPv4地址匮乏的灵丹妙药,按照正常方式从IPv4IPv6转换成功的话,全球所有的终端均可拥有一个IP地址,从而可实现全球网络的概念。
金融应用的国际化与本地创新
  银行业对国际化的需求日益迫切,业务国际化和运营模式的国际化趋势在慢慢浮出水面。业内人士指出,在银行积极推进国际化的进程中,信息化建设已成为提升银行竞争力的关键要素。从全球金融业的发展历史来看,正是信息化建设大大激发了传统金融行业的活力,为金融企业向现代金融巨头转型奠定了坚实的基础。因此,未来几年,也是我国银行信息化建设实现跨越式发 展的重要阶段。
坚持自主创新 建设创新型国家——专家学者在自主创新论坛上的演讲摘编
  专家学者在自主创新论坛上的演讲摘编:尚勇:量化指标与宏观决策;马俊如:产学研结合的创新探讨;陈清泰:企业技术创新的政策思考;段瑞春:知识产权与品牌财富
坚持走中国特色自主创新道路——胡锦涛在全国科学技术大会上的讲话
  这次会议的主要任务是:分析形势,统一思想,总结经验,明确任务,部署实施《国家中长期科学和技术发展规划纲要(20062020年)》,动员全党全社会坚持走中国特色自主创新道路,为建设创新型国家而努力奋斗,进一步开创全面建设小康社会、加快推进社会主义现代化的新局面。
华人企业国际化
  [摘要]中国品牌在国际舞台扮上主角的,不多,尤其是IT产业。Acer董事长施振荣日前在北京大学演讲时,用孤单一词描述自己的感觉,并不是故作姿态之辞,因为一个企业的国际化总是和周围群体的国际化相得益彰的。也正因为如此,施振荣把Acer创业24年来、花费上百亿元的实战经验讲了出来,与业界同仁分享——
信息产业及现代服务业
  发展信息产业和现代服务业是推进新型工业化的关键。国民经济与社会信息化和现代服务业的迅猛发展,对信息技术发展提出了更高的要求。
大象背上的SOA
  在业界对于SOA仍然存在着种种顾虑时,作为SOA最极力倡导者之一的IBM,仍然信心十足的进行着它的SOA计划。而这也恰恰是IBM一向的行事风格。仅仅在3月,就在中国连续进行了与SOA颇为相关的两项重要推广—“2006 IBM SOA Day”和以SOA“落地为主题的技术开放日。IBM借此正式宣告:SOA并不是又一个空泛的市场宣传口号。
技术与应用的新轮回2006年服务器技术展望
  2006年将发布的新品和新技术有不少,例如AMD的多核皓龙、Intel的双核安腾、Sun的全系列Niagara服务器、IBMPower6HPHP-UX 11i v3、微软的集群操作系统等,那么在新的一年中,最值得关注的技术与产品是哪些?
2006/7/12

Rule Engine

Rule engines are used in applications to replace and manage some of the business logic. They are best used in applications where the business logic is too dynamic to be managed at the source code level -- that is, where a change in a business policy needs to be immediately reflected in the application. Applications in domains such as insurance (for example, insurance rating), financial services (loans, fraud detection, claims routing and management), government (application process and tax calculations), telecom customer care and billing (promotions for long distance calls that needs to be integrated into the billing system), ecommerce (personalizing the user's experience), and so on benefit greatly from using rule engines.

Rule-based applications communicate with the rule engine by passing in the set of rules to be executed. Then, the application can inspect the results and either display them to the end user or perform further processing. The rule engine determines when to evaluate each rule based on the input required for the rule as well as the results obtained from the evaluation of previous rules. You do not need to specify the order or the dependencies of the rules.

以上是对Rule Engine的原文介绍,感觉还是很虚的东西,个人感觉Rule Engine的应用场景还是不够细化,仍然无法大部分抽取业务逻辑,不过结合workflow进行conditional flow control倒是一个不错的scene。Rule Engine只是对于if-else之类的条件进行抽取剥离(不过大部分业务代码也就是这个样子),光这点功能实现就使得原本已经很复杂的xml更加复杂,难看,针对drools来说,看到的是一堆堆的条件语句被抽到xml中,source-code也一样被抽到xml中,与其说隔离,不如说用xml写java,真的能剥离业务?

2006/6/15

Google's Bug or AJAX's Bug

 
出现这个错误很简单,因为都是异步调用,每次操作都向application level发request,由于process的时间较长,操作的速度较快,这样结果返回时回调展现方法,将两个结果都显示出来了。
2006/5/7

技术周期

  周期,我们都学过,完成一次振动所需要的时间,当然这强调的是机械周期,用在IT技术领域也一样适合,为什么呢?因为他们都有两个共同点,有两个极端,波峰、波谷,同时还有一个时间段的概念。
  IT领域中技术的发展也是如此,没有最好的技术,只有最适合目前阶段的技术,当然这个技术不是狭义上的语言、服务等,而是涵盖整个IT的硬件、软件、工程、设计理念、前沿理论等等。
  从结构设计上的技术回归,从最初的CS到BS,再到即将即将火热的RIA(这是BS的进阶,介于CS于BS中间,在我看来更像是轻量级CS结构^_^),CS就好比波谷、BS好比波峰,RIA就好比由于能量损失而衰减的波谷,总之,结构技术将再一次的回归。
  语言艺术的技术回归,从最初的结构化语言到面向对象,再到面向服务、面向方面,设计理念一步步成熟,语言的parse也从客户端搬到了服务器,但现在随着微软的avalon的发布以及现在才抄得火热的AJAX,相信会掀起计算机设计技术的一次革命,其强调的技术之一就是让解析内容回归到客户端,这又是一次周期的表现。
  系统架构设计上的技术回归,从最初的基于操作系统的架构设计被sun带到了跨平台的架构设计,再被ibm启发使用中间件技术,不过很可惜,这个市场巨大的技术应用并没有被ibm发挥到极致,反倒是bea抢了先机,逢人必推中间件,so,系统设计人员从考虑操作系统到不考虑操作系统再到考虑中间件(中间件的实现其实和操作系统的理念一样,也是通过统一平台调度资源,操作系统无非调度的是硬件资源罢了),这难道不也是周期的表现吗?
  根据论文的写作规范,开题及开门见山摆出了论点,也举例了不少论据,现在文章末了应该总结对论点进行升华。鉴于我书念得少,加少不知怎么上了高中以后就对写作失去信心,就不总了。
 
  Plus:浑浑噩噩地过了20多天,终于在大家都休假没人理我的情况下编出一篇看似技术类,实则调侃的文字,最近情绪处于低谷,哪位仁兄、仁姐能稍微开导我下。决定今天去影院看电影提提神,然后去KTV吼吼发泄下,不知道会不会被waitor鄙视,sigh...,有类似症状的同仁们可以分享下how ti relax的经验,拜谢
2006/4/1

信用卡

       考虑到未来两三年内我的消费需求增大,转帐已经不能满足这种消费模式,有必要申请一张信用卡了。申请过程,出于敏感,回来后想想设计一个信用卡管理系统究竟有多复杂?

       从系统环境角度出发需要考虑目前招商银行的网络环境及布局,能够通过internet提供多种服务,以及服务的可靠安全保密功能,这个招商银行在同类中做得还是相当不错的,集中\分布式平台处理数据、跨平台、跨操作系统、跨网络协议运行也是需要考虑的,对于银行这种特殊机构,其分支机构众多,网点设备种类繁多也是需要考虑系统设计的因素。当然这些都不是考虑的重点,这些在其他种类的卡中都需要考虑,可以直接利用现有的资源,不做赘述。

       从业务功能上考虑需要考虑用户资料管理、申请表管理、信用卡信息管理、帐单功能、对帐功能、划帐功能、报表功能、然后就是对以上各功能的维护管理。这里只简要提出需要考虑的各个方面,接下来就是细化的问题,鉴于各功能之间功能点差距不大,就不详述了,毕竟每个人有自己的一套方案,我也就不在此充当专家了,呵呵。

       从技术实现的角度上的考虑就不是现在急于考虑的事情,根据前两步对各功能点的强调与侧重,再挑选合适的技术实现即可,而不是将流行的技术硬加载到系统上,当然还需要考虑采用这种技术的后期维护成本以及稳定性等等多种考虑因素,这里我也不再详述了。
2006/3/22

Ctais的报表与RIA

  目前项目中涉及到的报表系统还是老套的PB两层结构的报表系统,老大也曾表示想将目前两层结构的报表移植到三层结构中。对于老大轻描淡写的一句话,由于时间的关系一致没有好好考虑一个实现方案。今天突然又想到了这个话题,索性就好好想想,利用博客记录一下思绪。
  报表从业务实现上并不复杂,业务上需要涉及的是样示定义、报表模板定义、数据查询组织、数据修改、报表打印等等,这些功能应该是最常用的核心功能,具体细节等以后有时间再考虑,这些功能有一个共同特点就是对view tier的要求特别高,需要很强的功能组件支持。也就是说从技术上相当依赖RIA。解决了这个问题,报表系统差不多就完成了50%的功能实现。下面来说说RIA的实现上可能需要考虑的问题。
  1、基于RIA的组件的元数据系统的定义、读取、存储、解析、使用等;
  2、数据集组件绑定的查询语句;
  3、数据集组件需要显示的字段;
  4、数据集组件对于用户定义的报表模板的组织与拼装展现;
  5、数据集组件如何与Microsoft的组件(诸如excel)的结合绑定,以及第三方组件的plugin;
  当然RIA带来的效应就是client is no longer a thin client,对客户端的要求增加了。当然毕竟这是少用户的需求,是用于产出报表的系统,不是像博客、论坛之流的泛数据化的操作,所以还是可以采用的一个技术方案,不过更为详尽的方案待有时间考虑后再贴出来。
2006/2/14

JSR175——用于 Java 编程语言的元数据工具

down了一篇SUN关于MetaData的官方说明,粗看了一下,有些抵触,首先是建立在JDK1.5的Platform上,且对数据的描述是在源代码一级描述,属于静态描述,不易更改,极度不爽。待细细看看再写些文字发发牢骚,呵呵
2006/1/25

简单了解下POJO和PO

POJO = pure old java object or plain ordinary java object or what ever.
PO = persisent object 持久对象

  就是说在一些Object/Relation Mapping工具中,能够做到维护数据库表记录的persisent object完全是一个符合Java Bean规范的纯Java对象,没有增加别的属性和方法。
  首先要区别持久对象(PO)和POJO。
  持久对象实际上必须对应数据库中的entity,所以和POJO有所区别。比如说POJO是由new创建,由GC回收。但是持久对象是insert数据库创建,由数据库delete删除的。基本上持久对象生命周期和数据库密切相关。另外持久对象往往只能存在一个数据库Connection之中,Connnection关闭以后,持久对象就不存在了,而POJO只要不被GC回收,总是存在的。
  由于存在诸多差别,因此持久对象PO(Persistent Object)在代码上肯定和POJO不同,起码PO相对于POJO会增加一些用来管理数据库entity状态的属性和方法。而ORM追求的目标就是要PO在使用上尽量和POJO一致,对于程序员来说,他们可以把PO当做POJO来用,而感觉不到PO的存在。
JDO的实现方法是这样的:
1、编写POJO
2、编译POJO
3、使用JDO的一个专门工具,叫做Enhancer,一般是一个命令行程序,手工运行,或者在ant脚本里面运行,对POJO的class文件处理一下,把POJO替换成同名的PO。
4、在运行期运行的实际上是PO,而不是POJO。
  该方法有点类似于JSP,JSP也是在编译期被转换成Servlet来运行的,在运行期实际上运行的是Servlet,而不是JSP。
Hibernate的实现方法比较先进:
1、编写POJO
2、编译POJO
3、直接运行,在运行期,由Hibernate的CGLIB动态把POJO转换为PO。
  由此可以看出Hibernate是在运行期把POJO的字节码转换为PO的,而JDO是在编译期转换的。一般认为JDO的方式效率会稍高,毕竟是编译期转换嘛。但是Hibernate的作者Gavin King说CGLIB的效率非常之高,运行期的PO的字节码生成速度非常之快,效率损失几乎可以忽略不计。
  实际上运行期生成PO的好处非常大,这样对于程序员来说,是无法接触到PO的,PO对他们来说完全透明。可以更加自由的以POJO的概念操纵PO。另外由于是运行期生成PO,所以可以支持增量编译,增量调试。而JDO则无法做到这一点。实际上已经有很多人在抱怨JDO的编译期Enhancer问题了,而据说JBossDO将采用运行期生成PO字节码,而不采用编译期生成PO字节码。

2005/12/4

谈谈克隆的用途

  Java中的克隆其实只有一种,即shallow copy,而所谓的deep copy则是shallow copy的重复,在设计缓存时,尤其是对数据库中的对象进行映射时将是非常有用的,通过ArrayList进行数据对象存储,通过LinkList实现LRU算法,简单的一个小技巧即实现了单机的缓存拷贝处理,对于Serializeable的clone,不确定的因素较多,在试验的过程中该类对象的克隆的效率一直是个棘手的问题,暂时还没有解决,希望有达人给个提示。^_^
  下面用两段小代码解释什么是shallow copy以及deep copy,比较懒,不像打太多字解释,用实例应该更加清楚。

========= shallow copy =========
public class CloneTest implements Cloneable {
    private CloneTest next;
    private char c;

    CloneTest(int i, char x) {
        c = x;
        if (--i > 0) {
            next = new CloneTest(i, (char) (x + 1));
        }
    }

    void increment() {
        c++;
        if (next != null) {
            next.increment();
        }
    }

    public String toString() {
        String s = ":" + c;
        if (next != null) {
            s += next.toString();
        }
        return s;
    }

    public Object clone() {
        Object o = null;
        try {
            o = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }

    public static void main(String[] args) {
        CloneTest ct = new CloneTest(5, 'a');
        System.out.println("ct = " + ct);
        CloneTest ct2 = (CloneTest) ct.clone();
        System.out.println("ct2 = " + ct2);
        ct.increment();
        System.out.println("after ct.increment, ct2 = " + ct2);
    }
}
======== Result ========
ct = :a:b:c:d:e
ct2 = :a:b:c:d:e
after ct.increment, ct2 = :a:c:d:e:f

======== deep copy ========
public class DeepCloneTest implements Cloneable {
    public DeepCloneTest(Depth depth) {
        d = depth;
    }

    public Depth d;

    public Object clone() {
        DeepCloneTest o = null;
        try {
            o = (DeepCloneTest) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        o.d = (Depth) o.d.clone();
        return o;
    }

    public String toString() {
        return "depth: " + d;
    }

    public static void main(String[] args) {
        DeepCloneTest dct = new DeepCloneTest(new Depth("one"));
        System.out.println("dct: " + dct);
        DeepCloneTest dct2 = (DeepCloneTest) dct.clone();
        System.out.println("dct2: " + dct2);
        dct2.d = new Depth("two");
        System.out.println("after change dct: " + dct);
        System.out.println("after change dct2: " + dct2);
    }
}

class Depth implements Cloneable {
    public Depth(String depth) {
        i = depth;
    }

    String i;

    public String toString() {
        return i;
    }

    public Object clone() {
        Depth o = null;
        try {
            o = (Depth) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }
}
======= Result =======
dct: depth: one
dct2: depth: one
after change dct: depth: one
after change dct2: depth: two

2005/11/6

设计模式的理解

常常都在讲设计模式,但是常用的就那几种模式,而且还都是简单工厂模式的不断变革、变通、改良,几乎所有的模式都或多或少的能看到工厂模式的影子。

为什么呢?无非是extend以及implements惹的祸,由于OOP,无法关心到每个共性对象的方方面面,就会产生通过抽取公用方法作为interface,按照这种原则,再根据需实例化对象的可知与不可知、实例化对象的多少、就产生了若干模式:简单工厂、工厂方法、抽象工厂、构建、代理、记忆、状态。

由于OOP的设计理论基础是静态基于业务模型的编程方法,如果业务发生变动则需要对原对象进行改造,而目前渐渐成熟的AOPAspect of program)据说可以尽量减少业务之间的耦合性,将核心业务与公用业务分离,目前我们项目中感觉是这样实现的,没有仔细研究过具体的代码,先看看再说。

2005/10/27

给新人出的考题,简单而实用

1.       JDK1.4中变量String tmpStr = new String(“test”),请说出tmpStr == “test”tmpStr.equal(“test”)的结果,并简要说出原因。

答:tmpStr == “test”结果为false;tmpStr.equal(“test”)的结果为true。前者比较的是内存地址,如果用IntelliIdea实时Debug,可以看到@1245之类的地址,对象tmpStr与对象”test”的就在比较其地址的值,而不是地址存放的内容的值,所以会出现意想不到的结果,这个错误居然出现在开票模块中,不可思议!

2.       请简要描述EJB的调用过程以及其生存周期。

答:客户端通过网络远程调用Home接口创建EJBObject对象,将该对象的reference返给远程客户端,客户端通过reference调用该EJB的商务方法(例如:CTAISEAIdoService),实现业务功能,程序结果后销毁内存中的对象。

生命周期:客户端invoke一个home对象引用,容器检索是否有钝化的EjB对象,如果没有则EJB调用ejbCreate方法创建对象放到容器中,调用结果后容器将该EJB对象ejbPassivate钝化,如果容器已有该对象则ejbActivate激活对象,根据LRU算法规则,对长时间不适用或者容器已容不下多余的EJB对象时,将其ejbRemove()

3.       请写出至少三个java原型(primitive type

答:doubleintfloatchar

4.       请简要写出jdbc调用过程

答:

//创建连接Connection con = null;

//初始化语句java.sql.PreparedStatement ps = null;

//初始化结果集 ResultSet rs = null;

//设置语句try {

                            doSomeThing();

} catch () {

} finally {

   //关闭结果集 rs.close();

   //关闭语句 ps.close();

   //关闭连接池 con.close(); 

}

5.       请简单描述在开发过程中出现程序错误应如何定位调试(无固定答案)

答:前台部分,可以通过页面左下角脚本错误提示获知JavaScript中具体哪行出现错误,或者通过jsp中元素对应的方法中设置alter断点来跟踪调试。对于后台错误,可以首先通过控制台提示的异常信息或者日志中的SQL语句来跟踪定位程序错误

6.       一个标准的EJB由哪些文件组成

答:EjbObject.javaEjbHome.javaEjbBean.javaejb-jar.xml

7.       请简述JMSqueue)调用过程

答:1、初识化上下文;2、找到server的连接工厂;3、创建连接;4、创建session5、查找jms destination6、创建sender7、创建消息;8、发送消息

8.       请简述Ormap文件的作用以及or技术在程序中的应用

答:ormap文件在于告知orm数据库表物理结构信息。为了更大的分离业务与数据操作,实现缩短开发周期,节省开发时间,使得数据库的操作对开发人员透明。

9.       何为轻量级开发?如何实现轻量级程序开发?

答:轻量级开发针对应用中开销较大的操作而言,比如创建、销毁数据库的连接池,大对象的创建、销毁都属于资源开销的操作,轻量级开发使用设计方法尽量减少该类资源的销号。由于jvm的垃圾回收机制会根据对象是否为null将对象置为无用标志并将其销毁,在程序开发中对于常用的对象可以不显示指明该对象为null,或者只要指向该对象的reference没有失效,该对象就能存在与栈中,供反复使用,比如可以将该对象的reference存于ArrayList中等等。

10.   在程序中如何应用事务控制数据库更新以及在事务应用的优点以及应用中应该注意哪些事项

答:

//新建事务

UserTransaction ut = new UserTransaction();

Try {

//启动事务

ut.begin;

…… //更新数据程序

//提交事务

ut.commit;

} catch () {

    ut.rollback();

}

 

事务是原子性的,事务中的做的事情尽可能简短明了

事务是一致性的,在事务中的所有事情都是同时成功,同时失败

事务是隔离性的,在事务与事务提交过程中互相都是透明的,所以事务不能交叉

事务是稳定性的,对于不可预知的故障,事务可以通过事务日志重建

11.   启动Weblogic提示以下错误可能是什么原因:

***************************************************************************

The WebLogic Server did not start up properly.

java.lang.OutOfMemoryError

***************************************************************************

答:可能是启动内存太小,无可分配内存,在启动脚本中修改set MEM_ARGS=-Xms128m -Xmx128m,将最小启动内容以及最大启动内存调大并保持,以免内存交换带来资源耗费。

12.   外围接口开发中,eaiconfig.xmlejbproperty.xmljmsproperty.xmlinterfaces.xml四个文件的作用分别是什么?

答:eaiconfig:提供服务ID的说明、诠释,对bean以及业务程序的类定义以及eai的可配置变量设置

Ejbpropertyctais访问外围系统ejb的配置

Jmspropertyctais访问外围Jms的配置

Interfaces:接口格式的定义

13.   在什么情况下需要更新ctais2or.jar

答:执行了DDL语句使得数据表发生的结构变化,名称变化,主键变化,类型变化。

14.   出现连接数不够限制应如何处理?

答:检查是oracle的限制还是weblogic的限制,如果是oracle的限制,加大process数(alter system set processes = 400 scope = spfile;),如果是weblogic的限制,进到控制台更改connections/pool

15.   如果出现连接池泄漏(leak)怎么处理?

答:连接池泄漏多半是由于weblogic检测可用连接时间间隔过长导致,可以调整检查时间间隔参数,或者直接对连接池shrink或者reset

16.   什么是笛卡儿积?在oracle中如何体现,可以用SQL代替

答:笛卡儿集就是集合A{1,2}B{3,4}按照A*B{13,14,23,24}的方式组合(?这个不知这样解释是否合适)。

oracle中两表以上进行表查询缺少相应的连接关系时会导致笛卡儿积,在oracle中的执行计划会有(cartisian join)的提示。例如:select 1 from sb_zsxx, sb_jks

17.   在开发中拼写自定义查询语句时碰到排序以及group by应该注意哪些问题,对排序的字段有哪些要求

答:考虑排序的的结果集是否很大,且oraclesort_area_size是否够大,且临时表空间是否够大且是否自动扩展(如果数据集超大且表空间不自动扩展会提示错误:不能扩展临时表空间)。对排序的字段要求尽量是索引字段,且如果可以,建好按照desc或者asc的函数索引,这样可以省去排序的时间(因为索引查询时不仅查询了该条记录的rowid,而且也查询了该记录的值,且按照顺序建索引,所以剩余了排序的时间,可以大大减少逻辑读)。另排序以及group by的字段要仅可能少。

18.   在开发中,为什么要注意自定义SQL语句要严格按照大小写的规范?

答:根据oraclecursor_sharing参数的设置情况,如果同一条语句大小写不一致,容易导致oracle解析语句时产生硬解析,这种情况多了会较大影响数据库性能,并容易导致library cache竞争,最终导致library cache lock

2005/8/8

XML的四种解析器原理及性能比较

  1: DOM

  DOM 是用与平台和语言无关的方式表示 XML 文档的官方 W3C 标准。DOM 是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而 DOM 被认为是基于树或基于对象的。DOM 以及广义的基于树的处理具有几个优点。

  首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改。它还可以在任何时候在树中上下导航,而不是像 SAX 那样是一次性的处理。DOM 使用起来也要简单得多。

  另一方面,对于特别大的文档,解析和加载整个文档可能很慢且很耗资源,因此使用其他手段来处理这样的数据会更好。这些基于事件的模型,比如 SAX。

  2:SAX

  这种处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。一般来说,SAX 还比它的替代者 DOM 快许多。

  3:选择 DOM 还是选择 SAX ?

  对于需要自己编写代码来处理 XML 文档的开发人员来说,选择 DOM 还是 SAX 解析模型是一个非常重要的设计决策。

  DOM 采用建立树形结构的方式访问 XML 文档,而 SAX 采用的事件模型。

  DOM 解析器把 XML 文档转化为一个包含其内容的树,并可以对树进行遍历。用 DOM 解析模型的优点是编程容易,开发人员只需要调用建树的指令,然后利用navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然而由于使用 DOM 解析器的时候需要处理整个 XML 文档,所以对性能和内存的要求比较高,尤其是遇到很大的 XML 文件的时候。由于它的遍历能力,DOM 解析器常用于 XML 文档需要频繁的改变的服务中。

  SAX 解析器采用了基于事件的模型,它在解析 XML 文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX 对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag。特别是当开发人员只需要处理文档中所包含的部分数据时,SAX 这种扩展能力得到了更好的体现。但用 SAX 解析器的时候编码工作会比较困难,而且很难同时访问同一个文档中的多处不同数据。

  4:JDOM

  JDOM的目的是成为 Java 特定文档模型,它简化与 XML 的交互并且比使用 DOM 实现更快。由于是第一个 Java 特定模型,JDOM 一直得到大力推广和促进。正在考虑通过“Java 规范请求 JSR-102”将它最终用作“Java 标准扩展”。从 2000 年初就已经开始了 JDOM 开发。

  JDOM 与 DOM 主要有两方面不同。首先,JDOM 仅使用具体类而不使用接口。这在某些方面简化了 API,但是也限制了灵活性。第二,API 大量使用了 Collections 类,简化了那些已经熟悉这些类的 Java 开发者的使用。

  JDOM 文档声明其目的是“使用 20%(或更少)的精力解决 80%(或更多)Java/XML 问题”(根据学习曲线假定为 20%)。JDOM 对于大多数 Java/XML 应用程序来说当然是有用的,并且大多数开发者发现 API 比 DOM 容易理解得多。JDOM 还包括对程序行为的相当广泛检查以防止用户做任何在 XML 中无意义的事。然而,它仍需要您充分理解 XML 以便做一些超出基本的工作(或者甚至理解某些情况下的错误)。这也许是比学习 DOM 或 JDOM 接口都更有意义的工作。

  JDOM 自身不包含解析器。它通常使用 SAX2 解析器来解析和验证输入 XML 文档(尽管它还可以将以前构造的 DOM 表示作为输入)。它包含一些转换器以将 JDOM 表示输出成 SAX2 事件流、DOM 模型或 XML 文本文档。JDOM 是在 Apache 许可证变体下发布的开放源码。

  5: DOM4J

  虽然 DOM4J 代表了完全独立的开发结果,但最初,它是 JDOM 的一种智能分支。它合并了许多超出基本 XML 文档表示的功能,包括集成的 XPath 支持、XML Schema 支持以及用于大文档或流化文档的基于事件的处理。它还提供了构建文档表示的选项,它通过 DOM4J API 和标准 DOM 接口具有并行访问功能。从 2000 下半年开始,它就一直处于开发之中。

  为支持所有这些功能,DOM4J 使用接口和抽象基本类方法。DOM4J 大量使用了 API 中的 Collections 类,但是在许多情况下,它还提供一些替代方法以允许更好的性能或更直接的编码方法。直接好处是,虽然 DOM4J 付出了更复杂的 API 的代价,但是它提供了比 JDOM 大得多的灵活性。

  在添加灵活性、XPath 集成和对大文档处理的目标时,DOM4J 的目标与 JDOM 是一样的:针对 Java 开发者的易用性和直观操作。它还致力于成为比 JDOM 更完整的解决方案,实现在本质上处理所有 Java/XML 问题的目标。在完成该目标时,它比 JDOM 更少强调防止不正确的应用程序行为。

  DOM4J 是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的 Java 软件都在使用 DOM4J 来读写 XML,特别值得一提的是连 Sun 的 JAXM 也在用 DOM4J。

  6:总述

  JDOM 和 DOM 在性能测试时表现不佳,在测试 10M 文档时内存溢出。在小文档情况下还值得考虑使用 DOM 和 JDOM。虽然 JDOM 的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM 仍是一个非常好的选择。DOM 实现广泛应用于多种编程语言。它还是许多其它与 XML 相关的标准的基础,因为它正式获得 W3C 推荐(与基于非标准的 Java 模型相对),所以在某些类型的项目中可能也需要它(如在 javascript 中使用 DOM)。

  SAX表现较好,这要依赖于它特定的解析方式。一个 SAX 检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。

  无疑,DOM4J是最好的,目前许多开源项目中大量采用 DOM4J,例如大名鼎鼎的 Hibernate 也用 DOM4J 来读取 XML 配置文件。如果不考虑可移植性,那就采用DOM4J吧!

2005/6/19

Martin Fowler关于敏捷开发的主题演讲

Martin Fowler:

  可能Sidney先生把我说得太好了,我有点不敢当了。如果大家感到失望的话,请原谅我。我今天想把主要的精力放在探讨敏捷式开发方面。

  软件开发行业目前同时存在两种情况,它既是一个非常成功的又是具有很多问题的行业。一方面软件已变成我们在日常生活中不可缺少的部分。有些可能不是非常明显,直至有问题出现的时候才发现。一个非常有名的例子就是几年前有家航空公司的计算机系统有一天不能正常工作,结果造成了很大的混乱和巨大的经济损失。我并不是要仔细分析问题的所在,只是想指出软件在各个行业中扮演的角色越来越重要,互联网的使用已极大地改变了人们的生活、工作方式。在西方,普通客户购买东西的过程中,经常把决策的过程使用在互联网上。所有这些软件所带来的影响,对于三、四十年前的人来说几乎是不可想象的。

  尽管有成功的方面,但软件开发过程中还是经常会遇到一些问题,很多企业在软件方面花了大量的金钱和经历,但并不是很清楚软件到底能给他们带来什么。一些调查发现世界上很多软件项目其实都失败了,也许这是因为在软件开发过程中,很难定义成功与失败这两个不同的概念。我们在软件界就是注重怎么预见软件开发的不可预知性,我们想象出了各种各样的技术、工具以及流程使得软件开发的过程变得越来越可以控制、预测。这种方法有一个很大的问题就是无法有效评估软件开发过程的有效性。在很多其他的产业界,可以用简单的办法评价过程的进程及有效性,但是对于软件开发过程,很难用一种标准来衡量它的进度和有效性。一个结果就是很难有效判断两种有效的方法哪种更好,使得软件技术、工具以及流程方面的很多讨论都被这种现象所左右。软件开发的过程中有各种问题,并不是新提出的概念。在六十年代末期的时候北约一个软件开发室提出了软件危机的概念,因此他们提出了非常有纪律性的方法即软件工程学,试图从电子工程学、技术工程学提炼出一些东西来用于软件工程学,他们想从中提炼出一种方法,使得软件开发的流程更有预测性。过去三、四年间这种工程学的方法一直为大家普遍使用。但软件业的人在做软件的过程中发现这些方法并没有减少软件开发过程中遇到的问题,对于这种现象有很多解释。近年来有人发现软件工程学里一些基本的假设是不正确的,并使用了一些新的开发方法,我们将其统称为敏捷式开发。

  敏捷式开发有很多特色,今天我主要集中介绍两方面的特色,我会重点介绍一下它就软件开发文化有什么样的影响。前不久我在我的网页上发表了一篇文章“新方法”解释我对敏捷式开发的看法。下面我介绍一下敏捷式开发与传统开发相比最具特色的两点。

  敏捷式开发采用适应性方法,而传统的软件工程学采用的是预测性方法。敏捷式开发是以人为主的,而传统的工程学是以过程为主的。我下面详细地介绍这两方面:

  适应性和预测性的区别存在于软件工程学对软件开发过程的描述中。在传统的工程学里,核心的概念就是把设计和构建这两个过程分开进行。最开始一个阶段叫设计阶段,在这个阶段所有跟软件设计相关的重要决定就已做出了,而且以完整的形式描述出来。这项工作通常是由一小部分非常专业的人来做的,而且他们所花的时间和精力在整个项目中占着很小的一部分。这项工作完成以后,这些设计的结果,从建筑学的角度就被“建筑公司”拿去,按照设计的结果一步步构建。在描述清晰的设计图纸的基础上,你就可以据此对构建过程进行详细的规划,并进行成本的预测。但是现在大家对这种过程是否非常适合软件开发行业存在着争议。这里经常会问到一个问题,就是这个过程要花多长时间,对于这个问题有各种不同的回答。在传统的工程学中设计过程在整个项目开发过程中只占10%左右的时间,但是很多软件开发权威机构都认为软件设计过程在整个开发过程中占百分之四、五十的时间,它明显告诉我们这里有些东西是不对的。在软件开发的过程中,我们很难想象,如何真正把设计和编程完全区分过来。软件工程学领域,所有在这里从事工作的人员,都把设计的过程想象成用图表、图象的方式来描述结果的过程。很多人都有这样的经验,没有经过编程而是直接想象出的设计,在进入编程阶段有很多地方是错误的,需要改正。而且从我的观点来看,几乎没办法进行有效的设计。还有一个更重要的问题就是说,软件本身的需求是在变化的。一个项目在开发过程中需求会出现变化,需求的变化从根本上推翻了工程学方法所建立的一个基础。当工程学的人尽量减少或者控制系统将来发生变化的可能,他越这样做问题就越容易出现。既然我们没办法避免变化的发生,那么我们就想找到一种新的方法能够更有效地适应这种变化现象。这也就是敏捷式开发方法所要达到的效果。

  最开始的时候,软件开发的过程,我们应该想到软件开发和其他的工程学是完全不同的学科。首先我们想象一种叠盖式、循序渐进的软件开发方法。软件的构建过程中是以小量的叠盖过程增加,而在这个过程中软件一直处于可使用状态。我们 ThoughtWorks在软件开发的过程中每两周都会得到一个可以工作的软件。这种非常短的循环,使终端客户可以及时、快速地看到他们花钱构建的软件是一个什么样的结果。使得客户可以更有效地参与到软件开发的过程中来。这同时也解决了软件开发中非常重要的问题,就是开发人员和终端客户交流的问题。这也使得软件开发本身可以更有效地适应业务本身需求的变化。对于一个发展变化非常快的国家,比如中国这种方法的好处是显而易见的。这个方法从理论上讲并非更简单,需要在实践的过程中学习如何使用叠盖式的开发。这种东西就是当你真正学会如何使用叠盖式开发的时候,才能发现它真正能带来的好处。如果真正在软件开发过程中实现叠盖式的开发,同时需要软件行业本身,以及业务部门本身共同的努力。如果可以实现软件开发部门和业务部门的紧密合作,本身就可以避免西方软件业发展过去所犯下的一些错误。另外一方面敏捷式开发是以人为核心的方法,而不是像过去工程学是以过程为核心的方法。这种现象是过去一些人专门研究软件开发的过程专门有一些实践。经常发现一个现象,软件项目开发的成功最核心的因素是这个软件团队里有非常优秀的人才的协作。这既意味着团队中有非常优秀的个人,又意味着团队中的人能有效地进行协作。这种协作方式通常情况下是跟这些人如何处理他们之间的关系有关而不是采用什么样的过程。工程学当中他们所采用的过程是尽量减少人在这个过程中所扮演的角色。在敏捷式开发中,提出的观点就是人在整个软件开发当中是最重要的因素,至于在这个开发过程中使用什么样的方法是次要的因素。这对于软件开发文化来说意味着什么呢?首先它意味着在提高软件开发效能中最重要的一点就是如何提高个人的能力,其中教育扮演着非常重要的角色。这也同时意味着软件开发团队在这个过程中是被如何对待的。很重要的一件事是如何为软件开发人员提供一个有效的环境,让他们为软件开发行业做出最大的、有效的贡献。而且还要提供这种环境使软件开发人员与终端客户进行有效的交流、合作。

  我在ThoughtWorks工作发现这种方式可以造就一种特别的企业文化,在西方擅长软件开发的人员往往都是一些怪才,这些人是真正喜欢软件、喜欢编程的。他与其他的人往往有不同的想法和对生活的追求,很多程序开发人员和客户进行交流过程中,遇到的困难真正的核心所在就是文化上的差异。我不知道这种文化上的差异在中国是否也出现,在印度已出现了这种情况。非常重要的一点就是认识到软件开发人员和终端客户之间交流问题的所在。就像刚刚提到的,没有一个真正可以衡量到底不同的软件开发方法哪种好、哪种不好。这就是因为我们不能非常有效的,以一个非常公正的标准来衡量软件开发哪个更有效。包括我在内,从事敏捷开发的人员,会发现在软件开发过程中敏捷开发是非常有效的方法。西方软件业敏捷开发还是非常少数的团队,但其增长速度非常快。

  我们希望在新的软件开发环境里,这种新的方法可能有更快的增长。如果能在软件开发过程中有效地避免开发客户和开发团队交流的问题,那么你就可以避免很多在西方软件开发中遇到的各种问题,当然同时也会发现一些其他新的问题。

  我就简单介绍到这里,下面跟各位领导、专家进行讨论。