自动编程:编写可编写代码的代码


105

读完《实用程序员》一书后,我发现最有趣的论点之一是“编写代码编写代码”。

我尝试在网上搜索更多有关它的解释或文章,尽管我找到了一些有关该主题的不错的文章,但仍然没有找到任何特定的代码实现或好的示例。

我觉得它仍然不是一个普遍的论点,缺乏文档或者很多人不接受,我想对此有所了解。

您如何看待这个主题?它会真正提高您的生产力吗?在书籍,博客,幻灯片等中,关于该主题有哪些好的资源?


一些代码示例将不胜感激,使我可以更好地理解其实现。


这是有关该主题的Wiki页面,其中包含各种相关的编程技术,例如元编程,生成式编程和代码生成。


32
我曾经写过写代码的代码,写过代码的代码... :)
Benjol 2011年

9
@Benjol:您是用Lisp写作吗?
compman 2011年

11
此外,服务器端语言始终通过生成HTML,CSS和JavaScript来执行此操作。你可以有一个创建与创建更多的HTML,也没有人会蝙蝠关于它的眼睛,因为如何JavaScript的HTML创建一个服务器端脚本服务器端脚本常见的是。
zzzzBov

8
如果还没有,请阅读以下IBM developerWorks系列文章:元编程的艺术 ”, 第1 部分第2 部分第3部分
约翰·托伯勒

3
AtomWeaver(atomweaver.com)是自动编程的一个很好的例子:首先,您在Lua中创建可重用的微型程序。然后,通过重用这些资产来对系统建模。然后AtomWeaver编织一个Lua程序,其中包含您的“微型发电机”以生成系统的最终源代码。然后,您可以调整模型并重新生成。
瑞库拉多

Answers:


49

在Lisp世界中,看到编写代码的代码和编写代码的代码(等等)是很常见的。因此,任何大小合适的Lisp或Scheme项目都将成为一个很好的代码示例。我建议查看Racket编译器和运行时源以及Bigloo,它们的库非常出色。

至于生产力:在几乎所有开发工作中,我都将元编程用作一种主要技术,这显然会有所帮助,既减少了代码大小,又提高了可读性。关键在于使用领域特定语言,元编程是实现它们的最有效方法之一。


67

我喜欢走得更远一点,而不是编写代码编写代码,写一个生成的对象,方法,功能代码。例如,这可以通过Lisp宏或Ruby动态程序修改功能来实现。

区别不大,您不会以自动生成的源文件结尾。通常,这些文件不是人类可读的,无法修改,所以为什么要打扰他们。我不喜欢使用无法控制的内容来增加代码库的想法。

我最喜欢阅读的一本书是《元编程Ruby》(如果您了解Ruby语言)


在评论中的以下问题之后进行编辑:

为什么我仍然必须对生成的代码进行编码,这为什么有用呢?我是否应该编写一个能够根据用户输入生成不同内容的代码,以便可以反复使用它?

首先,元编程不是目标,而是工具。不要使用元编程,因为“很酷”或“ X表示每个开发人员都应该使用它”。

我认为使用元编程的一个很好的理由是对您在代码中发现的一些通用模式(模式重复)进行概括,而其他常规编程技术(继承性,设计模式等)则无法实现。

正如Jordan所说,一种典型的用例是数据库处理和ORM(对象关系映射)。再一次,在Ruby中,您应该查看ActiveRecord,它是应用于ORM的元编程的一个很好的例子。

最后一点:

不要认为 “我想应用元编程,我可以在代码中将其应用在哪里?”。

想一想: “我看到这种模式在我的代码中不断重复,我找不到一种将代码重构为更小,更可重用的方法。也许元编程可以帮助我?”


3
@Jose:最常见的是您通过模板生成代码。例如,有Apache(N-)速度或Visual Studio T4模板。然后,您只有一个程序,可以将元数据输入到模板中并从那时开始创建新文件。这是很容易,我做的一切来生成UI的骨架,实体等的时间
猎鹰

2
@Jose Faeti,仔细研究Lisp宏(或Clojure或Nemerle,具体取决于您的平台首选项)。
SK-logic

1
我将添加元编程可以替换某些模式,例如策略或状态,但没有运行时成本。这不仅针对通用重构无法解决的问题,而且有时是更好的选择。
deadalnix

1
@Jose Faeti:我知道您知道一些Python。它也具有元编程功能,尽管我还没有真正使用过。看看Dangerously Advanced Python PDF
Kit Kit

3
@Falcon:IMO是生成代码的最糟糕的方法;对于没有内置元编程功能的语言,这是非常差的解决方法。与其生成Java或C#,不如以更高级别的JVM或.NET语言编写该代码。
凯文·克莱恩

19

更好的是,使用别人编写的代码为您编写代码。

代码自动化通常对于ORM和其他数据库交互代码很有用,当然对于重复但相似的代码构建也很有利。

当然,如果您要构建许多外观相似的类,也许您可​​以更快地用动态语言完成相同的事情,但是我离题了。

尽管您经常会发现该软件被标记为代码生成器,但许多人都拥护它。

查看公司和产品,例如CodeSmith和MyGeneration,或浏览以下Wikipedia文章:http : //en.wikipedia.org/wiki/Comparison_of_code_generation_tools


6
这没有什么好。您自己的宝贵的很少的代码无法由其他bloke的代码生成工具正确管理,因为其他bloke对您的细节一无所知。元编程最有生产力的用途是实现领域特定的语言-顾名思义,它们特定于您的问题领域,除您之外,其他任何人都无法实现。
SK-logic

@ SK-logic:ORM生成的代码如何?它是由另一个工具/库生成的,仍然可以满足许多项目需求。
大卫,

@David,老实说,我对通用ORM并不十分信服。过去,我在使用它们时遇到了很多问题,通常是依靠实现自己的特定ORM来实现。
SK-logic

1
@Jordan,所有这些工具都太具体了(更糟糕的是基于文本,即在设计上次于标准)。我是在谈论正确的元编程。
SK-logic

1
@AtillaOzgur,它们可以是“很好”,是的。但是它们并不比eDSL好。与宏元编程相比,独立代码生成显然受到更多限制,灵活性也大大降低。
SK-logic

16

lex和yacc是经典示例之一。它们的主要目的是避免编写任何类型的解析器的繁琐工作。在此过程中,它们使构建具有许多规则和状态的复杂解析器的速度大大提高,并且还避免了由于人们自己滚动而造成的所有意外错误。

这也是c的想法,c是编写汇编程序的工具。对于您想命名的任何高级语言而言,这也是一样。对于为您编写代码的工具,有一些简单的范例。

适当的IDE可以帮助您提供唾手可得的文档,智能的自动完成功能和代码段。IDE还包括各种模板,因此您不必从头开始编写程序。有一些程序可以绘制一个uml图并以一种高级语言来粗化类。

最后,您可以在自己的问题集中编写自己的代码生成工具。这就是lex和yacc第一次开始的方式。正是由于这个原因,存在任何一种特定于领域的语言。您创建了一些构建块,这些块以易于理解的代码描述了您的解决方案,总结了常见的活动,或者使用简单的命令来描述了复杂的部分。您并不是在寻找所有问题的解决方案,而只是简单地定义了要处理的特定问题。

从某种意义上说,您在二进制层之上执行的所有操作都是代码自动化。


这是一个非常好的观点。总之,这只是程序员尝试用来促进其操作并专注于更高级别的编码(而不是语法代码详细信息)的众多方法中的另一种。
Jose Faeti 2011年

1
@Jose Faeti Wikipedia文章en.wikipedia.org/wiki/Automatic_programming提供了指向各种不同工具的链接,如果您对更多详细信息感兴趣的话。我还建议您阅读lex和yacc,因为它们的文档和描述很多。
Spencer Rathbun

在足够强大的语言(例如,相对于C的C ++)中,不需要lex和yacc之类的外部工具。
凯文·克莱恩

YACC不会编写“任何类型的解析器”。它编写了一种特定类型的解析器(LALR),如果没有自动帮助,它很难实现。还有另一种解析器(递归下降),它更容易编写和正确使用,并且相应地更容易阅读和理解正在发生的事情。
梅森惠勒2012年

@MasonWheeler解析器的种类是指可以为广义,非精确意义上的问题解决而创建的语法。一年后阅读它,并没有我想要的那么清晰。我不确定我是否同意LL(*)解析器更容易编写和使用。
Spencer Rathbun 2012年

13

元编程

元编程是许多商店中有争议的技术。原因是,像任何强大的工具一样,帮助或伤害的幅度很大。

优点

  • 更具表现力,编写和维护的代码更少(通常增加一个数量级或更多)
  • 使用代码解决的问题类别上的一致性,更一致的行为
  • 生产力高,代码少,可解决更大的问题空间

缺点

  • 复杂性,即使代码更少,也可能非常复杂
  • 安全性,有时会牺牲类型安全性和静态分析
  • 错误影响更多,小错误将产生更大的影响

我是一个巨大的元编程的粉丝,但我已经做了很长一段时间。对我来说,减少代码大小和保持一致行为的权衡远不能弥补风险。更少的代码意味着更少的错误,更少的代码维护,而且我通常可以非常快速地添加大量功能。

但是,这并不意味着我认为所有程序员都应该参与其中。我已经看到并且不得不解决元编程所产生的大问题。通常从不了解概念并尝试扩展功能或仅修复错误的人开始。它需要一种特定的思维方式,至少要注重细节。 使用元编程技术的问题应该是团队的决定。如果您的团队成员不了解,没有脾气,或者只是反对它,那么任何团队都不应该使用元编程。


感谢您的有用考虑!您能建议我使用元编程来实现一个非常简单且基本的任务吗,这将使我节省一些比普通代码少的时间,只是一个简单的代码示例?
Jose Faeti 2011年

哈哈,让我想起几年前与GCC发生的错误。162行将错误消息显示在我的屏幕上。递归元编程FTW!
deadalnix

6
元编程的复杂性被高估了。只要使用正确的工具,其中绝对没有复杂的东西。而且DSL比典型的样板代码容易调试和维护。另外,我不明白为什么要牺牲类型安全性-恰恰相反,DSL也可能具有特定于域的高效类型系统。
SK-logic

2
@ SK-logic:并非所有语言都很好地支持元编程。因此有时会牺牲诸如类型安全性之类的东西(即C)。元编程也不只是DSL。它包括诸如调度样式编程,泛型,currying,对象检查,动态应用程序之类的东西。至于复杂性,我认为对我们(具有元编程经验的人)说起来并不复杂。我在理解所有将在其下执行代码的情况下还遇到了其他困难。这主要取决于他们的经验和所涉及的技术。
Dietbuddha

@dietbuddha,请您详细说明一下,无论如何实施,为什么都要牺牲自己的DSL的安全性?您可以在具有强大类型系统的纯C语言中编写临时解释器(例如,参见Hugs)。您可以编写一个针对C的代码生成器,它自己执行所有类型检查,而不依赖于目标语言类型系统。出于复杂性考虑:大多数人都以不必要的复杂方式进行操作,而所有相同的设计方法都可以像“常规”编程中那样应用于代码生成。几乎不需要新知识。
SK-logic

9

大多数代码编写代码。例如,php代码有助于编写html。php pdo库可帮助编写SQL调用。文件I / O功能编写代码以与OS通信。甚至常规的函数调用都引用了另一个要执行的代码块。因此,您的函数调用正在编写代码。

从广义上讲,我们可以将计算视为编写代码,该代码以递归方式编写代码,形成一个堆栈,当堆栈遇到连接到硬件的代码的物理现实时,该堆栈终止。


3
我不会将html称为编程语言。这是一个文档的syntaxe
西蒙Bergot

3
@Simon有趣的一点。我们使用的不同代码具有各种各样的表达能力。代码可以用较弱的语言,较强的语言或它自己的语言编写。
Ben Haley

5

您的操作方式因您的要求而异。假设您使用的是静态代码生成,则可以自己编写所有基础结构,也可以使用现有的生成器,例如CodeSmith或MyGeneration。使用这些,您只需要编写所需的模板。

我涉及的最后一个项目是一些基本的ASP.NET CRUD屏幕(代码生成对此非常有用)。该过程将实体定义为xml文件中的元数据。编写模板以涵盖所需的各种工件(实体类,存储库,服务类,asp.net控件,asp.net页面等)。运行生成过程并设置输出样式。

编写模板会有一些开销,但是可以将它们重新用于后续的类似项目。类似地,通过更改元数据并重新运行生成,可以处理基础数据的更改,从而使更改更容易实现。

至于测试。由于这是一个模板化的系统,因此您将需要花一些时间来初步验证流程的输出,如果模板错误,则该模板的所有输出也将同样错误。一旦对此感到满意,还可以使用代码生成器从xml元数据创建基本测试,然后将其扩展以涵盖特殊情况。但是请记住,您可能仍需要进行代码测试来满足特定的需求,代码生成会减少您的工作,但并不能完全消除它。


5

在我们公司中,我们使用一些工具,这些工具实际上使用从互联网下载的数据生成C ++或C#类。这些类是数据容器,并且在列表中包含大量对象。


例如在某些IDE(例如Visual Studio)中找到的代码片段?
Jose Faeti 2011年

@Jose我们的工具只是一个将HTML输出转换为类的应用程序。因此,与其每次应用程序启动时不下载数据,我们都下载一次并制作一个类。
霍利

5

元编程已经是编程的一部分了。不仅要考虑诸如SWIG之类的工具或创建代码的WYSIWYG设计器,还要考虑诸如C的预处理器甚至C ++的模板和C#/ Java的泛型之类的语言工具-更不用说反射了。

实际上,您可能会争辩说,每个编译器只是另一个元程序-他们采用程序文本以及输出机器或VM代码。而且,没有编译器的生活?哎呀


没错,但是您如何才能以自己的编程语言实际实现它以实际提高生产力?那就是我所缺少的。
Jose Faeti 2011年

5

这是我过去的一个具体例子。

我在一个使用BDE进行数据访问的大约50MB Delphi源代码的站点上工作。他们想切换到使用Direct Oracle Access,以允许Oracle升级到BDE支持的最高版本(如果我没记错的话,升级为8i)。

因此,我没有让编码团队来手动处理每个表单和数据模块来更改每个组件,而是编写了一个PERL脚本,该脚本:

  1. 解析DFM(表单文件)并标识所有TQuery,TTable,TStoredProcedure和TDatabase对象-将项目存储在列表中。

  2. 解析PAS(代码)并确定对象的用法-TQueries是在进行更新还是选择?同样,它可以识别用代码创建的所有对象,而不是放在IDE中的表单上。

  3. 重新编写DFM和PAS,以适当地更改对象类型(例如,将TTable-> TOracleDataSet的SQL属性设置为“ select * from”等)和方法调用。此外,如果适合关闭,打开和设置参数,则添加了额外的方法调用。

简而言之,需要花费3个星期的时间来调整脚本,使其能够在具有不同编码风格的不同团队编写的不同应用程序上工作,而不是最初的估计5个以上的开发人员要工作6个月。

我什至想到使用这种方法的原因是通过阅读The Pragmatic Programmer


太好了,从现在开始我就进入Perl了几天,我已经制作了一些生产力工具,只需键入“创建工作区”即可生成用于Web开发的基本工作区,以及所有目录,文件等!:)
Jose Faeti 2011年

1
@Jose就是这个主意。使用脚本语言自动执行重复的内容。一次性可以将生产率提高8倍,或者在某些情况下要一次又一次地浪费时间。
mcottle

4

你问例子。

使用SQL时,您不应该直接更改数据库,而应该执行执行所需更改的脚本,包括对数据库的结构更改(添加表,列,主键,约束等)。 。通常,您将需要同时对许多表或列执行相同的操作,并且一件一件地做它们会很乏味,这是一个简短的脚本,可以输出较大的脚本来满足您的实际需求省时间。

例如,在将DATE数据类型引入MS SQl Server之前,日期列的唯一选择是DATETIME,它具有时间部分-时间部分使处理数据更加困难。升级到具有日期数据类型的版本后,您可能希望更新时间始终为00:00的列。在具有数十甚至数百个DateTime列的数据库中,这将非常耗时。但是编写一个查询所有表的脚本很容易,检查数据类型为DATETIME的每一列,看看时间是否是除00:00以外的时间,如果不是,则创建一个ALTER语句来更改表/列数据类型为DATE。Presto,编写代码的代码。


3

看看CL(通用嘴唇)宏。我认为这正是您想要的。Lips是元编程的完美选择。

我也建议Nemerle如果您想拥有完善的元编程支持(包括宏)的.NET功能

但是,如果您想使用真正的代码生成引擎,请查看Apache Thrift。


3

我只是在开发这样的工具。在我们的特殊情况下,我们基于数据库中函数的签名为数据层生成VB.NET代码。

首先,由于不知道如何生成代码,因此开始进行代码生成非常困难,但是一旦有了一套确定的规则,就可以始终根据这些规则来生成必须生成的代码。 ,使用该代码并不难。当然,根据代码生成的复杂性和规则的数量,任务可能会变得更加困难。但本质上,自动代码生成用于重复的编码任务,而不是用于变化很大的高级代码。

测试输出是双重的。首先,您必须确保代码可以编译,这很容易。然后,您必须确保输出根据生成的参数来执行您要执行的操作,而且输出的难度因生成的代码的复杂性而异。

我的真诚建议是,如果您觉得自己以重复的方式编写代码,并且可以负担得起的时间。请尝试考虑所生成的代码无法完成您正在做的事情。如果是这样的话(如果它是重复性代码,几乎比通常情况要多),请考虑您将要扩展多少次,对该代码稍作修改以及还要编写该确切类型的代码多少次。如果对以上任何一个的答案都是“很多”,那么您应该认真考虑为该代码生成一个生成器

希望有帮助,
IPP


感谢您的回答!您的示例中的规则实际上是如何实施的?
Jose Faeti 2011年

1
我不能告诉您所有规则,但可以举一些例子。我们解析oracle数据库公开的接口,并考虑oracle接口中功能的签名。基于签名,我们生成数据层函数的名称。我们知道,我们总是从数据库中获得一个oracle数据表,并将其解析并保存到用于存储数据的特殊对象类型数组中。同时,基于我们添加相应的输入和输出参数,我们生成等功能的DB函数签名的输入/输出参数..
伊万·保罗Pirau

3

我有一个PHP模块,该模块输出一个包含生成HTML的JavaScript代码的网页。那是三层。男孩很难读!

在编程类中,我们必须编写一个程序,该程序将从用户那里获取公式字符串并进行解析并显示该值。最令人印象深刻的求解器只是简单地接受用户输入,将其包装在main(){printf(“%d”,...);}中,然后运行脚本进行编译,链接和运行。他没有写解析器!今天,您可以在SQL SELECT语句中执行此操作。

这是您应该使用的工具,然后将其存放起来,方便以后使用。


实际上,这就是我试图实现的目标!:)但是后来我决定离线使用Perl对其进行编码,并且效果很好。我有很多功能要添加!
Jose Faeti 2011年

我正在编写多达20层语言到语言转换的代码,完全没有问题。它没有比20层调用堆栈深度复杂的多了。因此,我强烈不同意它是一种“ 可以在将来方便使用的将来存储 ”的工具-代码生成始终很方便。
SK-logic

3

我已经使用Prolog开发了简洁的元编程解决方案。主应用程序(用C ++表示)在运行时将问题的抽象定义转换为Prolog应用程序,然后委托给该应用程序。通常,用C ++编写等效功能会花费很多时间。

我认为这种情况是支持code-writing-code参数的绝佳案例。


3

您如何看待这个主题?

元编程最常与非动态语言相关联,因为在没有大量非生产性和非智能代码行的情况下,实现某些行为(例如实现ORM)的过程比较困难。

但是,即使在诸如PHP之类的更动态的语言中,代码生成也可以真正节省生命,并大量提高生产率。在现代框架中,使用脚手架为您声明的某个业务对象生成大多数通用模型,形式,测试和操作是非常普遍的。这就是诸如symfony或RoR之类的框架取得如此巨大成功的原因之一,这些代码生成工具可以非常快速地生成一致的代码并提高程序员的生产率。

在网站中,大多数交互都围绕四个主要动作进行:

  • 创建一个元素
  • 检索一组元素(可能进行过滤)
  • 使用新属性更新元素
  • 删除一组元素

至少围绕这四个主要动作的所有事情都可以,并且恕我直言,应该使用代码生成工具来实现最高生产力。

在我的公司中,我们使用symfony,而它的admin-generator是一个出色的工具,它甚至可以在运行时生成代码(并将其缓存),这意味着我们甚至不需要使用任何类型的任务或外部工具即可生成新代码,我们只需要清理缓存即可。我强烈建议您将这种工具用于CRUD操作。

但是,完成symfony杰出贡献者的工作并非易事。我本人已经实现了一些代码生成任务,并且要做到真正一致的事情,并且要进行广泛的实现以涵盖大多数极端情况,这并不容易。

它会真正提高您的生产力吗?

我认为元编程在较低级别的工作(框架,缓存,编译器等)中非常重要,但是如果要在业务层上进行操作,则必须格外小心。

毫无疑问,使用代码生成是提高生产力的主要方法。实现自己的代码生成工具,除非您自己构建框架,否则无需做太多事情。

在书籍,博客,幻灯片等中,关于该主题有哪些好的资源?

理解编程的最佳资源始终是良好且注释良好的源代码。我想说,研究RubyOnRailsSymfony管理员生成器是一个好主意。


3

虽然这里有许多答案是指通常所说的元编程,但实际上有一个与AI相关的领域称为自动编程,它涉及程序理解合成程序[1]。

任何编译器(或元程序,代码生成器,翻译器,宏系统等)都可以进行转换,并通过执行其固定的转换算法从输入生成输出。但是,传统的编译器或元程序在给出列表排序的定义,描述或示例的情况下(例如[5,3,9] => [3,5,9])不会创建排序算法。这种问题是“自动编程”领域所关注的。

[1]-程序理解系统的进度报告 ftp://db.stanford.edu/pub/cstr/reports/cs/.../CS-TR-74-444.pdf


2

元编程可能很难维护。乍一看,它看起来很优雅,但是当您开始遇到极端情况时,错误就被捕获得很晚(在生成的代码上),并且整个事情变成了使用/调试的噩梦。

我主要写过python代码,根据我的经验,元编程始终是使用这种语言的错误选择。您总是可以通过无聊的正常语言功能来重构事情。结果不那么时髦,但更易于使用。


任何类型的代码很难维护。如果采取正确的方法,可能会非常容易。实际上,元编程可以将可维护性提高几个数量级。您的python经验很可能与实际的元编程无关,因为Python笨拙的AST太不适合这种思维方式。但是即使使用Python,我也可以高效地使用Tempita库,即使对于几乎没有Python经验的团队,也从未遇到任何可维护性问题。
SK-logic

我对您对python AST的观点感兴趣。您是否已将tempita用于元编程?
西蒙·贝格

这个(docs.python.org/library/ast.html)是一个特别的AST,并且解析器提供了一个未经优化的,过分的树,这使分析成为问题(尤其是在Python中缺少适当的模式匹配)。生成这样的AST也不是很方便。我使用tempita来生成Python和C代码(即,基于纯文本的元编程),它可以很好地完成特定任务(样板代码生成)。我还经常使用Python从一些XML高级描述中生成C代码。
SK-logic

2

OP要求资源。

您可能会发现我们的DMS软件再造工具包很有趣。它是一种纯元编程工具,旨在让人们构建自定义程序分析和转换工具。

[要对OP的问题发表评论,当DMS用于构建特定的转换工具时,DMS是写代码的产品线,它写代码:]

DMS通过与目标编程语言无关(但不独立)来实现这一目标。DMS提供了各种元编程任务所需的标准服务,就像OS为标准编程任务提供了多种服务一样。这些服务包括强大的解析,表象语法树的自动构建,树上的模式匹配和重写,符号表库,它们可以使用讨厌的作用域规则轻松管理语言,例如多重继承,控制流,数据流,指向和调用图分析。在没有要处理的特定语言的情况下,这些都不是有意义的,因此DMS接受与这些通用机器相关的语言定义,从而产生特定于语言的解析,AST构造,特定于目标语言的模式匹配/使用目标-语言语法

与OS一样,DMS旨在使您对要编写的(元)程序几乎没有意见或约束,这意味着DMS可用于多种目的:提取指标,查找无效代码,实现方面的织法器,翻译语言,从DSL生成代码,重新配置大型应用程序。(DMS已经用于所有这些任务)。

如果您不想花时间对语言参考手册中的所有内容进行编码(请想一想这对Java和C ++意味着什么),则需要一个可靠的语言定义。DMS通过提供完整的语言定义库来解决此问题。这里的模拟有点像为您的操作系统提供数据库。您无需实现其中之一即可继续编写以数据库为中心的应用程序。


2

请参阅麻省理工学院课程6.916:创新Web服务的软件工程(http://philip.greenspun.com/teaching/psets/ps4/ps4.ps)上的Philip Greenspun的问题集4 。

其目标是:“教会学生元数据的优点。更具体地说,他们学习如何正式表示Web服务的需求,然后构建计算机程序以生成实现该服务的计算机程序。”

这是潜在的ArsDigita(http://en.wikipedia.org/wiki/ArsDigita)新兵需要解决的问题之一。

Philip在pset中引用的“ SQL for Web Nerds”一书已移至(http://philip.greenspun.com/sql/)。


2

在2001年左右,我开始从事一个广泛使用业务对象和数据对象的项目。我本来要构建前端网站,但由于业务层和数据访问层尚未完全开发,因此不知所措。几周之后,我开始认真研究这些层在做什么。基本上,它们将存储过程返回的数据作为具有与数据字段对应属性的对象的集合公开,或者采用输入参数并将其发送到存储过程以保存到数据库表中。两层之间发生了许多序列化/反序列化,涉及到Microsoft Transaction Server,一个IDL / ODL类型库...但是它们都适合某种模式。

2周后,我找到了一个代码生成器,该生成器将转储IDL / ODL,也将转储业务和数据对象。构建业务和数据层对象的人花了两年的时间才能调试和测试这些对象。在两周内,通过代码生成,我们得到了相同的输出,但是由于它全部生成了,因此完全没有错误。

该代码生成器(低级CASE工具)跟随我进行了大约8到10年的许多不同迭代,因为原理是如此简单:与数据库对话时,您要做的事情需要做,这很漂亮很多重复的编码,一旦正确使用,就不必再担心了。

因此,可以:使用代码生成器,尤其是在代码重复且符合明确定义的模式时。

我知道人们使用RegX宏来执行类似的操作,或者使用Excel公式来执行类似的操作(我也这样做)。


2

元编程示例

我有一个称为Authority的Ruby授权库。它让开发者提出问题,在其应用有类似的方法current_user.can_read?(@post)@post.readable_by?(current_user)。这些问题由集中授权者类回答。

这是关键部分:授权机构在看到用户的配置之前不知道要定义哪种方法。用户配置可能包含:

config.abilities =  {
  ...
  :read      => 'readable',
  :microwave => 'microwavable',  # user-defined
  ...
}

在这种情况下,需要使用类似的方法current_user.can_microwave?(@post)

元编程使这成为可能:在阅读配置之后,我知道要定义哪些方法

Authority.verbs.each do |verb|
  class_eval <<-RUBY, __FILE__, __LINE__ + 1 # allows for a nice bracktrace
    def can_#{verb}?(resource)
      resource.#{Authority.abilities[verb]}_by?(self)
    end
  RUBY
end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.