代码自动生成和抽象

  原文: http://dev.csdn.net/article/29/29128.shtm

 

代码自动生成和抽象

Hoping (原作)

 

基本概念

抽象在软件开发中的重要性是不言而喻的。如果一个系统有了正确的抽象,那么这个系统就更容易理解,更容易维护,开发起来也更为高效,最为重要的是也更容易把事情作对。Grady Booch甚至认为抽象是应对软件复杂性最为有效的手段。在面临一个复杂的系统时,往往只要再提升一层抽象层次(当然要是正确的抽象),那么该系统就会立即变得清晰、简单,理解、开发、维护起来也更为容易一些。不过,值得注意的是,虽然有了一个正确的抽象后,可以大大降低理解、开发和维护的难度,但是要想得到一个正确、合适的抽象却是非常困难的。

 

提起代码自动生成,可能大多数人立即会想到这样一种情形:只要获取了系统的需求,那么就会自动地从这些需求生成系统的代码。这种想法固然很好,但是在目前的科学发展水平(这种技术不单是软件技术的问题,它还和人思维的生物基础有密切关系)下却还无法实现。需求和能够自动转化为代码的精确的形式化规范之间有一个巨大的鸿沟,目前这项转换工作还只能由人来独立地完成。因此,这种技术在目前来说只能是一个神话。我们在本文中所指的代码自动生成是针对比较局限的领域而言的,即需求已经被正确的理解并由人转化为解决方案领域中的抽象模型。代码自动生成并不是为了替代人去完成系统的软件开发的,它只是一种支援抽象的工具而已。

 

领域特定语言(DSL

其实,大家在每天的软件开发中都在不经意的使用着这项工具。当我们在使用面向对象语言进行软件开发时,其实我们是在一种抽象的层面上进行工作。有了这层抽象,我们所编写的软件就会更有表现力,更为简洁。比如:当我们写下下面的代码行时:class  Cat  extends  Animal我们想表达的是Cat is a Animal,面向对象语言为我们提供了强有力的支持。而这个抽象的实现细节则由编译器来完成,我们无需关心。这样我们就能够在一个更高、更直接、更易于理解抽象的层面进行开发和交流,同时也大大降低了出现错误的机会。当我们使用支持泛型或者AOP的语言进行软件开发时,其实我们是在另外一种抽象层面上工作。比如:当我们写下如下代码时:

template

T Add(T, T)

我们想表达的是求两个类型为T的变量之和,而不管T到底是什么具体类型。想想看,如果语言不支持这种表达规范,我们要写多少个雷同的Add方法。有了这种表达规范,我们就可以直接、简洁地表达出我们的意图,而具体的转换工作就有编译器代劳了。还有,如果我们在支持AOP的环境中进行软件开发,那么我们只要使用该环境提供的AOP语言规范定义出我们希望的横切关系(其实就是一种抽象),剩余代码的编写和插入工作就由该环境帮我们自动完成了。虽然编译器或者开发环境在底层生成的实际上也是大量重复的代码,但是这些代码的抽象规范却只有一份,而人们开发、维护、沟通所基于的正是这唯一的一份抽象规范,底层的重复实现细节对开发者来说是不可见的,并且是自动和抽象规范保持一致的。可以说,在开发者的头脑中,是没有重复的。从而有力的支持了“once and only once”和DRY原则。试想,如果语言种没有提供这种描述规范,那么我们要编写多少晦涩、难懂、重复的代码才能描绘我们想要表达的概念。

 

上面提到的抽象是一些比较通用的机制,因此一般都是语言内置支持的。也正是其通用性使其有效性范围受到了限制。一般来说,上面的一些抽象机制是仅仅针对开发者群体而言的,并且使用这些抽象机制进行的表达也是由编译器来自动生成底层执行代码的。但是,还有一种抽象表达更为重要,它的作用是在开发者和客户之间进行沟通、交流。说它重要是因为它和所要开发的系统是否能够真正满足客户需要密切相关。这种抽象表达更贴近具体的问题领域,因此也称为领域相关语言(Domain-Specific LanguageDSL))。比如,如果我们开发的是一个金融系统,那么如果我们能够使用一套金融术语及其关系来刻画金融领域中的一些业务逻辑,那么不但表达起来会简洁、直接得多,更重要的是客户也更容易理解,和客户沟通起来也更为容易。再如,如果我们要开发一个科学计算系统,那么如果我们拥有了一套描述科学计算领域的词汇,那么在表达该系统时不但会容易、自然很多,而且也更加高效。有了这套DSL之后,剩下的工作就是要自己实现一个编译/解释器,来把DSL自动生成为目标语言。由于这个DSL一般都局限于某个特定领域,因此其编译/解释器实现起来也不会有多大困难。

 

       敏锐的读者一定会发现,我们在前面列举的支持面向对象(OO)、泛型(GP)或者面向方面(AOP)的语言,其实也是DSL的一种。只不过它们所针对的是更为通用的,和软件要面临的实际问题领域无关的领域。它们的作用是为了提高一些通用问题描述的抽象层次,并且也为构建更贴近问题领域的抽象提供了基础。

 

自上而下 还是 自下而上?

写到这里我突然想起一个非常有趣的问题,那就是大家常常争论的自上而下开发和自下而上开发。一般认为,自上而下的开发方法更具目的性一些,也更为自然一些。其实自上而下的方法是有很大风险的,一是往往很多预先的设想很可能本身就是错的,一是这些预先设想落实到底层时要么无法实现,要么无法很好地适配。其结果就是生成一个具有大量冗余、丑陋粘合层代码的系统。而采用DSL思想的自下而上方法则具有很多你可能没有想到的好处。你可以先实现一些DSL中的单个单词,然后再实现一些更大的单元,并试着把这些元素组合为更大的领域逻辑,按照这种方法实现起来的系统往往更加简洁、清楚、干净,甚至更加易于重用。一般来说,如果你想采用DSL的开发方式,动态语言大有用武之地(PythonRuby都是不错的选择,在www.martinfowler.com/bliki中,Martin Fowler对动态语言和DSL的关系进行了深入、有趣的描述)。

 

自下而上的做法实际上是在改变、扩充开发语言,使其适合于所面临的问题领域。当你进行软件系统的开发时,你不仅仅只是把你所构思的程序直接映射到实现语言,同时你还不断对语言进行增强,使其更加贴近你所构思的程序,并且表达起来能够更加简单、更加直接。比如:你会想语言中如果有了这个操作符,表达起来就更加清楚、简洁了,那么你就去构建它。这样,语言和程序就会一同演化,直到二者能够形成一种完美的匹配关系。最后,你的程序看起来就会像是用专门为它设计的语言开发的。而当语言和程序能够很好地相互适合时,所编写的代码也就会更清晰、更少、更有效。

 

       值得注意的是,自下而上设计相对于自上而下设计来说,并不意味着用不同的顺序来编写同样的程序。当采用自下而上设计时,常常会得到一个和自上而下设计不同的程序。所得到的不会是一个单一的单片机(monolithic)程序,而是一个具有更多抽象操作符的更“大”的语言和一个用该语言编写的更“小”的程序。此外,这个语言的抽象操作符也很容易在其他的类似的程序中得以重用,所编写程序也更加易读、更加易于理解。

 

       还有一点值得提出,那就是自下而上的开发方法可以尽快地得到来自代码的反馈,可以及时进行重构。我们大家可能都已经知道,设计模式一般是重构的目标,这里我想特别指出的是:DSL往往也是很好的重构目标。

 

抽象、库和DSL

C++之父Bjarne Stroustrup经常强调的“用库来扩充语言,用库来进行思考”( http://www.artima.com/intv/elegance.html有近期对Bjarne Stroustrup的采访,他再次强调了这个问题),其实就是在强调DSL以及自下向上开发的重要性。库就是DSL的一种形式,Bjarne Stroustrup所列举的科学计算库的例子就是科学计算领域的DSL。构建库的过程其实就是在朝着更加贴近问题领域抽象的方向迈进。明白了这一点,我们就不难理解Bjarne Stroustrup一直强调的泛型在构建一个优雅、高效库的方面的重要性了,因为泛型为构建这种抽象提供了一个坚实的基础。

 

       不仅C++如此,其他一些语言(比如:Java)也拥有众多的库。这些库在我们进行软件开发时,为我们提供了强大的支持。不过,这些库往往都只实现了它所针对领域的一些通用基础性的问题。因此,在某些特定问题上,可能无法直接地使用这些库来进行表达。此时,你就应该考虑建立一个特定于自己问题的特定库了。

 

结论

      作为开发者的我们,该如何做呢?正如本文开始所说的,抽象固然很好,但是要找出适合于自己手边问题的抽象是一件很困难的事。它应该是一个不断从代码编写中得到反馈,然后再修正,接着再编写代码的循环反馈的过程,这也是我为何认为自下而上开发更为有效的原因。我们不应该局限于仅仅会使用某一种工具,某一种开发环境,而应该多想想这些工具、开发环境背后蕴涵的思想。我们应该注重于培养自己发掘抽象的能力,这方面能力的培养既需要很好的和客户沟通的能力,同时还需要有坚实、高超的软件能力。

 

此外,近期热的不能再热的技术MDA,其核心思想其实就是DSL,不过我对于其试图使用一种语言来刻画所有领域模型的做法并不看好。与其使用它,倒不如逐步演化出一个特定于自己问题领域的Mini DSL和一个DSL编译/解释器,并基于这个DSL来进行开发,这样或许更为直接一些,更为轻便一些,更为清晰一些、更为有效一些,更加具有针对性一些,也更为经济一些J

 

参考文献

[1]  Eric Steven Raymond, The Art of Unix Programming

[2] Eric Evans, Domain-Driven Design: Tackling Complexity in the Heart of Business Software

[3] Andrew Hunt, David Thomas, The Pragmatic Programmer:  From Journeyman to Master

[4] Grady Booch, Object-Oriented Analysis and Design with Application

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于模型的autostar自动代码生成是一种利用软件工程技术将模型自动转化为可执行代码的方法。它结合了建模和编码的过程,将模型转化为程序代码,从而简化了软件系统的开发过程。 在基于模型的autostar自动代码生成中,首先需要建立系统的模型。这个模型可以是结构化的、形式化的、图形化的或者是文本化的描述。模型可以包括系统的需求、行为、限制和其他相关方面的信息。 然后,通过autostar工具将模型转化为可执行代码。这个转化过程是自动进行的,autostar工具会根据模型中的规约和约束来生成相应的代码。生成的代码可以是常见的编程语言(如C++、Java等)或特定领域的语言(如Simulink等)。生成的代码具有良好的结构和可读性,可以直接用于软件系统的开发。 基于模型的autostar自动代码生成具有一些优点。首先,它可以有效地减少人为错误,因为代码是由工具自动生成的,避免了手动编写代码中的疏忽和错误。其次,它提高了软件系统的可维护性和可重用性,因为代码是从模型生成的,模型的修改可以直接反映在代码中,减少了维护的成本。此外,它提高了软件开发的效率,因为代码的生成和更新是自动进行的,开发人员可以将更多的精力放在系统设计和测试上。 总的来说,基于模型的autostar自动代码生成是一种有助于软件开发的工具和方法。它可以提高开发效率、减少错误,并提高软件系统的可维护性和可重用性。 ### 回答2: 基于模型的autostar自动代码生成是一种利用软件工程中的建模技术,根据设计模型自动生成符合标准的代码的方法。它是一种现代化的软件开发方法,能够大大提高代码开发的效率和质量。 在基于模型的autostar中,首先需要对软件系统进行建模。建模的目的是将软件系统的需求、功能、结构等抽象化为模型,以便后续进行代码自动生成。建模可以使用统一建模语言(UML)等标准化的建模语言,将软件系统的各个方面进行描述和定义。 建模完成后,模型将会被输入到autostar的代码生成工具中。这些工具通过解析模型,自动生成符合编程语言语法和规范的代码代码生成工具可以根据不同的语言、框架、平台等要求进行配置和定制,以生成特定的代码。 在代码生成工具生成代码的过程中,可以应用一些模板和规则引擎来指导代码的生成。模板提供了代码的结构和框架,规则引擎则提供了代码生成的规则和逻辑。通过这些机制,代码生成工具可以根据模型的定义和要求,生成出高质量、标准化的代码。 基于模型的autostar自动代码生成具有许多优势。首先,它可以极大地提高代码开发的效率,避免了手工编写代码的繁琐过程。其次,它可以减少人为错误的产生,提高代码的质量和可靠性。此外,它还可以提升团队协作的效率,减少沟通成本和风险。 尽管基于模型的autostar自动代码生成方法在一些简单和标准化的场景中表现出色,但在复杂和定制化的情况下,仍然需要人工干预和调整生成的代码。因此,在使用基于模型的autostar自动代码生成时,需要结合人工的智慧和经验,确保生成的代码符合实际需求和业务逻辑。 ### 回答3: 基于模型的Autostar自动代码生成是一种软件开发的方法,通过使用模型驱动的方法自动生成代码。它将建模和代码生成技术相结合,以实现快速、高质量的代码生成。 对于传统的软件开发过程,开发人员需要手动编写源代码,这是一个费时费力且容易出错的过程。同时,开发人员还需要花费大量时间进行代码调试和测试。而基于模型的Autostar自动代码生成可以自动化这个过程,从而提高开发效率和代码质量。 在基于模型的Autostar自动代码生成中,首先需要建立一个模型。这个模型可以使用各种建模语言来描述系统需求和设计。然后,通过使用代码生成器,将模型转换为相应的源代码自动生成的源代码可以包括各种编程语言代码,如C++、Java等。这些代码可以包括类定义、函数定义、变量定义等。生成的代码遵循一定的编程规范和设计模式,以确保代码的可读性、可维护性和可重用性。 基于模型的Autostar自动代码生成具有以下优点: 1. 提高开发效率:通过自动代码生成,开发人员可以节省大量时间和精力,快速生成大量源代码。 2. 提高代码质量:自动生成代码是基于模型的,可以避免手动编写代码时的一些错误,提高代码的正确性和可靠性。 3. 提高系统可维护性:使用模型驱动的方法,可以更好地对系统进行设计和改进,使系统更易于维护和演化。 4. 促进团队协作:通过共享和修改模型,团队成员可以更好地协同工作,减少沟通和集成问题。 不过,基于模型的Autostar自动代码生成也存在一些挑战。例如,建立准确的模型需要开发人员对系统需求和设计有深入的理解;模型和代码之间的映射关系需要仔细定义和维护;生成的代码可能不符合特定的编程风格或性能要求,需要进行手动修改。 综上所述,基于模型的Autostar自动代码生成是一种强大的软件开发方法,可以提高开发效率和代码质量。然而,在实际应用中,需要权衡其优点和挑战,选择适合的应用场景和工具
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值