解决这个问题的传统方法是写注释或其它形式的文档来记录设计信息和模型信息,已经有几个方面的因素证明了这是一种脆弱的解决方案,至少包括编写这些辅助文档的成本、以及文档和代码逐渐不同步的趋势;并且,还有一个没被广泛认识到的事实,就是文档并不能直接连接到它所记录的概念;注释和源代码被绑定到同一个地方,但是概念可能在源代码的多个地方被表达;其它类型的文档彻底从源代码中分离出来,只能间接的引用源代码;理想情况下,代码应该是自我描述的,我应该只阅读代码本身来理解代码,而不是什么注释和外部的文档
Domain Learning Curve
第三个主要的问题是对语言进行领域相关的扩展;例如,在OOP中扩展语言的主要方法是使用类库;问题是类库不是用领域概念相关的术语来表达的,而是用低层的 general-purpose的抽象诸如类和方法等来表达;因此,库很少能够直接表述领域概念,它们必须引入额外的枝节(如一个类的运行时行为)来完成到领域概念的映射;两个很好的常见例子是GUI库和Database库
学习这些类库不是一项简单的任务,即使你是个领域专家;因为从领域到语言的映射不是直接的,你必须学习这种映射;这意味着一个陡峭的学习曲线;通常我们试图用大量的指南和文档来解决这个问题,但是学习这些将花费大量时间;当一个类库变得复杂的时候,它也变得更难以学习,程序员将因此失去学习它的动机
甚至当掌握了这种复杂的映射之后,依然还会很容易的误用类库,因为开发环境(像编译器和编辑器)不能帮助你正确的使用类库,对这些工具来说,调用一个GUI 对象的方法和调用一个DB对象的方法是一样的:它们都只是对象上的方法调用,没有任何更多的意思;记住哪些类和方法应该被调用,以什么顺序被调用,等等,都是使用者的责任
甚至即使你既是领域专家又是类库的使用专家,也仍然有使用类库编写的程序十分冗长的问题;相对简单的领域概念需要复杂的措施来正确的调用;例如,任何用过Swing的开发者都清楚这一点;编写简单的程序就已经花费太长的时间了,复杂的程序甚至更糟
Details of LOP
What Is a Program in LOP?
今天,百分之九十九的程序员认为编程就是编写一串计算机能够执行的指令集;我们被教育说计算机建立在图灵机模型之上,因此它们用指令集的术语来“思考”;但是这种编程的观点是有缺陷的,它混淆了编程的目的和手段;我将为你演示LOP为什么优于传统编程方法,但首先我必须澄清以下事实:一个LOP的程序,不是一串指令集;那么它是什么呢?
当我有一个问题要解决,我在头脑中思考解决方案,这个解决方案用单词、标记、概念、思想,或者任何你喜欢的称呼来表述,它是我头脑中如何解决问题的模型;我几乎从未把它们想象成一堆指令集,而是我正在工作的领域中特定的具有内在联系的概念的集合;例如,当我思考GUI领域时,我想象“这个按钮到那边去,这个输入域到这边来,这个组合框里面需要有一些数据的列表”;我甚至只是在头脑中把它画出来,根本不用任何言语
我之所以认为这种意念模型是一种解决方案是因为我能够用足够的细节向另一个程序员解释这个模型,使他能够坐下来编写一个解决这个问题的程序(比如用 Java);我不需要非得用编程语言的术语来解释这个方案,它可以是任意形式;比如,为了解释如何布局一个GUI的窗体,我只需要画出这个窗体;如果绘画有足够的细节,绘画本身就代表了解决方案;这种领域相关的表述应该就是程序。换句话说,应该有一种方法允许我们使用这种表述作为真正的程序,而不仅仅是与其它程序员交流的手段;于是这便导出了我对程序非正式的定义:一个程序是任何对一个问题无歧义的解决方案,或者,更精确一点:一个程序是对某个领域的某个问题的解决方案的任何使用领域相关概念表达的,精确定义的模型
这就是我认为程序员应该拥有创建他们自己的语言的自由的主要原因:这样他们就能够用更加自然的形式来表达解决方案;General-purpose的语言是无歧义的,但是太冗余和易于出错;自然语言(如英语)表达能力十分丰富,但目前它难以使用因为它太不精确太不形式化了;我们需要能够容易的创建形式化的,精确定义的,领域相关的语言;因此Language Oriented Programming将不只是编写程序,还包括创建用来编写程序的语言;我们的程序将被编写的更接近问题域而不是计算机指令集领域,因此它们将非常容易的被编写
Programs and Text
人们习惯性的认为程序是作为文本来存储的,也就是说,一个字节流;为什么不应该是呢?毕竟有无数的工具来编辑、显示、操作文本;今天的编程语言的核心部分是文法器,解析器,编译器和面向行的调试器;但是程序的文本只是程序的一种表现形式;程序不是文本;强行把程序塞到文本里引起了大量你可能还不知道的问题;我们需要一种不同的方法来存储并和我们程序一起工作
当编译器编译源代码时,它把文本解析成称作抽象语法树的树状结构;当程序员阅读源代码时,他们在脑海中做了本质上相同的事情;我们仍然不得不考虑程序的树状结构;这就是为什么我们要有花括号,方括号,圆括号等;这也是为什么我们需要格式化和缩进代码和遵守编码规范,因为这样就能够更容易的阅读源代码
我们为什么使用文本存储呢?因为当前,阅读和编辑程序最方便和最通用的方法还是使用文本编辑器;但是我们会为此付出代价,因为程序的文本表示有重大的缺点,其中最重要的是基于文本的编程语言非常难于扩展;如果程序以文本的形式存储,你就会需要一个无歧义的文法器来解析程序;当为语言加入新特性时,维护语言无二义性的扩展变得日益困难;我们将需要发明更多类型的括号、操作符、关键字、顺序规则、嵌套,等等;语言的设计者们花费了无数时间来思考语法,并试图发现扩展语言的新方法
如果我们打算让创建语言变得容易,我们就需要将程序的表示和存储从程序本身分离开;我们应该直接将程序存为结构图,因为这允许我们对语言做任何我们喜欢的扩展;有时,我们甚至根本不需要考虑文本存储;今天的一个很好的例子是Excel spreadsheet.百分之九十九的人根本不需要处理存储格式,当这成为问题时总会有各种导入导出功能可用;今天我们使用文本的真正原因是我们没有比文本编辑器更好的编辑器,但是我们可以改变这一点
问题是文本编辑器很愚蠢,并且不知道如何与程序的图状结构一起工作;但是使用正确的工具,编辑器将能够直接和图状结构一起工作,并且能够让我们自由的使用任何编辑器提供的我们喜欢的可视化表现形式;我们可以把程序做成文本、表、图、树、或其它任何形式;我们甚至能为不同目的使用不同的表现形式,比方说,图形化表示用来浏览,文本化表示用来编辑;我们能够为代码的不同部分使用领域相关的表示,比如为数学公式使用图形化的数学符号,为图表使用图形化的图表,为 spreadsheets使用行和列,等等;我们能够为问题域使用最合适的表现形式,可以是文本,但不限于文本;最好的表现形式依赖于我们如何思考问题域;表现形式的灵活性也将使我们的编辑器比以往更加强大,因为不同的表现形式有不同的方式去编辑它们
What Is a Language in LOP?
最后,我应该阐明我认为的“语言”是什么;在LOP中,一种语言是通过三个主要的要素来定义的:结构、编辑器、和语义;结构定义了抽象语法、支持的概念、以及如何安排它们;编辑器定义了具体的语法,如何描绘和编辑语言;语义定义了行为,它如何被解释,和/或它如何被转换成可执行代码;当然,语言还可以有其它方面,比如约束和类型系统
Part II. INTRODUCTION TO META PROGRAMMING SYSTEM
Creating Languages in MPS
我已经解释了为什么我们需要容易的创建新的语言,但是,我们如何才能让它容易呢?如果你turn around这个问题,并且把Language Oriented Programming应用于它自身,你会很快看到答案;This calls for a little self-referential bootstrapping, which can seem tricky, but be patient. 一旦你理解了这个,你将得到LOP真正的力量(一个LOP的元层次)
回顾一下LOP的理念:使创建DSLs更容易,而这些DSLs将使编写程序更容易;但就像我已经说明的,LOP中的‘程序’不局限的意味着你用过的典型的 “一堆指令集”的程序;对某个领域中某个问题任何无二义性的解决方案都是‘程序’;因此如果你设想一下“创建新语言”这个领域,那么这个领域中的‘程序 ’,本身就是一种新语言的定义,可以作为一个解决方案来思考,就像任何其它领域的解决方案一样;
因此,应用LOP的思想,使“创建新语言”更容易的方法,就是创建一种特定的专注于“创建新语言”这个领域的DSL;通过应用这些language- building DSL,我们可以使制造新语言更容易;让我们看几种language-building语言的例子,使你更好的理解它们是如何工作的;这里只是一个概述,以后的文章我会更详细的描述它们
Structure Language
最小最少,我们需要定义新语言的‘结构’;这是我们何以能够编写“精确定义”的程序的原因;语言的结构并不意味着它的文本形式的文法--像我提到过的,这种语言甚至根本就没有文本表示而只有图形化表示
在实践LOP的时候,大部分情况下,你会工作在两个层次的编程中:元层次和程序层次;你在元层次中定义语言,在程序层次中编写程序;当定义一种新语言的结构时,你会使用一种language-structure DSL来定义你的新语言,而这时,你将同时工作在这种language-structure DSL的程序层次和新语言的元层次中
在MPS 中,程序层次的每个节点都有一种“类型”,简单的连接到元层次的另一个节点;程序层次的这个节点被称作这种类型的一个“实例”;元层次中的“类型”节点则定义了这种类型的实例能够拥有的关系和属性;描述这种元层次语言结构的语言,就被简单的称为“Structure Language”
用Structure Language定义一种语言的抽象语法,你应该只是枚举这种语言所有的类型;类型简单的表示了这种语言支持的特性或者概念;每个概念应该用它的名字、实例的内部属性、实例与其它节点之间的关系(通常是连接)来定义
存在两种可能的关联;第一种是类似聚合的关联,它形成了概念模型的父子树结构;第二种是非聚合的,自由形式的关联,它可以连接到系统中任何其它的节点;关联有两个端点:源和目标;关联有角色,你可以定义每个角色的名称、每个端点的多重性,每个目标节点的类型;多重性可以是1, 0..1, 0..n, 1..n等,让你能够约束关联可以创建多少连接;关联的目标类型可以被用来约束哪些类型的节点可以被连接在一起
文章来源于领测软件测试网 https://www.ltesting.net/