在讨论代码生成器之前,首先,让我们抛开这个主题,来看看一家工厂。在这家工厂里,有一个很大的厂房,厂房里有好几条生成线在运作,人来人往,川流不息又井井有然。一些工人在搬运各种各样的原材料;一些工人在调试和安装模具;一些工人在流水线上完成各自的工序;一些工人在将成品入库。当然,这可能不是一家现实的工厂,现实的工厂会比这个复杂多,这只是工厂的抽象与简化。
那么这个抽象的工厂对于我们的代码生成器有什么启发意义吗?
首先,让我们先引进几个术语:代码生成工具、生成控制器、模板参数、模板引擎、模板。
我们暂且不给出这些术语的定义。参考工厂的生产模式,我们可以将代码生成描述为,在代码生成工具(对应为工厂)内有好几个生成控制器(对应为流水线),每一个生成控制器利用模板引擎(对应为模具)读取并分析模板(对应为原材料),然后结合模板参数(对应为原材料),最终生成代码文件(对应为产品)。
是不是有些相似性?而上面引入的5个术语就是基于模板的代码生成器的5大要素。全文都围绕着这5大要素展开。
知道了5要素后,我们一个一个来分析他们。
首先是模板参数。我们首先问自己,什么是模板参数?它有哪些形式?
模板参数,顾名思义,它是针对模板而言的,它依赖于模板,它和模板之间有机的结合,会产生丰富多彩的代码文件。可以说,模板和模板参数之间是相互依存的,谁离开了对方都会成为死物,只有当二者结合,才能产生生命力。但是,除开这些空洞的描述,我们能具体的描述什么是模板参数吗?我们能列举并归纳它有那些形式吗?我无法给它一个准确的定义,就像这个世界的代码一样,它似乎有无数种。现在好像进入了死胡同,哪里是突破口呢?
我们为什么要直接去分析它呢,可不可以从另外一个角度来分析、归纳呢?我们都知道,我们工具要实现的目标是生成代码,也就是说,我们的关注焦点是代码,是程序。而以OO的观点而言,程序是什么?它是由对象组成的。所以,可以说,我们工具要实现的目标是生成’对象’。我们都知道,对象包含了属性和行为,我个人觉得还可以扩展一点,对象的展现。既然我们的整个工具都是围绕对象而运作,那么对于模板参数而言,它也离不开这个范围。
最后,我们可以给模板参数下一个定义,模板参数是对象的属性、行为、展现的描述或抽象。接着,我们可以给模板下一个定义,模板是对象实现的描述。
其次是模板引擎,它的作用是什么?有哪些方式?
模板参数、模板引擎和模板3者相互作用的方式,我们可以划分为3种。一种,我称之为push模式,在这种模式下,生成器将获得的模板参数推入(push)到模板中。这种模式的特点是,对象实现的逻辑由模板来描述,生成器仅仅作为一个推动的工具,利用模板引擎将模板参数推入到模板中,最终生成所需要的代码文件。另外一种,我称之为pull模式,在这种模式下,生成器首先将读取(pull)模板的内容,用模板引擎分析它,然后将分析后的模板与模板参数结合,最终生成所需要的代码文件。这种模式的特点时,生成器本身需要包含一定的代码生成业务逻辑。最后一种我称为混合模式(mix),在这种模式下,生成器首先将模板参数推入模板中获取代码片段,然后根据生成器根据本身的业务逻辑生成代码并输出,在这种模式下,生成器同样也要有一定的代码生成业务逻辑。
所以,我们可以把生成器看成是模板参数、模板引擎和模板之间的联系纽带。通过生成器,我们可以分隔不同的代码生成方式,从而降低耦合度。
最后是工具。对于工具而言,最重要的是可扩展性。它主要表现为:
1. 能够不断的添加、删除、更新生成器。
2. 能够支持以不同的方式获取业务对象。可以是从数据库中、从文本文件中、从Xml文件中。等等方式。
3. 能够支持多种生成方式,可以是按层生成,可以是按对象生成。等等。
对象
也可以称为业务对象。它主要包含属性、行为和展现。对于代码生成工具而言,主要的问题是挖掘对象、获取属性、定义行为、定义展现、对象映射。
挖掘对象
是工具工作的第一步。对于工具而言,对象的挖掘需要高扩展性。初步列一下,有以下几种方式:
1.通过数据库来挖掘对象。(初期支持SqlServer2000和SqlServer2005)
2.通过Xml文件来挖掘对象。
3.自定义对象。
对象映射
举个例子来说,我们现在有一个学籍系统,其中包含了学生对象,它的属性有姓名、性别、年龄等等。学生所拥有的行为有上课、写作业,同时,为了持久化学生对象,我们还会有新建学生、修改学生、删除学生、查询学生的行为。那么这些属性和行为是否都集中放在一个类中呢?
为了使整个应用程序结构良好,我们通常都会划分几个层。假设,我们现在将应用程序划分为实体层、业务逻辑层、数据访问层、展示层。这样一来,学生对象将在各个层上映射为学生实体对象,学生业务逻辑对象,学生数据访问对象。这,我称之为对象映射。
对象属性
对象的属性可以划分为持久化属性、业务属性与展现属性。一个对象的属性可以同时为持久化属性、业务属性和展现属性。
持久化属性:顾名思义,就是最终将会持久化到数据库(或者其他文件)中的属性。这些属性一般通过数据库来获取。
业务属性:为了满足业务逻辑而定义的属性,一般由用户自己定义。
展现属性:用于对象展现时的属性。
对象行为
对象的行为可以划分为持久化行为、业务行为与展现行为。与对象属性划分有区别的是,一个行为只能属于一种类型。
模板参数
模板参数其实是一个由层次对象构成的对象。对象模型如下图所示:
模板参数由工具创建、初始化、填充对象并传递给生成器。然后由生成器自己决定是将模板参数传递给模板引擎,还是在生成器内部进行解析。
模板
是模板文件及内容在应用程序中的映射。由于在框架内允许用户自定义模板引擎。因此,对模板的内容不做任何限制。但是因为系统需要通过模板来找到对应的模板引擎,顾每个模板都唯一指向一个能解析它的模板引擎。这一点通过对模板文件的强制性命名规则来实现:
模板文件的后缀名一定要为.template
模板的文件名的格式为:*.LanguageCode.TemplateEngineeCode
其中LanguageCode表示模板所对应的语言编码。TemplateEngineeCode表示模板引擎编码。这2项中LanguageCode属于可选项而TemplateEngineeCode是必选项。系统解析时,首先将文件名按句号(.)切割。然后从后往前,首先确认截取的TemplateEngineeCode部分是否为已知的模板引擎编码。如果不是,那么匹配过程结束,系统认为整个模板文件名中没有定义LanguageCode和TemplateEngineeCode。如果是,那么系统继续往上搜索匹配。
所有的模板类都必须继承自AbstractTemplate,接口签名如下:
/**//// <summary>
/// 模板接口
/// </summary>
public abstract class AbstractTemplate
{
/**//// <summary>
/// 模板所对应的语言编码
/// </summary>
public abstract string LanguageCode{get;}
/**//// <summary>
/// 模板引擎编码
/// </summary>
public abstract string TemplateEngineeCode{get;}
/**//// <summary>
/// 模板内容
/// </summary>
public abstract string Content{get;}
/**//// <summary>
/// 模板文件路径
/// </summary>
public abstract string FilePath{get;}
/**//// <summary>
/// 获取一个值,表示该模板是否为有效的
/// </summary>
public virtual bool Valid
{
get
{
if(this.TemplateEngineeCode.Trim() == string.Empty)
return false;
else
return true;
}
}
}
模板引擎
模板引擎和模板是代码生成的一对基石,它们之间的相互作用从而满足了灵活多变的代码生成需求。模板引擎和模板是相互依赖的,没有了模板,系统无法生成满足需求的代码;没有模板引擎,系统无法解析模板,从而也无从谈起代码生成。
模板引擎的作用是解析模板,将解析后的结果与模板参数结合,最终输出代码或代码片段。模板引擎和模板之间通过模板引擎编码来对应。
Note:模板引擎编码必须在整个系统中唯一。
/**//// <summary>
/// 模板引擎接口
/// </summary>
public interface ITemplateEnginee
{
/**//// <summary>
/// 获得模板引擎的生成模式
/// </summary>
EngineMode Mode{get;}
/**//// <summary>
/// 模板引擎编码
/// </summary>
string EngineCode{get;}
/**//// <summary>
/// 推模式
/// </summary>
/// <param name="pMobj">映射对象</param>
/// <returns>返回生成的代码</returns>
string Push(MappingObject pMobj);
/**//// <summary>
/// 拉模式
/// </summary>
/// <param name="pTemplate">模板</param>
/// <returns>返回代码片段列表</returns>
CodeSectionList Pull(AbstractTemplate pTemplate);
/**//// <summary>
/// 混合模式
/// </summary>
/// <param name="pMobj">映射对象</param>
/// <returns>返回代码片段列表</returns>
CodeSectionList Mix(MappingObject pMobj);
}
代码片段
当模板引擎是使用Pull模式或者Mix模式时,引擎返回的将是代码片段。
那么什么是代码片段呢?为了方便用户自己设计、实现模板引擎和对应的模板,代码片段的定义应该模糊一些。我们可以仅仅简单的把它看作是可编译代码的一个片段,它可以是逻辑完整的,比如像字段、属性、方法之类的,也可以是逻辑不完整的,比如是方法的一部分等等。
代码片段由模板引擎生成,由生成器处理,最终形成所需要的代码文件。它对应的类声明如下:
/**//// <summary>
/// 代码片段
/// </summary>
public class CodeSection
{
private fields#region private fields
private string _sectionId =string.Empty;
private string _content =string.Empty;
private string _typeId =string.Empty;
#endregion
constructor#region constructor
public CodeSection(){}
#endregion
properties#region properties
/**//// <summary>
/// 代码片段ID
/// </summary>
public string SectionID{get{return this._sectionId;}set{this._sectionId=value;}}
/**//// <summary>
/// 代码片段内容
/// </summary>
public string Content{get{return this._content;}set{this._content=value;}}
/**//// <summary>
/// 代码片段类型Id
/// </summary>
public string TypeId{get{return this._typeId;}set{this._typeId=value;}}
#endregion
}
生成器
我们可以生成器看成是一个总装工厂,在这里,将把模板参数、模板引擎、模板组合起来,最终生成我们所需要的代码文件。当然,特定的生成器对于模板参数、模板引擎或者模板会有所限制,就例如空客的A300总装工厂只组装A300而不能组装A100等等其他飞机。
生成器生成的方式主要可以分为横向和纵向以及二者的结合。
1. 横向
即代码文件按层来生成。举个例子,系统可以先一次性的生成Entity层的所有类。
2. 纵向
即代码文件按业务对象来生成。举个例子,系统可以生成某个业务对象的Entity层、Dao层、Biz层的类。
3. 混合
即横向和纵向的结合。
4. 全部
生成模板参数中所定义的全部的类(实际是指模板参数中所有Tier下的所有的MappingObject)。
所有的生成器都必须实现IBuilder接口,接口原型如下:
/**//// <summary>
/// 生成器接口
/// </summary>
public interface IBuilder
{
/**//// <summary>
/// 生成方式
/// </summary>
BuildMode Mode{get;}
/**//// <summary>
/// 模板参数
/// </summary>
TemplateParameter Parameter{get;set;}
/**//// <summary>
/// 生成器的内置生成条件
/// </summary>
BuildCnd InnerBuildCondition{get;}
/**//// <summary>
/// 生成代码文件
/// </summary>
/// <param name="pCondition">过滤条件</param>
void Build(BuildCnd pCondition);
}
代码文件
代码文件可以分为类文件、配置文件、组织文件。
类文件就是我们通常所理解的代码文件。配置文件也很好理解,我们都经常会用到,通常都是xml格式的,例如app.config、web.config等等。而组织文件其实就是指组织类文件、配置文件的一些辅助文件。例如使用 VS集成编译环境时,由编译环境生成的.sln、.suo、.csproj文件等。
待解决问题
1. 对于模板参数,是否需要抽象出模板参数构造器?
2. 映射对象所对应的模板,是在模板参数中体现,还是在生成器中指定?
自答:
因为现在模板和映射对象之间并无内在的关联关系,因此,在生成器中指定模板参数无法解决
映射对象与模板对应的问题。所以还是应该在模板参数中指定映射对象所使用的模板。但是生
成器可能无法匹配相应的模板(例如支持push模式的生成器无法匹配由pull模式的模板引擎分
析的模板)。
3. 层的定义是由系统来定义,还是由用户自己定义?如果是用户自己定义,如何融入框架内?
自答:
层还是应该由自己定义,这样系统灵活性高。
4. 对象的展现包含哪些内容?是否可以抽象出这个概念?这个概念对代码生成有没有意义?
5. 现在所涉及的代码生成都仅仅考虑的是类文件,配置文件和组织文件是否可以生成?如果可以生成,怎么整合到框架内?
6. 模板参数还是太单薄。
7. 最关键的一点,这个框架是否值得去尝试去实现他?
类图
posted on 2007-06-01 08:03 东风31 阅读(214) 评论(3) 编辑 收藏 所属分类: ProgrammerLife
分享到:
相关推荐
使用Migcode代码生成器,开发者可以轻松地基于数据库表结构生成相关的实体类、DAO层、Service层以及前端展示页面的代码。此外,还可以根据需求自定义生成验证逻辑、权限控制等相关代码。 #### 六、结论 综上所述,...
【C# Devexpress 代码生成器】是一种基于C#编程语言和DevExpress库开发的应用程序,旨在简化和自动化编码过程。DevExpress是一款强大的Windows Forms、ASP.NET和.NET Core开发框架,提供了丰富的UI控件集,用于创建...
【标题】"毕业设计-java代码生成器"是一个基于Java编程语言的工具,旨在简化软件开发过程中重复性的编码工作。这个工具通常被称为代码自动生成器,它能够根据预先定义的模板或者数据库模型,自动创建出符合特定规范...
本文将详细介绍一款基于C#编程语言编写的源代码生成器,以及其设计说明书中的关键知识点。 首先,代码生成器的核心功能在于根据预设的模板或规则,自动生成符合特定需求的源代码。这款C#代码生成器专注于生成DAL层...
"自己编写的简易的代码生成器,c#代码编辑,纯手工打造" 描述了这个工具的两个关键特点:首先,它是作者独立编写的,意味着它可能具有独特的设计思路和功能,可能并不像商业软件那样经过大规模的测试和优化,但可能...
《Java源码:懒惰者代码...总之,通过对"懒惰者代码生成器IdlerCodeGenerator"的源码学习,我们可以提升自己的Java编程技巧,理解代码生成器的工作原理,同时也能借鉴其设计思路,为自己的项目开发带来灵感和实践指导。
3. **基于Ant+Velocity的简单代码生成器的思路与实现 - - Java - JavaEye论坛.mht**:这个文件可能是一个论坛帖子的存档,展示了使用Ant和Velocity构建代码生成器的具体步骤和案例讨论。 4. **velocity(1).rar** 和 ...
在介绍这项技术之前,我们需要了解现有的代码生成器通常基于数据库的元数据来生成基础的增删改查(CRUD)代码。这些代码生成器虽然能够自动完成代码的初步生成,但往往不能完全满足业务需求,还需要开发者进行大量的...
5. **代码生成器**:系统提供的代码生成器是一个辅助开发工具,它可以自动生成部分基础代码,如DAO、Service、Controller层代码,减轻开发者的工作量,提高开发效率。这通常基于数据库表结构,自动生成对应的Java...
通过以上知识点的学习,开发者可以理解如何使用Java Swing构建GUI界面,结合Velocity模板技术,创建一个自定义的代码生成工具,满足特定项目的需求,同时也可以借鉴这个工具的设计思路,为自己的项目定制类似的解决...
《动软代码生成器源码解析与应用》 在IT行业中,提高开发效率是每个程序员追求的目标之一。动软代码生成器(BW.Codematic)就是这样一个工具,它以其强大的模板生成功能,大大简化了程序员的编码工作,使得开发者...
5. **激发灵感**:即使不直接使用,浏览各种模板也能激发新的设计思路和创意。 总的来说,这些免费的CSS模板为网页设计师和开发者提供了丰富的资源,无论是用来学习、实践还是加速项目进度,都能发挥重要作用。通过...
自定义表单设计思路 本文主要讲述了自定义表单设计思路的总体规划,旨在满足和现有工作流系统的耦合,通过对自定义表单系统的设计来实现表单权限、记录权限、字段权限等功能。下面是自定义表单设计思路的详细内容:...
生成器的设计可能基于对常见编程模式和任务的抽象,通过预设模板或规则自动生成相应的代码片段。 【描述】"简易的C语言生成器"表明该工具设计简洁易用,旨在降低C语言学习曲线,使用户能够更专注于解决问题而不是...
8. **答辩与论文**:在毕业设计中,通常需要撰写关于项目实施的论文,详述设计思路、技术选型、遇到的问题及解决方案。答辩环节则需要向评审委员会展示项目的实际功能和创新点,以及在开发过程中的学习和成长。 9. ...
您刚刚下载EnterpriseExtjs.rar中,包含WMC2.0-Client.zip文件,... 并且WMC2.0-Client.zip作为客户端开发框架,您是不需要写任何代码的,我们提供代码生成器帮助你实现基于EntityFramework+Extjs+MVC架构的快速开发。
垃圾文章生成器通常采用两种技术:一是基于模板的生成方式,通过随机替换模板中的关键词和短语来产生文章;二是基于自然语言处理的算法,如词嵌入和语言模型,利用机器学习技术生成看似通顺但实际意义不明确的文本。...
标题中的“基于模板的药品名称识别系统源码&python毕业设计.zip”表明这是一个使用Python编程语言,特别是Django框架开发的毕业设计项目。这个系统的主要功能可能是通过预先设定的模板来识别药品名称,可能用于医药...
课程设计报告部分,会详细阐述项目的背景、目标、设计思路、实现方法、遇到的问题及解决方案,可能还会包括性能测试和未来改进的方向。报告应遵循学术写作规范,包含引言、技术实现、结果展示、讨论和结论等内容。 ...
分离模型与模板,以达到模型重用的目的,模型的加载由模型构建器完成,模型构建器支持自定义,以满足多样的代码生成需求。 框架的执行流程主要是: 1.easygen框架加载主配置文件config.json 2.根据config.json中...