代码生成器的设计理念和实践
李俊杰
概论
代码生成器十分有利于提高编码效率和项目进度,并且有利于代码的规范化管理,把程序员从繁琐的重复性的代码编写中解放出来,特别是同时产生代码和配置文件(config),这样避免了多个文件之间的互相引用带来的错误(当你查找bug精疲力竭,最后发现仅仅是由于你的配置文件中的配置时某一个参数的字母大小写的错误,你什么感受),所以颇受的广大程序员和项目管理者的青睐。
设计思想分类
代码生成器的设计思路其实很简单。简而言之,包括输入模块,加工模块,输出模块。
输入模块
所谓输入模块主要是组织“原料”,该原料可以是数据库表(如hibernate的代码生成器),也可以是文本文件(最常用的是xml文件,或者java代码文件如doclet代码生成器)或者别的途径。
加工模块
加工模块是根据输入模块产生的原料按照一定的规范(模版)生成字符串(广义的字符串,即包括要生成文件的内容 )。
输出模块
输出模块的功能是把代码生成器生成的代码字符串写入一系列指定目录和文件名称文件。
设计分类
1) 无模版设计类型。事实上该模版在设计者的心中,也就是说设计者非常清楚生成的文件的格式和内容。后面的篇幅中会简单介绍该设计思想,其优点是很灵活,缺点是扩展性和适应性较差。如同样的“原料“,生成新格式的文件就会很被动,需要重新编程。
2) 模版设计类型。这是现在最广泛的的运用设计思路。就是加工模块首先读模版文件,根据模版文件中的标志,把相应的“原料“填充到替换标志。然后生成新的文档。
实现原理简介
1)无模版设计类型示例:
//设置文件中的格式
//回车
public static final String RETURN_ROW = "\n";
//2个空格
public static final String BLANK2 = " ";
//4个空格
public static final String BLANK4 = BLANK2 + " ";
//6个空格
public static final String BLANK6 = BLANK4 + " ";
public static final String BLANK8 = BLANK6 + " ";
public static final String BLANK10 = BLANK8 + " ";
public static final String BLANK12 = BLANK10 + " ";
public static final String BLANK14 = BLANK12 + " ";
public static final String BLANK16 = BLANK14 + " ";
public static final String BLANK18 = BLANK16 + " ";
public static final String BLANK20 = BLANK18 + " ";
public static final String BLANK22 = BLANK20 + " ";
public static final String BLANK24 = BLANK22 + " ";
下面是读。Xml文件,根据读进来的原料,进行加工。
String serviceID = serviceConfig.getServiceID();
String serviceName = serviceConfig.getServiceName();
String serviceDesc = serviceConfig.getServiceDesc();
String serviceTypeName = serviceConfig.getServiceTypeName();
String packageName = serviceConfig.getPackageName();
String pureServiceName = serviceName.substring(0,serviceName.lastIndexOf("Service"));
String serviceClassName = packageName + "." + serviceName;
String inServiceBeanClassName = packageName + "." + pureServiceName + "InServiceBean";
String outServiceBeanClassName = packageName + "." + pureServiceName + "OutServiceBean";
String serviceUnitTestClassName = packageName + "." + pureServiceName + "ServiceUnitTest";
String canTest = serviceConfig.getCanTest();
String noSecurityCheck = serviceConfig.getNoSecurityCheck();
String dbServerName = serviceConfig.getDbServerName();
String serviceNo = serviceConfig.getServiceNo();
//下面是生成新的字符串
StringBuffer sb = new StringBuffer();
sb.append(beginTagRow(ProxyXMLCodeGenerator.BLANK2,"service"));
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"serviceNo",serviceNo));
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"serviceID",serviceID));
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"serviceName",serviceName));
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"serviceDesc",serviceDesc));
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"serviceTypeName",serviceTypeName));
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"packageName",packageName));
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"serviceClassName",serviceClassName));
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"inServiceBeanClassName",inServiceBeanClassName));
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"outServiceBeanClassName",outServiceBeanClassName));
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"serviceUnitTestClassName",serviceUnitTestClassName));
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"canTest",canTest));
sb.append(ProxyXMLCodeGenerator.BLANK4).append("<noSecurityCheck>1</noSecurityCheck>").append(ProxyXMLCodeGenerator.RETURN_ROW);
sb.append(generateRow(ProxyXMLCodeGenerator.BLANK4,"dbServerName",dbServerName));
sb.append(ProxyXMLCodeGenerator.BLANK4).append("<callServices/>").append(ProxyXMLCodeGenerator.RETURN_ROW);
System.out.println(sb.toString());
这样就生成了某一定格式的xml的字符串。
2)模版设计类型示例
小试牛刀,最基础的替换原理
public static String transit(HashMap map, String template){
if(template == null){
return null;
}
String ret;
StringBuffer sb = new StringBuffer();
int beginIndex = 0;
int endIndex = -1;
int t = 0 ;
int i = 0;
String key = null;
while((t = template.indexOf("$",beginIndex)) != -1 ){
endIndex = t;
if(beginIndex + 1 == endIndex){
beginIndex = endIndex + 1;
continue;
}
key = template.substring(beginIndex, endIndex);
i++;
if(i % 2 == 1){
sb.append(key);
}else{
sb.append((String)map.get(key));
}
beginIndex = endIndex + 1;
}
if((t = template.lastIndexOf("$"))!= -1){
sb.append(template.substring(t+1));
}else{
sb.append(template);
}
ret = sb.toString();
return ret;
}
public static void main(String[] args){
HashMap map = new HashMap();
map.put("name","lisi");
map.put("age","25");
map.put("address","beijing");
map.put("year"," years old");
map.put("desrc","Read me : ");
String[] names = new String[]{"name", "age","address","year","desrc"};
String[] values = new String[]{"lisi", "25", "beijing"," years old","Read me : "};
String template = "$desrc$My name is $name$, my old is $age$$year$, I live in $address$.";
System.out.println(StringUtils.transit(map, template));
}
下面是工业化版本
//seq语句模版
#loopBegin#
INSERT INTO "TX"(
"TXID",
"DEPT_CLASS",
"TXNAME",
"SEP_GRANT_FLAG",
"CROSS_OP_FLAG",
"MGRBRANCH_OP_FLAG",
"SECURITY_CHK_FLAG",
"SECURITY_TX_FLAG",
"VALCONSTR_FLAG",
"TX_TYPE",
"CI_GROUP_NO"
)
VALUES(
'$serviceId$',
'$deptClass$',
'$serviceDesc$',
'1',
'1',
'1',
'1',
'1',
'0',
'U',
'1'
)
/
#loopEnd#
首先我要解释一下该模版中的标志#loopBegin#和#loopEnd#表示这中间的代码要进行循环,其中“$$,##”为识别符,因为在模版中要识别该代码段要进行特殊的操作或者替换(另外识别符的选择一般是比较生僻的字符,在原始的代码中难以看到,如果原始的代码中真的存在该字符,可以用转字符来替代,如“\$,\#”),$serviceId$表示把“原料”中的serviceId的值替换到该处,生成新的代码字符串。
实现代码(下面的代码是我从相关的类中摘取的代码),我们的模版是以文件存在的,而文件是由一行行字符串组成的,因此我把处理的最小单元设计为一行。
/**
*
* @author lijunjie
* @param
* @return String
* @exception
* 方法描述:把从模板文件中读取的某一行进行转换,把其中的参数替换成实际的代码
*/
public String transit(ArrayList lines,HashMap map){
StringBuffer sb = new StringBuffer();
String line = (String)lines.get(0);
StringTokenizer tokenizer = new StringTokenizer(line,"$");
int i = 0;
String name;
while(tokenizer.hasMoreTokens()){
i++;
if(i % 2 == 1){
sb.append(tokenizer.nextToken());
}else{
if((name = (String)map.get(tokenizer.nextToken())) != null){
sb.append(name);
}
}
}
return sb.toString();
}
/**
*
* @author lijunjie
* @param
* @return String
* @exception
* 方法描述:依据模板生成文件内容的字符串,
* 根据模板文件的内容来进行不同的处理,使用策略模式来创建不同的处理类.
*/
public String generateCode(String templateFile) {
分享到:
相关推荐
总的来说,动软代码生成工具是一款实用的开发辅助工具,它结合了三层架构和工厂模式的最佳实践,为开发者提供了便捷的代码生成方案,大大提升了软件开发的效率和质量。通过学习和掌握这款工具,开发者能够更专注于...
"动软代码生成器"是一款高效实用的软件开发工具,专为程序员和开发团队设计,旨在简化和自动化代码编写过程,提高开发效率。这款工具能够根据用户定义的模板和业务模型,自动生成符合规范的源代码,覆盖了常见的编程...
此外,代码生成器还能帮助开发者遵循最佳实践,比如使用依赖注入、面向接口编程等设计模式。这样生成的代码更容易维护,更易于扩展,符合敏捷开发的理念。 ".net超爽的代码生成器"可能包含了以下特性: 1. 用户友好...
总的来说,易语言事件代码自动生成器是提高易语言开发效率的重要工具,通过理解和使用它的源码,开发者可以学习到事件驱动编程的概念、易语言的语法特性,以及如何构建代码生成工具。同时,这也为熟悉软件工程流程、...
7. **学习与借鉴**: Codematic2 的设计理念和实现逻辑对于其他类似工具的开发者来说也是一份宝贵的参考资料。通过研究其工作原理,可以提升对代码生成技术的理解,甚至启发创新。 总的来说, Codematic2 是一款...
【标题】"毕业设计-aspnet代码生成器v"是一个基于.NET框架的开发工具,主要用于帮助开发者快速生成ASP.NET应用程序的代码。这个工具的核心功能是自动化代码编写过程,减轻了开发人员的手动编码工作,提高了开发效率...
5. **Plop.js** 和 **Yeoman**:JavaScript的代码生成工具,帮助创建可复用的生成器模板。 6. **AutoRest**:微软提供的工具,从OpenAPI或Azure Resource Manager模板生成客户端SDK。 这些工具的使用能够显著提升...
【标题】"仿造李天平的动软代码生成器写的"所指的是一款基于李天平的动软代码生成器理念开发的工具。动软代码生成器是李天平先生设计的一种自动化软件开发工具,它能够根据预先定义的模板和数据库模型自动生成符合...
快递单代码生成器是一款实用工具,主要用于自动化生成快递单的打印代码,特别是在电子商务和物流行业中,这样的工具可以极大地提高工作效率。程序的核心理念是提供一种模板化的思路,帮助开发者快速构建出能够自动...
本文将详细介绍名为"SimpleCodeGenerator"的简单MVC三层代码生成器,它是基于Java语言并利用FreeMarker模板引擎实现的高效工具。 首先,让我们理解MVC(Model-View-Controller)架构。MVC是一种广泛应用于Web开发的...
1. **模板驱动**:动软.NET代码自动生成器基于模板驱动的设计理念,允许开发者自定义模板,以适应不同的编程风格和项目需求。用户可以根据自己的喜好和团队规范,定制出符合项目需求的代码模板。 2. **数据库反向...
《maku-generator低代码生成器 v3.0.3.zip》是一个包含源码和相关文档的压缩包,专为简化编程工作流程而设计。这款工具的核心理念是通过低代码技术来提高开发效率,使得开发者无需编写大量重复的代码,就能快速构建...
这不仅降低了开发成本,还提高了代码质量,因为自动化工具通常能遵循最佳实践和一致性。同时,随着微服务和云原生理念的普及,越来越多的项目倾向于采用这种自动化策略,以适应快速迭代和持续集成/持续部署(CI/CD)...
《Java源码:懒惰者代码...总之,通过对"懒惰者代码生成器IdlerCodeGenerator"的源码学习,我们可以提升自己的Java编程技巧,理解代码生成器的工作原理,同时也能借鉴其设计思路,为自己的项目开发带来灵感和实践指导。
总之,X-gen代码生成框架是软件开发领域的一个强大工具,结合PPT讲义和工程代码的学习,开发者不仅可以掌握如何使用该框架,还能深入了解代码生成技术背后的原理和实践,对于提升个人技能和团队开发效率都有极大的...
为了适应日益增长的嵌入式系统编程需求,研究并实现一款高效的代码生成器对于提升开发效率和代码性能具有重要意义。 《32位MIPS处理器代码生成器的研究与实现》这篇论文,针对MIPS处理器的指令特性,深入研究了LCC...
首先,Foxcode系统主要针对BusinessLogic、Models和DataAccess三层架构进行源代码生成,这三部分是任何企业级应用的基础。BusinessLogic层处理业务逻辑,是应用程序的核心;Models层定义数据模型,封装了数据操作;...
3. **基于Ant+Velocity的简单代码生成器的思路与实现 - - Java - JavaEye论坛.mht**:这个文件可能是一个论坛帖子的存档,展示了使用Ant和Velocity构建代码生成器的具体步骤和案例讨论。 4. **velocity(1).rar** 和 ...