作为一个开发人员,很多年以来我都梦想有一个可以 写出许多程序的程序,这样在系统开发中过程中可以 节省多少时间呀。 我一向是一个很懒惰的人,编写程序生成器让我感到 许多乐趣,通过他我省去了许多的重复性的劳动,大大 加快了开发进程。程序生成器的效率很高,在开发软件 的许多环节都可以大显生手:数据持久化、界面、中间 件等等。  $:为什么需要程序生成器?
 我没有深入的研究过这个问题,所以关于这个问题我无法 讲的很全面。不过从我的经验来讲,归纳起来有以下几点 : 1:抽象层次规范系统。 想象以下通过生成代码,你可以将实现技术,算法,数据 结构等代码细节规范化,并对上层开发人员完全屏蔽。如 果需要修改实现,只需要简单的修改定义的规范即可。 2:工作分工 在叫大规模的软件开发中,开发人员彼此间往往需要共同 维护代码,造成个人独立地从事工作变的不可能。而通过 程序生成器为开发人员提供了一种工作分工的有效解决手 段。 3:可以生成系列产品 你可以通过程序生成器生成一系列的相关产品如:测试用 例、用户文档、图表、其他相关代码等等。 4:程序族 通过成成,你可以针对同一问题,产生不同的实现,而成 为一个程序族,而不只是单一的特定系统。譬如:你可以 使用同一界面规范(xul)生成不同平台(windows,unix)的 实现。 5:正确性和一致性 即便是你一个有多年开发经验的开发人员,你对自己编写 的代码有几分信心?通过生成方式,可以大大减少错误。 软件开发重构是免不了的,但是这往往会引发新的错误, 程序生成器,使的修改也变的方便许多,修改抽象的规范 即可,从而减少修改所引发的错误。 6:优化你性能 可以这么说程序生成器,让你有更多的时间不必浪费在重 复的编码中,从而有时间去关注系统的性能。   $:理解程序的三中可变性。 可变性有三种:1.运行时可变性;编译时可变性;生成时可变性。  运行时可变性
 运行时可变性的信息保存在一个外部文件中并通过程序读入。 在castor jdo中就是通过将保存在配置文件中的对象关系映 射信息读入来实现持数据久化的。前一篇文章中所讲的配置 既是这种方式。   编译时可可变性 编译时将信息合并到程序中。通过类与类的协作实现。   生成时可变性 将信息通过一个定制程序的生成器读入。SUN的JDO规范既是  这种方式。将配置信息通过代码增强器读入到程序中。生成 新的代码。   $:代码风格
 世界上没有两片完全相同的叶子,同样的开发人员编写的代 码在细节和结构上是不同的,而生成器生成的代应该是易维 护,容易理解,便于修改的。因而我们需要明白的是生成和 手写需要遵循不同的规则。 规则1:为修改而设计。生成的程序本生不重要,重要的是 规范,没人会去读你生成的程序,他应该是对上屏蔽的。 规则2:注意程序的正确性。 规则3:更多的关注性能而不是可读性和结构。   程序生成器生成的代码严格来讲有三种风格: 1:面向对象的驱动    以面向对象技术来组织程序的结构。功能上进行分解。便于    理解。        <bean class="java.swing.JFrame" id="TopFrame"> ...............................................       <add>         <bean class="java.swing.Button">           <property name="label" value="Stop"/>           <event-binding name="action">             <script>               <call-method target="Juggler" name="stop"/>             </script>           </event-binding>         </bean>       </add>     ........................................ </bean>  public class TopFrame  extends JFrame implemetns  ActionListner{ ...............................
  public void actionPerformed(ActionEvent e){  new Juggler().stop(); } ..............................   
 }  public class Juggler {      public synchronized void stop() {   }      }                                     2:面向代码的驱动    直观,简单的输出代码需要做增加从需要的规范处获取的信息,    代码结构紧凑,从手写观点来看,不便于修改,但动态输出无妨。       class  Afrmae extneds Frame{        ............................        public void entry(){          if(prop==start){         start();         }else if(prop==end){              end();            }else if(prop==suspend){                suspend();                 }else{                   System.exit(0);                       }         }         ............................    }
  3:面向表格的驱动    数据与代码分离,规范信息存储在专门的数据结构中,代码在适    当时候参照数据结构恢复数据。
 class Employee{  private int id ;   public void setId(int newId){   this.id =  newId;   }   public int getId(){   return id;   }      private String name;   public void setName(String newName){   this.name = newName;   }   public Stirng getName(){   return name;   }    }  <ado>        <package name="com.test" talbe="CUSTOMER">           <type>int</type>    <property>id</property>    <field pk="true">ID</field>        <type>String</type>    <property>name</property>       <field>NAME</field>        </package>     <ado>         ===>
 class Data{  //表数据。。。。   public String[] field={"ID","NAME"};   public String key = "ID";   public String tableName = "EMPLOYEE";    }class Employee implements Persistence{     class Data{  //表数据。。。。   public final static String[] field={"ID","NAME"};   public final static String key = "ID";   public final static String tableName = "EMPLOYEE";      }   //........................  private int id ;   public void setId(int newId){   this.id =  newId;   }   public int getId(){   return id;   }      private String name;   public void setName(String newName){   this.name = newName;   }   public Stirng getName(){   return name;   }      public String getTableName(){     Data.tablename;   }      public String[] getField(){   ....................   }      ............................. }  class DAO{
  public makePersistence(Object o){    .....        sqlstart= "INSERT INTO "+getTableName( ";        int count = o.getField().length();   for(int i=0;i<count;i++){       prxP = prxP+o.getField()[i]+",";       prxQ = prxQ+"?";    }        sqlend= " )  VALUES ( "+  prxQ  +" )";        sql = sqlstart+prxP+startend;    ....    } } $:作用方式
  代码生成有两种作用方式:源代码和字节码。前者生成的代码  为源代码,后者是在字节吗基础上进行代码增强。我把前者  称为白盒方式,因为对于开发者来说可以看到生成码内部的  结构,好处是便于实现,不好处是对外透明,不便于屏蔽;  后者成为黑盒方式,生成码对外不透明,对开发人员完全屏  蔽实现,不容易实现,需要掌握额外的api(BCEL 库).  本章完。
    
 
  |