论坛首页 Java企业应用论坛

xml配置文件considered painful

浏览 8008 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2005-03-04  
最近看spring的bean factory。发现spring大量的东西都围绕着用xml文件来配置java bean。

个人觉得这种xml文件往往弄得比java代码还难懂。为了节省重新编译和部署的时间,就把组装代码写成这么繁琐冗长复杂的xml代码,真是不爽。
而且还需要熟悉很多spring自己的dtd,比如list如何写啦之类的。

然后想了一下我的jaskell,欣然发现用jaskell要简单多了。下面是个例子:
假设有个CompositeBean,它内部会再ioc进来一个MyBean。

public final class CompositeBean {
  private MyBean mybean0;
  private MyBean[] beans;
  private String name;
  
  public MyBean[] getBeans(); {
    return beans;
  }
  public void setBeans(MyBean[] beans); {
    this.beans = beans;
  }
  public MyBean getBean(); {
    return mybean0;
  }
  public void setBean(MyBean mybean0); {
    this.mybean0 = mybean0;
  }
  public String getName(); {
    return name;
  }
  public void setName(String name); {
    this.name = name;
  }
}


public final class MyBean {
  private int[] nums;
  private short s;
  private String name;
  private java.util.Map map;
  
  public String getName(); {
    return name;
  }
  public void setName(String name); {
    this.name = name;
  }
  public int[] getNums(); {
    return nums;
  }
  public void setNums(int[] nums); {
    this.nums = nums;
  }
  public short getShort(); {
    return s;
  }
  public void setShort(short s); {
    this.s = (short);s;
  }
  public String toString();{
    return "name="+name
    +"\nshort="+s
    +"\nnums="+jfun.util.StringUtils.listArray("[",",", "]", nums);;
  }
  
  public java.util.Map getMap(); {
    return map;
  }
  public void setMap(java.util.Map map); {
    this.map = map;
  }
}


大致照着spring的意思写了一个xml配置

<bean id="CompositeBean" class="tests.jfun.MyBean">
  <property name="name"><value>qian</value></property>
  <property name="bean"><ref id="mbean"/></property>
  <property name="beans">
  	<list>
  	  <bean id="bean0" class="tests.jfun.MyBean">
 				<property name="name"><value>yu</value></property>
  			<property name="short"><value>33</value></property>
  			<property name="nums"><list/><property/>
  		</bean>
  		<ref id="mbean"/>
  	</list>
</bean>
<bean id="mbean" class="tests.jfun.MyBean">
  <property name="name"><value>jack</value></property>
  <property name="short"><value>200</value></property>
  <property name="nums"><list>
    10,20,30
  </list><property/>
</bean>


对比一下我的jaskell版本的配置文件:
{
  CompositeBean = let bean0 = 
    testbean "MyBean" {name = "yu";short = 33;nums = []};
  	in
  	testbean "CompositeBean"
  	  {name = "qian";bean = mbean;beans = [bean0, mbean]};
}
where
mbean = testbean "MyBean"
	{name = "jack";short= 200;nums= [10,20,30]};
testbean name = bean ("tests.jfun."+name);;


后者不但简洁很多,而且,自动拥有jskell提供的所有的高阶函数能力和直接调用java的能力。
jaskell提供的扩展功能也让自定义新的配置语义易如反掌。(这些bean, new函数就是通过jaskell api简单地扩展出来的)
不像xml,你要新添加一个element,要改dtd,改很多xml相关的东西来支持这个新的语义。

另外,用来处理基于构造函数甚至静态工厂的对象构造也容易,比如:

{
CompositeBean = new "test.jfun.CompositeBean" ["jack", 33, [bean0, mbean];
);
   发表时间:2005-03-04  
好啊。
我正准备用Spring 作为 复杂对象组装、参数读取的 统一配置文件格式。
也正头疼里面的arry, list, map等的复杂写法。很羡慕python的简洁强大script定义方式。

以前看 jaskell, 以为只是一个由java调用运行的一个script engine,是把Java object 从jvm 引入 jaskell 当作 scirpt object用。看了这个例子,才知道jaskell可以读取配置文件,可以把script object 从jaskell 引入jvm, 当作java object 用。
Bean Shell,  groovy, Jython是不是也可以这么用作配置文件?
如果是这样,那太方便了。

根据楼下各位的帖子提示,我搜索了pico, nano. 并下载了 nano.
http://www.nanocontainer.org/One+minute+description

nano 支持 groovy, beanshell, javascript, xml, jython等配置文件方式。
引用

        extensionToBuilders.put(GROOVY, "org.nanocontainer.script.groovy.GroovyContainerBuilder");
        extensionToBuilders.put(BEANSHELL, "org.nanocontainer.script.bsh.BeanShellContainerBuilder");
        extensionToBuilders.put(JAVASCRIPT, "org.nanocontainer.script.rhino.JavascriptContainerBuilder");
        extensionToBuilders.put(XML, "org.nanocontainer.script.xml.XMLContainerBuilder");
        extensionToBuilders.put(JYTHON, "org.nanocontainer.script.jython.JythonContainerBuilder");
0 请登录后投票
   发表时间:2005-03-04  
也可以用groovy来配置啊。
脚本语言在这种胶水位置是最好的选择了。
不过groovy的排错能力可不怎么样,到了beta9以后才有较大的改善。
xml做配置,干净是干净,最麻烦的也是排错,比程序难多了.
不过,说句实话,也许我以前没接触过jaskell,反正一看之下怎么也看不懂,haha.groovy可能更加接近 java一些.
0 请登录后投票
   发表时间:2005-03-04  
引用
对比一下我的jaskell版本的配置文件:
java代码: 
{ 
  CompositeBean = let bean0 = 
    testbean "MyBean" {name = "yu";short = 33;nums = []}; 
          in 
          testbean "CompositeBean" 
            {name = "qian";bean = mbean;beans = [bean0, mbean]}; 
} 
where 
mbean = testbean "MyBean" 
        {name = "jack";short= 200;nums= [10,20,30]}; 
testbean name = bean ("tests.jfun."+name);;
 


后者不但简洁很多,而且,自动拥有jskell提供的所有的高阶函数能力和直接调用java的能力。
jaskell提供的扩展功能也让自定义新的配置语义易如反掌。(这些bean, new函数就是通过jaskell api简单地扩展出来的)
不像xml,你要新添加一个element,要改dtd,改很多xml相关的东西来支持这个新的语义。

我还是喜欢XML,至少在描述数据方面XML是Jaskell无法比拟的,而且XML也更通用一些。
我看了这个Jaskell,看了老半天,还是没看懂。 偶笨,没学过啊 
0 请登录后投票
   发表时间:2005-03-04  
曾经用Jython配置PicoContainer. 发现在写Script时很不爽, 没有像Java或XML的Editor那样有AutoComplete和纠错功能的帮助, 时常有typos或者API记不住的情况.

总结: 写Script, 特别是Huge Script需要很好的记忆力(API)和专注力(typos) ;)
0 请登录后投票
   发表时间:2005-03-04  
XML有编辑器的帮助,还好,没感觉到需要记什么东西。
特别是IDEA,几乎让代码跟配置文件合二为一了。
0 请登录后投票
   发表时间:2005-03-05  
好。我不知道groovy用来配置的代码大致是什么样子,我先贴两段jaskell配置的代码,希望明白groovy的也贴些groovy的对应代码大家比比看。


personbean = bean "com.xxx.Person" {
  name = "Tom";
  age = 10;  
  male = true;
};

这段代码调用bean函数(预定义的),产生一个com.xxx.Person类的对象,并且把name设为"Tom", age设为10, male设为true.
花括号内部是一个tuple,name, age等等property的名字甚至不需要用引号括起。

personbean = let
  obj = new "com.xxx.Person" [];
  setProperty obj
    "name" "Tom"
    "age"    10
    "male"   true
     1           [1,2,3]
  in obj;

这段代码几乎和上面的代码做同样的事情,只不过,它又对一个叫做“1”的perperty设置了值。
首先,请注意,let,in是两个关键字,
let x=1; y=2; in x+y

等价于java的
int x=1;
int y=2;
return x+y;



new "com.xxx.Person" [] 首先创建一个Person类的对象。jaskell里面对java函数的参数都是通过一个列表传递,所以是[]而不是()。
然后,调用setProperty函数来设置每个property的值。
你可以把一对一对的name-value pair再后面排列起来就成了。这是jaskell函数调用的标准语法(不用括号,逗号)。
不过,你也可以使用括号和逗号(象java那样),只不过,个人认为这种情况不用括号和逗号好看得多。

最后let ... in obj把这个对象返回出去作为personbean的值。


personbean = new "com.XXX.Person" ["Tom", 10, true];

这个代码不依赖bean的setter,它直接调用构造函数,把三个值传递进去。
这就是pico倡导的构造器注射了。


personbean = class "com.xxx.Person".newInstance["Tom",10,true];

这段代码调用静态工厂函数newInstance来构造Person对象。class不是关键字,而是一个预定义函数,它用来动态装入一个类。



personbean = new "com.xxx.PersonFactory"[].newInstance["Tom",10,true];


这个代码使用一个抽象工厂来构造对象。

其它用jndi或者用任何方法,都可以做到。(当然,复杂的逻辑还是推荐在java中做,script只当胶水)


jaskell虽然暂时还没有debugger(要debug只能跟踪进java的解释器),但是,它给你提供良好的stack trace,你可以看到是什么错误以及错误出在哪一行代码上,我想这也差强人意了吧?

groovy能坐到怎样呢?

至于说编辑器,呵呵,给ultra-edit添几个关键字也就差不多了吧?
0 请登录后投票
   发表时间:2005-03-05  
引用
以前看 jaskell, 以为只是一个由java调用运行的一个script engine,是把Java object 从jvm 引入 jaskell 当作 scirpt object用。看了这个例子,才知道jaskell可以读取配置文件,可以把script object 从jaskell 引入jvm, 当作java object 用。
Bean Shell, groovy, Jython是不是也可以这么用作配置文件?
如果是这样,那太方便了。

xml说到底不是一个好的程序语言,如果勉强用它来描述复杂逻辑,只会事倍功半。
jaskell的解释器就是一个java api,它从头到尾就运行于jvm当中,当然可以把解释的结果在java程序中使用了。
所以说jaskell和java的关系是双向的,jaskell可以调用java, java也可以调用jaskell。
jaskell和其它脚本语言得区别在于
1。它是函数式的,支持高阶函数。
2。它是call-by-need,是lazy的。
3。和java自由交互。
4。jaskell运行时扩展性良好,你完全可以在java里定义一个函数hello,然后引入jaskell运行时,这样脚本就可以直接使用这个函数。比如我上面的bean, new, class等函数就都是户入根据配置文件的一般要求通过扩展运行时得到的。
这样,一人千面,根据不同的应用领域,可以预定义不同的函数给脚本使用。

你也可以把一小段适合用jaskell描述的逻辑在jaskell脚本中完成,然后把这个函数再输出回java来用。
0 请登录后投票
   发表时间:2005-03-08  
jaskell能不能处理对象?比如说我在java里面定义了几个对象,能不能直接把这几个对象传给jaskell去处理。
0 请登录后投票
   发表时间:2005-03-08  
ajoo 写道

个人觉得这种xml文件往往弄得比java代码还难懂。为了节省重新编译和部署的时间,就把组装代码写成这么繁琐冗长复杂的xml代码,真是不爽。
而且还需要熟悉很多spring自己的dtd,比如list如何写啦之类的。

xml文件比java代码还难懂?xml文件会冗长是确实的,但感觉比代码强啊。至于熟悉dtd,熟悉新的语法不也是一种熟悉吗。
脚本式的最大问题就是缺少好的编译器和调试器。原来也想用文件和脚本混合来完成配置,可用groovy的eclipse插件用的要烦死。相反,spring的插件要好用很多。
而且考虑到一旦混合,就要明确哪些需要脚本,哪些需要文件,这就会导致项目成员各自为政,加大管理难度。对于那些有专人完成配置编写人员的组织这个也许就不是问题了。
ajoo 写道

后者不但简洁很多,而且,自动拥有jskell提供的所有的高阶函数能力和直接调用java的能力。
jaskell提供的扩展功能也让自定义新的配置语义易如反掌。(这些bean, new函数就是通过jaskell api简单地扩展出来的)
不像xml,你要新添加一个element,要改dtd,改很多xml相关的东西来支持这个新的语义。

另外,用来处理基于构造函数甚至静态工厂的对象构造也容易,比如:

{
CompositeBean = new "test.jfun.CompositeBean" ["jack", 33, [bean0, mbean];
);

扩充能力是个不错的卖点,但对于一般人很少会用到这种功能吧。

对象的关系的复杂必然导致配置文件复杂,但用脚本就能解决吗?深表怀疑,不知道有谁能提供出这样的实例来。我自己碰到到的都是中等复杂的,虽然配置文件很大,但关系并不复杂。
0 请登录后投票
论坛首页 Java企业应用版

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