差沙的密码 -- SSHWSFC's code
阅读本Blog请自备塑料袋一只
posts - 14,  comments - 59,  trackbacks - 0
这两天找点时间看了看jbpm,其设计思想相当不错,功能强劲,而且几乎实现了工作流模型的所有要求。可扩展的思想也是贯穿了整个jbpm的设计思路,这都是能看得出来的优势。但是这也仅仅是限于表面的一两眼,如果真的研究起其代码来,你会惊讶的发现Jbpm的代码漏洞百出,其设计思想完全没有发挥出来,应该说,Jbpm的代码真是“秀逗”了。下面来举几个例子吧。另外,我还没有看svn上的最新代码,所以可能有的问题jbpm自己已经修复,那就谢天谢地了。下面的代码基于jbpm3.1

秀逗1。无中生有

看到最核心的JpdlXmlReader代码真实欲哭无泪,如果好好精简精简,至少能踢掉1/3的代码。而其中甚至有些无中生有的代码:
if ( (actorId!=null)
           
|| (pooledActors!=null
         ) 
{
        assignmentDelegation.setProcessDefinition(processDefinition);
        assignmentDelegation.setClassName(
"org.jbpm.taskmgmt.assignment.ActorAssignmentHandler");
        String configuration 
= "";
我们看到,如果符合之前的条件,就用代理类来代理org.jbpm.taskmgmt.assignment.ActorAssignmentHandler这个类,但是找了好半天也没有找到这个类。。。。 难道是让用户在自己的项目中用这个类么?还是为了兼容原来的程序,,就算是其中一种,但是,可但是,这个条件根本就不可能满足,也就是说这是段废话,而且还无中生有的出来个ActorAssignmentHandler。。

秀逗2。画蛇添足

应该是我的基本功不都扎实,实在是高不明白下面的代码在干什么。。。
  public void setActorId(String actorId) {
    DefaultAuthenticationService authenticationService 
= (DefaultAuthenticationService) services.getAuthenticationService();
    DefaultAuthenticationService defaultAuthenticationService 
= (DefaultAuthenticationService) authenticationService;
    defaultAuthenticationService.setActorId(actorId);
  }
先强制转换成DefaultAuthenticationService,然后再强制转换成DefaultAuthenticationService。。。。
而且这里这么设计基本上就把DefaultAuthenticationService实现的AuthenticationService接口晾在那里了,根本就是应该用AuthenticationService这个接口来说话才对。jbpm的service设计的扩展性很强,可自己配制。但如果这么用service的话,再怎么扩展也没用。

秀逗3。莫“名”其妙

Jbpm中变量的名字真的莫名其妙,很多明明是Map的类型他叫xxList,而不是Map的类型,他却叫xxMap。这个地方我相信应该是能体现出程序员编写程序的严谨性的地方,而Jbpm作的还不够好。

秀逗4。固若金汤

Jbpm的扩展性贯穿始终,但是在最重要的泳道的扩展上却小家子气起来。看看泳道类代理的扩展代码。
if (expression!=null){
        assignmentDelegation.setProcessDefinition(processDefinition);
        assignmentDelegation.setClassName(
"org.jbpm.identity.assignment.ExpressionAssignmentHandler");
        assignmentDelegation.setConfiguration(
"<expression>"+expression+"</expression>");
      
    }
写的很明确,如果泳道使用表达式来表示的那么就用代理类来代理处理表达式。。我本想,太好了,写我自己的表达式,然后代理交给Acegi来根据表达式分配ActorId,但是,可是,但可是。他的代理类居然是写死的,写得就是自己的java.identity包里面的东西,不是说java.identity设计的不好,但是一个综合系统的用户角色管理系统是不可能跟着你的jbpm走的。强行要加入的java.identity的设计有点保护自我的意思,真的固若金汤,让我结合acegi的想法又是难上加难。(不过还是有办法的。大家自己找找看)。

秀逗5。口径不一

口径不一就是指两个程序部分的结合不一致。这种例子很多,我举一个程序和xsd的冲突的例子。
Instantiator是jbpm代理里面一个比较不错的概念。代理功能之一是生成代理的类的实例,而Instantiator则是负责生成实例的机制,这个Instantiator设计的不错,可以在配制文件中的config-type属性来扩展。看程序。
      // find the instantiator
      instantiator = (Instantiator) instantiatorCache.get(configType);
      
if (instantiator == null{
        
// load the instantiator class
        Class instantiatorClass = classLoader.loadClass(configType);
        
// instantiate the instantiator with the default constructor
        instantiator = (Instantiator) instantiatorClass.newInstance();
        instantiatorCache.put(configType, instantiator);
      }
这里的设计很人性化,可以根据configType来用自己的构造器,但是xsd却不这么想。
      <xs:attribute name="config-type" default="field">
        
<xs:simpleType>
          
<xs:restriction base="xs:string">
            
<xs:enumeration value="field"/>
            
<xs:enumeration value="bean"/>
            
<xs:enumeration value="constructor"/>
            
<xs:enumeration value="configuration-property"/>
          
</xs:restriction>
        
</xs:simpleType>
      
</xs:attribute>
可以看到它限制了4种类型,别说使用自己的构造器了,就连他自己的XmlInstantiator都不再考虑范围之内,真是大义灭亲呀。。

构造器来这里的作用很大,我写了自己的spring构造器,构造的时候使用beanFactory来构造,这样就算是存在数据库里面的class也能当作spring的bean来处理。但是如果用xsd的话就会导致交验错误,所以索性把xsd去掉了,还好一切正常,就是感觉别扭点。

秀逗N。。。 能够看得出来Jbpm需要提高的地方还很多。但是这些问题应该是一些开发人员的小疏忽,相信在以后的版本中可以改进。不管再怎么秀逗,Jbpm在工作流中仍然保有着强劲的地位,对BPM模型的实现也作的最为全面。而jbpm的par热部署和IDE也是整个系统中的两大亮点,这些优点都是不可不提的,所以我仍旧支持Jbpm,希望他能更加迅速的发展壮大起来。。。。

PS:文中错误之处还望大家指出,我希望有些“秀逗”是我自己秀逗了。
posted on 2006-08-24 11:07 差沙 阅读(5714) 评论(7)  编辑  收藏 所属分类: avaj

FeedBack:
# re: 秀逗的JBPM
2006-09-12 10:09 | freizl
看到jbpm里的这个H3.xml,不知道能不能算个秀逗得?
<map>定义里的table属性并不适用于one2many(Hibernate-Reference)

<hibernate-mapping default-access="field">

<subclass name="org.jbpm.file.def.FileDefinition"
extends="org.jbpm.module.def.ModuleDefinition"
discriminator-value="F"
lazy="false">

<map name="processFiles" table="JBPM_PROCESSFILES" cascade="all">
<key column="FILEDEFINITION_" foreign-key="FK_BYTEARR_FILDEF" />
<index column="NAME_" type="string" />
<one-to-many class="org.jbpm.bytes.ByteArray" />
</map>

</subclass>

</hibernate-mapping>  回复  更多评论
  
# re: 秀逗的JBPM
2006-09-19 14:00 | jackd
about 秀逗1。无中生有
you can checkout from cvs..
it has ActorAssignmentHandler.  回复  更多评论
  
# re: 秀逗的JBPM
2006-09-20 14:12 | 家有小猫's Java Blog
部分说法是正确的,例如第一个,我自己写了个org.jbpm.taskmgmt.assignment.ActorAssignmentHandler,发现居然永远用不到.

你当然也可以自己写个org.jbpm.identity.assignment.ExpressionAssignmentHandler,不使用jbpm的identity.相信将来jbpm会将这部分做成可配置的.

至于构造器,我不明白你为什么非要使用Spring的构造器.  回复  更多评论
  
# re: 秀逗的JBPM
2006-10-08 15:16 | coolfish
楼主现在有什么好办法把jbpm和自己用户系统结合起来么.
还有Assignment expressions 有些不太明白  回复  更多评论
  
# re: 秀逗的JBPM
2007-04-24 16:08 | 差沙
@家有小猫's Java Blog
才发现这个回复,用spring的构造器,可以注入spring的bean。  回复  更多评论
  
# re: 秀逗的JBPM
2008-05-22 10:03 | 网友
@freizl
我想知道在那里可以找到这个表 table="JBPM_PROCESSFILES"
我的jbpm数据库里面没有这张表, 所以调用的时候老抛空指针异常  回复  更多评论
  
# re: 秀逗的JBPM
2008-07-23 14:36 | gabriel
@网友
傻子。。那有这个表啊  回复  更多评论
  

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


网站导航:
 
这家伙很懒,但起码还是写了一句话。

<2006年8月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

常用链接

留言簿(8)

随笔分类

随笔档案

文章分类

搜索

  •  

最新评论

阅读排行榜

评论排行榜