自动化编码(Code Generation)的探讨与实现
摘要
现今阶段软件开发越来越成熟,开发人员关注的焦点从以前的编程到如今的系统设计。软件的代码越来越向一致化的方向发展,编写大量的类似代码却频频在开发中出现。这就要我们去解决这个问题:如何降低程序员的工作量,更加突出系统设计,让程序员更加轻松,让软件更加高效稳定。本文提出了利用自动化编码的方式来解决这个问题,在本文中我们将会探讨几个问题:什么是代码生成?为什么要代码生成?代码生成适合在哪些场合?如何去设计和实现自己的代码生成器?代码生成器在项目和产品中的应用现状是怎样的一个状况?使用代码生成会给项目带来什么样的风险?我们将一一讨论这几个问题来了解代码生成器,并且探讨它给软件开发带来怎样的优势。
关键词:自动化编码、代码生成器
名词解释
[1] MDA:模型驱动的体系MDA(Model Driven Architecture)是由全球最大的软件工业标准化组织OMG(Object Manage Group)提出,MDA是经过OMG推出CORBA、OOP、UML等标准之后,大力推广的一套体系标准。
引言
人类发明了计算机来让它做那些枯燥无味的事情,而将自己解脱出来,去做有创造性的事情。使用 Code Generation将使开发人员从单调无味的代码中解脱出来,去做更有创造性的设计。
在现在的软件开发中,程序员们需要手写代码。为什么不能够让机器写代码呢?那么,以后程序员就不是程序员了,而是设计师,他们设计能够自动写程序的程序。如果这个思路得到普及,软件行业的生产力也会得到飞速的提升,软件开发也会进入一个工业时代。
这个思路就是CodeGeneration。这个技术其实并不是什么新思路,我们平时使用的IDE环境中都大量使用了CodeGeneration。只是这项技术仍然不够普及,大家平时在编写程序的时候,缺少一种代码自动化的意识。
一、什么是代码生成?
代码生成是使用程序生成代码的一种技术。这些程序包括从很小的帮助性质的脚本,到创建大量完整应用程序中的业务逻辑模型。对于代码生成应用软件,并没有一种固定的模式,可以使用命令行或者GUI,它们可以创建一种或多种程序语言的代码,可以多次创建代码。没有固定的输入和输出。代码生成的共同的特点就是生成器的输出是代码,这些代码是可以通过手工编写来完成的。
二、为什么需要代码生成?
软件工程中有两个永恒不变的定理:
1、 程序员的时间是很宝贵的。
2、 编程并不是重复无聊的工作。
代码生成解决了软件开发中编写重复代码的无聊工作,采用了自动化的形式将重复代码按照程序员定制的规格由特定的程序产生。这样程序员将有更多的时间去关注软件在设计上的问题和扩展,有时间和精力去挑战更高难度、他们自身感兴趣的工作。将程序员从烦闷的复制粘贴中解脱出来,这才能更好的发挥他们自身的聪明才智。
代码生成不仅仅是避免了一些繁琐无聊的编程工作,它更多的是给软件开发以下面六个方面的优势:
1、 开发效率
当代码生成器第一次运行的时候,对于代码生成技术的这一好处是很容易认识到的。你从输入一些对输出代码的设计中所需的输入开始,几乎就在同时,你得到了你的设计所实现的代码。无论怎样,真正的高效率就在你运行生成器来创建基于设计的代码时就开始了。你有几次看见一个项目的需求没有变化过?这就是基于变化的需求生成代码的能力
2、 产品质量
通过代码生成器生成的代码的质量是由用来生成目标代码的代码和模版的质量决定的,当这些代码和模版的质量提高时,重新生成的代码的质量基于此也会提升。
3、 代码一致性
由代码生成器生成的代码有很强的一致性,变量命名,方法命名,类命名都通过相同的方式创建。这些使得生成的代码便于使用和分层。
4、 抽象
一些生成器基于目标代码的抽象模型来创建代码。比如:你可以创建一个sql Schema 和数据访问层代码,从xml中定义数据库中的表,字段,关系和查询。这种抽象的价值在于生成器可以重新定位以创建其他平台上的代码。这意味着你的业务逻辑和规则拥有了可移植性。而你不必为不同的平台编写代码。
5、 开发成本
当然在第一次开发生成器的时候,它所付出的代价会比较高,需要有不少的人力物力去设计、实现、测试。这也属于软件本身的一部分风险投资,如果生成器开发完成,并且初步投入使用没有发生重大问题,那么它对项目组以后的开发就有不可估量的作用。在加快开发进度的同时,也就意味着开发成本的降低。项目组可以在短时间内高质量的完成项目开发甚至测试,这样无形中就将人力物力财力都降下来了。所以成功开发出代码生成器,意味着一劳多得,可以一直延续用下去,当然你还需要对它不断的维护和优化,精益求精。
6、 软件风险
软件项目的风险无非体现在以下四个方面:需求、技术、成本和进度。那么代码生成器在这四个方面体现出什么样的价值呢?因为代码生成器的生命周期是在项目的开发阶段,所以它对于需求分析带来的风险无能为力。但是对于技术风险,生成器是可以把握的。
我们从整体上分析了代码生成器对软件开发带来的效益,也简单的讨论了对于程序员、软件工程师,代码生成器意味解放:抛弃繁重的重复代码编写工作,突出设计决定。
然而前线是前线,更往上层是管理人员和公司,怎么让你的老板接受你的代码生成器呢?对于管理人员、公司,代码生成器存在的理由是什么呢?
代码生成可以给项目管理以很多好处,比如提高了生成效率和产品质量,这是不容置疑的。但是,真正的优势却在于业务层和管理层,让我们看看代码生成给业务层和管理层带来了什么:
1、 结构一致性
项目采用了代码生成使得项目的整体结构在软件生命周期的前期就已经确定,这个举措有三点优势:
1) 鼓励程序员在确定的结构中工作编程
2) 当代码生成不能完成我想要的工作的时候,这是一个设计偏离现有结构的暗示
3) 一个有详细文档可维护性好的代码生成工具提供了一致的结构和方法,即使团队成员离开,新成员也能很快地着手工作
2、 抽象性
代阿生成工具已经将应用逻辑呈现出来,包括业务逻辑、数据库定义文件、页面定义等等。从应用中抽象出这些语义并且实现有以下几个好处:
1) 可以随时通过新建模板将逻辑应用到其他程序语言或者其他平台上,这比手工编码要容易的多。
2) 业务分析员可以检查和验证抽象的设计以确保业务无误。
3) 在抽象层上提取应用的语义可以将设计和实现分离,降低系统的耦合度。
3、 高昂的士气
如果项目期限很长,会让团队难以忍受,如果项目中有大量无聊乏味的重复代码编写工作,那么情况将更糟。代码生成器减少了程序员的工作,加快了项目时间进度表,让程序员可以有更多的时间去关注他们感兴趣的工作。同时由于代码生成器产生的代码有高质量、一致性等特点,项目成员对项目将会更加有信心并且引以为豪。
4、 快速开发
代码生成器最重要的特点之一就是易扩展性,可以对需求的改变快速的作出反应,在很短的时间修改程序以适应新的需求。
所以,我们看到代码生成有那么多好处,还要坚持要手工写代码吗?还要去忍受那些无聊繁重、重复的代码吗?还需要拷贝-粘贴-替换吗?
当然是不需要!
三、代码生成适合在哪里场合
既然我们前面阐述了那么多好处,为什么我们不到处都使用代码生成?但是事实上,任何事物,只有在适合的场合才能发挥出它的最大功效,代码生成也是如此,如果场景错误,那么可能会造成无法估计的损失,那么代码生成在哪里适用呢?笔者认为当程序员遇到如下的情况的时候,可以考虑使用代码生成:
1、开发一个成熟的代码生成器也是需要付出很多代价的,所以代码生成器必须是在项目开发中有大量的类似的代码。而这种情况最常出现在数据库访问和用户界面上。
最多的是用在数据库访问方面,因为数据访问的代码是重复性非常高的。另外,生成数据访问层为提供了技术平台的可移植性和平台可移植的益处提供了标准。
用户界面编码也有很大的重复性,所以它也成为生成器的通常的目标。另外,一个用户界面生成器也可以提供多方面的实现,比如针对同一份定义,生成胖客户端和瘦客户端。
2、你必须考虑设计和表现层的稳定性。当表现层不是非常稳定的时候,或者是设计需要发生变化的时候,在全盘使用代码生成之前你首先要考虑手工编写原型代码。
3、单一的代码生成器不是万能的,必须要和其他的工具结合起来才能合适地解决特殊的问题,代码生成器使用得当将会非常强大,同时在错误的环境中使用将使项目变得繁重艰难。
四、如何去设计适合的代码生成器
每个人遇到的问题都是不一样的,我们可以把代码生成器看作是一个产品,而项目组成员是用户,那么每个用户的需求是不一样的,每个程序员要求代码生成器所要做的事也是各式各样的。那么我们在这里来讲设计就是不可完成的任务,也是不可靠的。但是有一些原则它们是可以抽象出来成为代码生成器的共性,以下讨论10个设计原则:
1、对手工编码要持尊重和憎恶的态度
尽管代码生成可以免去许多重复的工作,提高开发效率,但是你必须知道无论你的生成器有多么强大,多么灵活,都有很多特殊情况存在,这些可能都在你的代码生成器可归纳的范围之外。所以,虽然你使用了代码生成器,但是手写代码仍然是必需的。
2、先亲手写代码
即使有必要使用代码生成,也要在你确定你了解你的框架的时候再开始使用它。
3、控制源代码
一个好的源代码管理系统是代码生成项目成功的必须的。如果你的生成器操作了已经包含了手写代码的文件,你就更需要一个版本管理系统来保障你的工作
4、仔细考虑慎重选择实现语言
用来实现生成器的工具不同于实现应用程序的工具。生成器的一个问题就是它尝试去解决那些应用程序所要解决的许多完全不同的问题。基于这一点,你应当认把生成器作为一个独立的项目来真的选择你的工具。
5、将代码生成器的开发加入到项目开发进程中
生成器是工程师们使用的工具,所以,它应当合理的,完整的结合到开发过程中。可以使它整合到IDE工具中,或者build过程中。
6、包含警告,对错误操作的提示,需要有良好的容错性
生成器生成的代码中应当对那些不应被改动的地方作出警告,以防止被手工改动。如果被手工改动,那么生成的代码的版本就无法保证一致。同时有可能使重要的地方出现不可预期的行为。
7、友好
生成器是给程序员使用的工具,但是这并不意味着它就可以很粗糙。生成器应当告诉工程师他能够作什么,正在作什么,它生成了哪些文件。生成器应当是易用的,界面友好的。
8、务必文档化
好的文档是生成器的一个卖点。你的文档应当完整,清晰,但是不要过多。而且要对关键的地方作特殊的说明,比如生成器能作什么,如何安装,怎样运行等。
9、要记住并不是所有的人都会接受代码生成
给你的同僚们看文档,培训,一个接一个的会议,这些对于你的生成器的成功推广是很危险的。人们对新事物总是充满怀疑,你需要让他们认识到生成器会给他们带来怎样的好处。
10、经常维护
除非生成器只是一个临时的方案,否则在很长时间内都要认真的进行维护,生成器控制着大量的代码,维护生成器和维护代码具有同样的意义,你应当安排专门的时间和金钱来维护、升级它。
五、代码生成器在项目和产品中的应用现状
代码生成所包含的面非常之广,但是对于目前最普遍的层生成器,所使用的技术有很多是共通的。下面简单介绍层生成器所普遍使用的几项技术,以及为你的层生成器选择一门开发语言所要考虑的要点。
从目前的软件应用上看,代码生成有以下的几种实现方式:
1、模板技术:代码生成通常意味着创建具有复杂结构文本类型的文件。为了维护生成器的简单性和完整性,你可以使用文本模板工具,这样你可以把逻辑的定义和逻辑的代码格式相分离,这是最理想的情况。
模板一直以来都是CodeGeneration的主要实现手段。C++使用模板来实现泛型机制。而众多的建模工具和IDE工具都使用模板来重用代码。在Apache组织的旗下,有一个名为Velocity的项目,它的目的就是提供一种易用的模板技术。Velocity使用了一种脚本语言,叫做Velocity Template Language (VTL)。目前,Velocity主要用于生成Web站点的动态内容。此外,还有更出色的FreeMaker,它比Velocity更全面,可以说Velocity是轻量级的模板技术,而Freemaker是一个强大重量的模板引擎,相比velocity而言,其强大的过程调用、递归和闭包回调功能让freemaker可以完成几乎所有我们所想的功能。此外还有很多的模板技术,这里就不一一介绍了。
2、面向属性编程
英文缩写虽然同样都是AOP,但面向属性编程(Attribute-Oriented Programming )和面向切面编程(Aspect-Oriented Programming )可不是一回事。面向属性编程是通过在代码中添加元数据(属性)的方式来自动产生代码,添加功能。而这方面最优秀的软件莫过于xDoclet。
XDoclet 是一个通用的代码生成实用程序,是一个扩展的Javadoc Doclet引擎(现已与Javadoc Doclet独立),XDoclet是EJBDoclet的后继者,而EJBDoclet是由Rickard Oberg发起的。它允许您使用象 JavaDoc 标记之类的东西来向诸如类、方法和字段之类的语言特征添加元数据。随后,它利用这些额外的元数据来生成诸如部署描述符和源代码之类的相关文件。可以让你创建自己的javadoc @tags进而利用XDoclet中的Templet enging基于这些@tags生成源代码或其他文件。
3、MDA(Model Driven Architecture模型驱动架构)
MDA能够将特定的模型转换为特定平台的代码。AndraMDA就是其中的代表者。在具体实现上,AndraMDA主要采用了模板技术,同时,它也利用了xDoclet技术。所以,AndraMDA是在前两项技术的基础上实现CodeGeneration的。
4、正则表达式:用来检索,扫描源文件,以提取你要用到的信息,正则表达式的缺点就是不易阅读。
5、XML:读入XML文件,进行解析,验证,或者把XML文件作为代码生成器的输出。
6、文件目录的操作:几乎是每个生成器都会使用的技术,从文件读入代码格式,将生成的代码写到输出文件中。
7、命令行:命令行有自己的优势,由于代码生成有很多自动过程,所以在有些情况下命令行更高效,简捷。
相应的CodeGeneration技术还有很多,以上只是列出了比较有代表性,影响比较广的几种,详细的介绍了最常用的三种方式。
六、代阿生成在项目应用所存在的风险
我觉得使用代码生成器有风险。使用任何一项新技术,都会带来一定的风险。但我们不能因为有风险就成为不使用的理由,因为如果从不使用新技术的话,就不会有这方面的风险。但另外的更大的风险发生了,企业被客户和社会所淘汰。因此,我们需要对代码生成器所可能带来的风险进行评估。那么它会存在哪些风险呢?
1、程序员不愿意使用代码生成器
我们可以分析一下程序员不愿意使用代码生成器的原因:
1)生成的代码质量太差,看不懂,bug太多。这是选错了代码生成器的原因。
2)生成的代码不支持变化的需求与设计。这是体系架构运用不当的问题。使用代码生成器,使用与代码生成器相适应的的优秀的体系架构和技术,比如比较严格的 界定层与类的功能。
3)代码生成器约束了我的编码思想。实际上这是一个误区。代码生成器造就了千辟一律风格的代码,我写的精致代码反倒成了另类。 风格相同是软件维护容易的一个重要特性。
2、爆炸性错误
由于是机器产生的代码,所以所有的代码都是一样的,这样容易维护,但是同时也带来一个问题:假如代码生成器存在错误,那么所有由代码生成器生成的代码都会存在同一个错误,这时你就不得不修改代码生成器,通过测试,然后再产生一次所有的代码。这个时候新的问题又出现了,如果说你的生成代码经过修改,比如业务变更或者说你的代码生成器并不管业务层(这就意味着业务层代码都是需要手写的),那么你的这些修改如何保存?是继续由生成器生成?还是手工去修正错误?那么数目怎么确定呢?什么地方需要修改呢?一系列的问题接踵而至。这个时候就需要你根据具体情况选择一种改动最轻最不影响系统的方案。同时我们也就要意识到你开发的代码生成器必须要经过严格的测试才能投入正常使用。
代码生成实际上是一个用生成器来替代重复,枯燥的手工编码过程,本身并没有使用任何特别的技术,只是一个简单的替代过程,理论上应该风险是很小的。实际上,现在的代码生成器智能化,可配置性已很高,基本能够生成自己所想要的代码,部分代码生成器商还提供商业化的生成过程,更能满足自己的特定需要。
结束语
代码生成器有好处,同时也存在风险,如何正确地使用它,这需要管理人员和设计人员共同决策。本文我们只是讨论了代码生成器的几个基本问题,还未涉及到具体实现。只是希望读者在看完本文之后,对代码生成器有一个大概的了解,在以后的软件开发中存在自动化编码的意识,在适当的地方使用代码生成技术以提高开发的效率和软件的质量。
参考文献
[1] 代码生成-CodeGeneration
http://youwg.blogdriver.com/youwg/326638.html
[2] Jack Herrington Code Generation in antion Manning Publications (July 1, 200
分享到:
相关推荐
本主题将深入探讨如何利用VBA在Excel中创建自动编码系统。 首先,我们需要理解“自动编码”的概念。自动编码是指根据特定规则或模式生成唯一的序列号或代码,用于标识数据记录。在企业中,这通常用于产品编号、订单...
另外,`juniversalchardet`是Java版的`Universal Character Set Detector`,它是基于Mozilla的`Chardet`库的Java实现,可以自动检测多种字符编码。 总的来说,自动识别编码是处理异构数据时必不可少的技术,Java...
总之,Python结合TensorFlow提供了一种强大且灵活的方式来实现图形自动编码器,这对于处理非欧几里得数据和图结构的学习问题具有很高的价值。理解GAE的工作原理并能正确实施是掌握这一技术的关键。
本教程将探讨如何在Ubuntu操作系统下,通过一个名为confuse的工具来实现自动编码的功能。confuse是一款用于配置文件解析的C++库,它允许开发者定义配置语法并将其转化为程序可读的结构。 【描述】:“virtualbox下...
本文将深入探讨如何使用Python编程语言结合自编码器(Autoencoder)这一机器学习模型来实现图片去噪的设计与实现。 自编码器是一种无监督学习的神经网络模型,主要用于数据降维和特征学习。它的主要思想是通过训练...
在这个例子中,我们使用了Univocity-Parsers库,它支持自动编码检测。`setEncodingDetection(true)`设置允许库尝试识别文件的正确编码。 然而,需要注意的是,自动检测编码并不总是100%准确,尤其是当文件没有BOM...
本文将深入探讨基于车辆自动驾驶的磁道钉编码系统的设计与实现。 一、磁道钉编码系统的原理 磁道钉编码系统利用磁性传感器检测预埋在道路表面的磁性标记(磁道钉),通过读取这些磁道钉的编码信息,为自动驾驶车辆...
本文将深入探讨如何使用C++语言来实现这一算法,并关注其人性化设计和编码效率的计算。 首先,C++是一种强大的面向对象编程语言,它的灵活性和高效性使其成为实现香农编码的理想选择。在设计C++程序时,通常会使用...
本文将深入探讨量子自动编码器的原理、实现方法以及在Jupyter Notebook中的应用。 自动编码器是深度学习中的一种无监督学习模型,主要用于数据的自编码和解码。它们由两部分组成:编码器和解码器。编码器将输入数据...
本篇文章将深入探讨“自动识别不同编码的文本文件”的关键知识点,包括ASCII、UTF-8、Unicode 16 Little Endian和Big Endian四种格式。 首先,ASCII(美国标准信息交换代码)是一种基于拉丁字母的7位编码系统,它...
在此,我们将深入探讨门控注意自动编码器(Gated Attention Encoder,GAE)及其在内容感知推荐中的应用。 首先,自动编码器(Autoencoder)是神经网络的一种,主要用于数据的降维和特征学习。它由两部分组成:编码...
这里我们将详细探讨One-Hot编码的概念,以及如何使用Python从零开始实现它。 首先,让我们定义One-Hot编码。在分类问题中,我们经常遇到离散特征,例如颜色(红色、蓝色、绿色等)。这些特征无法直接被大多数机器...
在本文中,我们将深入探讨如何使用C++进行实时面部地标检测,特别关注“FaceLandmarking”项目,该项目利用决策树和神经网络(NN)自动编码器实现这一目标。面部地标检测是计算机视觉领域的一个重要任务,它涉及识别...
本文将深入探讨一种结合了深度自动编码器(Deep Autoencoder)与Q学习算法的移动机器人路径规划方法。这种方法旨在提升机器人的自主导航能力,降低对外部环境依赖,优化路径选择,提高效率并确保安全性。 首先,...
首先,本文通过分析国内外工程编码系统,指出了在铁路造价信息编码与预算自动化编制研究中存在的不足。由于铁路项目的专业性、复杂性,加之各个项目之间数据的管理和信息交换成本高昂,因此迫切需要一个高效、准确的...
本教程将深入探讨堆叠自动编码机的概念、应用以及实现细节。 去噪自动编码机(Denoising Autoencoder,DAE)是自动编码机的一种变体,它的主要任务是通过在输入数据中引入随机噪声,训练神经网络以重构原始无噪声的...
本篇文章将深入探讨如何利用MATLAB进行JPEG图像的压缩编解码设计与实现。 首先,JPEG压缩的基本原理是通过离散余弦变换(DCT)、量化和熵编码等步骤实现的。在MATLAB环境中,我们可以利用其内置的函数来完成这些...
本文将深入探讨如何使用Qt来实现一个自动升级系统,包括服务器端和客户端的实现。 首先,让我们了解自动升级系统的基本原理。自动升级系统的核心目标是使用户能够无缝地更新软件,无需手动下载和安装新版本。这种...