I坐标

博客园 首页 新随笔 联系 订阅 管理
希望得到大家的指正

原文信息

  • 原文地址
  • 作者信息
    • Sergey Dmitriev
    • JetBrains
    • Sergey Dmitriev is the cofounder and CEO of JetBrains Inc., makers of the IntelliJ IDEA Java IDE .

      Sergey's personal website can be found at www.sergeydmitriev.com
    • Contact Sergey via email: dmitriev (at) jetbrains.com

Introduce:简介

        现在是在软件开发领域进行下一代技术革命的时候了,而且革命的形式也越来越清晰。下一代编程样式正呼之欲出。例如有着不同的名字以及不完全相同的形式的几种技术: 意识编程(Intentional Programming) 、 模式驱动编程(MDA) 、 产生式编程(Generative Programming) 等等。我建议统一这些新的技术为: 面向语言编程(Language Oriented Programming)  。这篇文章主要讲述这个新的编程样式的主要概念。



        当前相近的主流的编程范式有一些严格的内设的假设,这些假设就像缠绕在我们脖子上的蛇一样阻止我们的前进,虽然大部分的程序员没有意识到这一点。当编程技术发展到今天时,我们依然停留在石器时代。我们拿到了我们倍加信任的石斧:面向对象编程 ,并且将它用得很好,但是当我们想用石斧去削片和烧烤时,我们遇到的很大的困难。为了超越石器时代,我们必须拥有和控制火,那么我们就可以锻造新的工具,点亮创造的新时代以及迎来新技术的大爆发。



        我谈到了当前的编程技术的限制,它们让强迫程序员像计算机一样思考,而不是让计算机像程序员那样思考。这些限制是那么的根深柢固,以致我们要花费相当大的努力才能克服它。当我说 面向语言编程是下一代编程技术的主要编程范式时,我并非在夸耀。是时候重新定义我们编程的方法的时候了。



        在这篇文章中,我将解释我的观点以及我正在做的 Language Oriented Programming。首先,我要当今编程技术的错误所在;接着,我再用我已经实现的例子: Meta Programming System解释 Language Oriented Programming的概念。这篇文章希望能让你俯瞰 面向语言编程,激发你在这方面的想法,并且期望得到你的反馈和意见。



Language Oriented Programming 概观



        理想的,我是一个程序员,就意味着我能在计算机上做任何事情,我是完全自由和完全主动的。但是,实际上,程序员只有非常有限的自由。当然,我是可以在计算机上做任何事情的,但是那将花掉我多年的努力。所以,一定有某些地方发生了错误,否则我只需要花费少量的时间就能做很多的事情。



        程序员所经受的限制是因为他们不得不依赖于他们无法轻易改变的编程基础架构,换句话说,就是他们所使用的语言和相关的环境。如果我想扩展我所使用的语言,我不得不等待,等待语言的设计者去更新它。如果我想让我使用的IDE有更强大的功能,我也得等,等IDE的开发商去增加哪些功能。



        事实上,这就是我为什么要做IntelliJ IDEA的原因。我已经厌倦了现有的功能弱小的Java IDE。但是像我这样做,对于大部分的开发者来说是不现实、要花费大量时间和努力的事情。毕竟,理想的自由和实际的自由之间的差别是很大的。所以,当我在这里谈起自由这个词时,我指的都是实际的自由。



        获取自由就是减少依赖。例如:Java 的一个目的就是不依赖操作系统,给予开发者在任何操作系统上开发的自由。所以,为了从开发语言和环境中获取更多的自由,我们就应该减少对语言和环境的依赖。



        为什么要这么说?任何通用的语言,例如Java或者C++,让我们可以在计算机上做任何我们想做的事情。当然,这是事实,至少理论上是的,但是通用语言无法达到我所探求的生产效率。或者我们可以使用DSLs,对特定的问题的领域具有高生产率的语言, 去提高生产效率,例如使用SQL编写数据库查询。 DSLs的强项, 对特定领域解决问题,恰恰也是它的弱项, 因为现实世界中,一个问题往往是跨越多个领域的。



        通用和特定领域的对比没有问题,但是我想要的是自由,我想在计算机上做任何事情,高效率的做任何事情。现在,还没有什么好的方法可以让我做到那样。我的理想是,我可以用任何语言同时条理清晰的别写一段代码,并且我的开发环境支持在这些语言上做重构、代码比较、代码浏览以及其它当前所有主流语言具备的功能。



        为了获取这样的自由,我要能自由的创建、重用并且修改语言和环境。为了能让这样的自由具有实用性,我们需要让人们能容易的获取它和使用它。如果我们能用简单的开发语言和环境解决问题,那么这对程序员来说,将是一次巨大的飞跃。这也就是 Language Oriented Programming 出现的原因。



        为了理解什么是Language Oriented Programming,先让我们了解一下当前主流的开发语言的,假设如下的场景:



Think:你需要编写一个程序,于是在你的脑子里你形成了概念模型和如何解决的方法。



Choose:你选择了某一个通用语言(例如,Java,C++)去编写你的程序。



Program:你编写了程序,却是用和你的概念模型不一样的模型来编写的。



        Program这一步是环节中的瓶颈所在,概念模型映射成为代码不是一件容易的事情。如下图,这个方法已经被证明,程序员要使用这种方法表达复杂的系统是效率极低的。





Think:你需要编写一个程序,于是在你的脑子里你形成了概念模型和如何解决的方法。



Choose:你选择了某一个 "DSLs":Conception.DomainSpecificLanguage 来解决你的问题。



Create:如果没有合适的 "DSLs":Conception.DomainSpecificLanguage 适合解决你的问题,你需要自己去创建一个适合你的。



Program:你通过较为直接的方式把概念模型转换为 "DSLs":Conception.DomainSpecificLanguage 来解决你的问题。



        现在,Program这一个环节不算是很大的瓶颈了。这主要是因为DSLs是从概念模型到代码的映射容易了很多。如下图,似乎整个环节中最困难的就是Create步骤了。不过,实际上一个支持Language Oriented Programming的工具可以很轻松的完成这件事情。





        LOP背后的主要动机就是:我能按照我要解决的问题的概念以及概念的方式去工作,而不是被强迫的去把我对问题的概念转换为某一种通用语言。为了达到这一目标,我要使用DSLs。我怎样能得到DSLs我创建一个。



        我已经开始开发一个统一的DSLs平台Meta Programming System以及支持工具和环境。它将允许程序员能像写程序一样轻松的定义他们自己的语言。这个平台将完全支持Language Oriented Programming,给予程序员更大的自由,而不是让他们受限于某一种语言。



        MPS是Language Oriented Programming的一个例子,尽管我只用了MPS作为例子,但是Language Oriented Programming可以通过各种途径实现。Language Oriented Programming的概念和实现是两回事,就像OOP和Java以及C++一样。



当前的主流程序语言有什么问题吗?

        你知道曾经有这么一句话:“如果东西没有破,那么就不要去修理它。”。但是现在的主流的编程语言已经很明显的有缺陷了。我看到了它们的很多的缺陷,其中大部分的缺陷都是因为当前的主流语言无法完全的支持面向领域,而且它们同样都没有同一的DSLs。下面三个主流语言的最糟糕的问题是 Language Oriented Programming将来要解决的。



1、从概念到实现,主流语言有着太长的延迟



        对于我来说,最大的麻烦就是我在将解决方法用程序与计算机沟通时,在我所知道的和所作的事情时间存在着巨大的鸿沟。我只需要几个小时就能把我的想法告诉给另一个程序员,但是要把它告诉给计算机却是一个相当长的时间的过程。造成这样一个问题不同的过程的原因主要是因为我用丰富的自然语言与其它程序员交流,但是与计算机交流时,却是用表达力非常弱的编程语言。当前的主流编程语言只能表达几十个概念,但是自然语言却能用简单的方法表达数千个。因此在表述同一个问题时,与程序员交流和与计算机交流就在交流层次和交流方法上存在着极大区别。使用现在的编程语言的程序员大部分的时间和精力都放在了通过编程这种方法,将自然语言的抽象概念转换为程序思想告诉给计算机,这是一个及其费时、费力和毫无创造性的事情。



        例如,现在非常流行的面向对象设计。这是一个在程序员表达类、层次、关系以及类似概念时非常有效的方法。OOD的主要目的就是用面向对象的模式来表达类、方法等概念。它看起来是非常有用的,非常有创造性的,但是这些对于Language Oriented Programming来说,OOD的构成完全没有必要。



2、理解和维护现有的代码



        无论是我自己写的或是别人写的代码,都存在着一个同样的问题,就是理解和维护。由于现在的编程语言要求我把高级的概念思维转换为低级的程序语言,大量的信息在这个转换的过程中丢失了。当我再次看到代码时,我不得不把代码再次转换为我曾经的概念。基本上,我不得不在脑子中重建哪些曾经在转换过程中丢失的信息。



        传统的解决方法就是使用注释或者是其它的文档形式记录下设计和模型的信息,这种方法现在已经有好几条理由说明它是一种相当不牢靠的方法了,例如要花费大量的时间和精力去编写辅助文档,以及文档往往不能与代码同步。文档虽然写了,但是却没有直接的表达所要表达的概念,注释虽然写了,但是却是与被注释的代码放在同一个地方,而表达整个程序的概念的文字散落在代码中的各个地方。虽然有些文档完全从代码中分离出来了,但是却不得不应用代码来表达要表达的意思。



        理想的,代码应该是自解释的,我是通过阅读代码来解释代码,而不是注释或者是外部的文档。



3、领域学习曲线

        这第三个问题就是将特定领域扩展到语言。例如,在OOP的概念中,语言的最主要的扩展方法就是类库,但是类库却不能表达领域概念的形式,仅仅是低层次的类和方法的抽象表达。所以,类库几乎没有直接表述领域。它不得不引入复杂的形式(例如一个类的运行时行为)来完成对领域的映射。两个最好的例子就是图形用户界面库和数据库访问库。



        学习这样的类库不是一个简单的事情,即使你是这些领域的专家也不例外。因为没有从领域到类库的映射,所以你必须自己去做这样的事情。这时,就会有一个起伏跌宕的学习曲线出现在你的学习计划中了。通常,我们借助众多文档和帮助,想平滑学习曲线,但是这样依然要花费大量的时间。当一个类库越来越复杂时,对它的学习难度也就越来越大了,并且程序员们也对它失去了学习的兴趣。



        即使学好了一个复杂的类库,但是却存在着滥用和误用的陷阱。因为这个类库的相关环境(例如编辑器)不能有效的协助你正确的使用这个类库。例如,你不得不自己去记住某些方法的调用方式,调用顺序等等,而这些编辑器是无法帮助你确定好坏的。



        甚至即使你是一个领域的专家,同时也是这个领域的一个类库的熟练使用者,但是你还是要面对使用这个类库编写冗长的代码的情况。一个相对来说比较简单的领域概念,却不得不用复杂的方法去正确的实现。用过Swing的人,或者了解的人都知道,要用Swing完成一个简单的工作并不容易,复杂的就更不用说了。



Language Oriented Programming的细节



对于Language Oriented Programming来说什么是程序?



        今天,对于99%%的程序员来说,程序就是给计算机执行的一系列指令。我们一直被告知,计算机是按照图灵机设计的,它们是按照一系列的指令来“思考”。但是这样的观点是错误的。它混淆了编程和编程的目的概念。我将会告诉你Language Oriented Programming与传统编程相比有什么好处。但是在这之前,我想说明对Language Oriented Programming来说, 程序不是一系列指令,那么程序究竟是什么?



        当我需要解决一个问题时,我在脑中形成解决方案,这个解决方案在我脑中可以是文字,概念,思想,想法等等表达,无论你怎么认为,总之它们在我的脑中是一些解决方案的模型。我一直都不认为它们是一系列指令,而是认为它们是我工作的特定领域的一系列内在关联的概念。例如,对于GUI领域,我会这么想,按钮在这里,文本框在哪里,下拉框应该有一些数据列在里面等等,我甚至能在脑海中形成图片而不需要一个字来表达。



        我之所以说这些脑子中的模型是解决方案,这是因为我能把这些东西足够相信的告诉另一个程序员,而他能根据这些信息用某种语言(例如Java)编写程序并实现。我并不需要用某种编程语言来解释这些解决方案,例如为了说明如何布置窗体,我会画一个窗体出来。如果这幅画有足够多的细节,那么这幅画就能解释这个解决方案。这样的特定领域的表述方式就是程序。换句话说,应该有一种方法让我用它表述真正的程序,而不是使用用自然语言与其它程序员交流这个方法。因此,我对程序的定义是:程序就是对问题的任何清晰的解决方案。或者更严格的说:程序是在一个领域中出现的一些问题问题的准确定义的解决方案模型,并且使用该领域的领域模型表达。(A program is any unambiguous solution to a problem. Or, more exactly: A program is any precisely defined model of a solution to some problem in some domain, expressed using domain concepts.)



        这就是我想让程序员自由的创建他们自己的语言的原因。这样他们就能用多种自然的表达形式表述他们的解决方案了。现在的计算机语言也是可以明确的表达意思的,但是它们太过于冗长和容易发生错误。自然语言(例如英文)是非常丰富的,但是它们太过于通俗和具有二义性,所以目前作为计算机语言使用也非常困难。我们需要创建一种正式的,定义明确的,特定领域的语言。所以,Language Oriented Programming不是用来编程,而是用来创建能在我们程序中使用的语言。使用它创建的语言编写程序,我们的程序将比一系列指令更接近问题领域,也更容易编写。



程序和文本



        每个人都知道程序是存储为文本的。例如一个字符流。这并不奇怪,程序本来就是存储为文本的,毕竟,有很多的工具都是为了编辑、显示和维护文本。当今语言的核心部分就是语法,解析,编译和行调试。但是,一个程序的文本是程序的一种表现方式,程序不是文本。强迫把程序编程一段文本会导致很多你意识不到的问题。我们需要另一种方式去存储和使用程序。



        当编译器编译源代码时,它是把代码翻译成一个树状结构,即抽象语法树。程序员在阅读源代码时,也在做很类似的事情。我们不得不考虑程序的树状结构。这就是我们为什么要在程序中有[],{},()的原因。这也就是为什么我们编写代码时要缩进和遵循代码约定的原因,一切都是为了能更好的阅读。



        为什么我们不重新安排代码的存储方式?因为当前方便的,通用的阅读和编辑代码的方式就是用文本编辑器。文本存储和编辑程序的最大问题就是很难扩展。如果程序保存为文本,你需要一个定义明确的解析器去解析它,如果要添加一个功能给这个语言而不能让这个语言变得具有二义性,这将是一个非常困难的过程。我们需要引入更多的[]、类型、关键字、操作符和顺序规则。



        假如我们能让创建语言变得很容易,我们就需要分离程序的表现和存储。我们可以直接把程序保存为树状的结构,因为这样可以方便我们对语言的扩展。我们根本就不去考虑把程序保存为文本。当前最好的例子就是Excel。99%的人都不需要处理保存格式,当需要时,使用导入导出就可以了。而我们现在使用文本的原因在于目前还没找到比文本更好的编辑和保存方法,但是我们可以改变这一点。



        文本编辑器的最大问题在于,它太笨,不知道处理基于图形结构的程序。但是如果使用适当的工具,那么编辑器就能用图形结构直接工作了,同时也能给我们更大的自由去使用我们喜欢的可视化编辑方式。我们可以把程序表现为文本,表格,视图,树状或者其它你能想到的形式。我们甚至能为了不同的目的使用不同的编辑方式。例如使用图形形式查看,而同时使用文本方式编辑。我们可以对于不同领域使用不同的编辑方式。例如,图形的数学符号用于数学计算,图形的数据视图,表格用来表示行和列等等。我们不必要使用文本而是使用我们喜欢的方式来编辑程序。



Language Oriented Programming中语言是什么?

        最后,我要说明白,我所说的语言是什么。在Language Oriented Programming 中,语言由三个部分定义:结构、编辑和语义。结构定义了抽象语法,支持什么样的概念,以及这些概念是如何被整理的。编辑定义了具体的语法,即语言是如何表示和编辑。语义定义了行为,语言是如何解释,如果被翻译为可执行的代码。当然,语言还有其它的特征,例如约束和类型系统。



posted on 2004-12-03 15:32  I坐标  阅读(1871)  评论(3编辑  收藏  举报