精华内容
下载资源
问答
  • System Designer是一个基于模型驱动的生成程序领域特定语言的软件框架。 DSPE是基于System Designer的开发环境之一。 音频n-Genie是DSPE音频领域专业化产品。
  • 浅谈领域特定语言

    千次阅读 2021-07-16 15:43:29
    近年来,随着移动应用、人工智能、区块链、量子计算、芯片逻辑、音乐工程等领域的蓬勃发展,软件各行各业的应用得到爆发式的增长,各行各业的研究人员和领域专家加入到软件开发的队伍,比如:芯片研发工程师需要...

    目录

    0  序言

    1  什么是 DSL

    1.1 生活中的 DSL

    1.2 DSL 与 GPL

    1.3  DSL 的分类

    1.4  DSL 的优势与劣势

    2  建立一个简单的 DSL

    2.1 领域建模与问题域和解答域

    2.2 确立共通的词汇

    2.3 设计 DSL 执行模型

    2.4 初次尝试 DSL

    3  DSL 的优势与发展

    3.1 eDSL 优势与分类

    3.2 业界语言 eDSL 扩展能力分析

    3.3  UI 领域的 eDSL —— SwiftUI

    4  总结

    4.1 小结

    4.2 未来的展望


    0  序言

     

    近年来,随着移动应用、人工智能、区块链、量子计算、芯片逻辑、音乐工程等领域的蓬勃发展,软件在各行各业的应用得到爆发式的增长,各行各业的研究人员和领域专家加入到软件开发的队伍,比如:芯片研发工程师需要通过编程来写芯片逻辑,人工智能算法研究人员需要通过编程写计算逻辑,音乐工程师需要通过编程构建音乐的交互式系统。这些领域专家不是计算机科班出身,但是他们对自己的领域研究非常深入,他们非常期待能有一门面向领域的编程语言来帮助他们屏蔽计算机底层的复杂度,聚焦自己的领域,高效的进行编程。

    在这样的背景下,领域特定语言如雨后春笋般在各行各业兴起。比如苹果在 2019 年推出基于 Swift 的 UI 描述语言 SwiftUI,FaceBook 在 2019 年推出安全灵活的 Libra 区块链编程语言 Move,微软在 2017 年推出量子计算编程语言 Q#,伯克利使用高层次构建语言 Chisel(基于 Scala 语言扩展)编写 RISC-V 的芯片逻辑,因此业界对领域特定语言的研究也进入了一个高峰期。其实领域特定语言(DSL)的概念并不是新的概念,它最早可以追溯到上世纪 50 年代,比如科学计算领域使用的程式语言 Fortran。而领域特定语言真正得到快速发展,还是得力于领域特定语言在理论、工程技术、工具等方面的发展。

    本文主要介绍领域特定语言(DSL)的基本概念、分类以及优劣势,并通过一个简单的例子入手讲解如何构建一个领域特定语言,并且结合 EDSL 的优势以及发展趋势,推导出宿主语言的特性需求,最后通过一个工业界的典型 DSL——SwiftUI 讲解元语言和对象语言的配合关系。

    当然如果读者想了解更多有关 DSL 相关的技术内容,可以持续关注 SIG-DSL 扩展发表的相关文章。我们也欢迎读者朋友加入我们的 编程语言技术社区 SIG-DSL 扩展小组 ,和我们一起深入探讨 DSL 相关技术。

    加入方式:文末有小助手微信,添加并备注加入 SIG-DSL 扩展


    1  什么是 DSL

    1.1 生活中的 DSL

    单看上面的叙述,对于初次接触这一领域的你来说,大概率还是会迷惑什么是 DSL,引用维基的定义:领域特定语言指的就是专注于某个应用程序领域的计算机语言 [1]。现在我们将这一句话换一种说法:领域特定语言,就是让解决领域特定问题的编程模型使用领域专有的语言来 “说话”。即用代码来说话,其目的是让用户通过阅读代码就可以明白建模里的业务规则,而非一堆架构图上的框框和箭头。

    如果要弄懂这个概念,首先我们要明白什么是领域专有的语言,这里举用一个和 Debasish Ghosh 所提到的买咖啡相似的用例 [2],这就如同,当你走进奶茶店点上一杯 “正常冰 3 分糖的多肉葡萄”,那么店员就会准确无误的给你制作一杯,550ml 当季葡萄果肉加绿茶底并配上醇香芝士再加上满满一杯子冰的饮品。你无需过多的描述每一项,只需按照菜单规则的名字来点单,而且这一说法只适用于奶茶饮品领域。

    在这个场景中,点单的过程就是用特定领域的语言来表达一个问题,店员根据你的订单,把饮品做出来是对于问题的解答。这种从问题域映射到解答域的实现模型就是 DSL 的基本思路。如果把上述的场景做成软件,那么客人们点单时所用到的语言就是你要找的 DSL。

    1.2 DSL 与 GPL

    认识一个新事物,我常常会从正面和对立面两个方向来看,正面就如上段内容所述,而与 DSL 处在对立面的就是 GPL(General Purpose Language),即通用编程语言,像我们熟悉的 Java、Python 或者 C 语言等,这类语言没有特定的使用场景,你可以拿他们来实现任意领域的计算机程序,他们的出现并不是为了解决特定领域的问题,我们称这种能力为具有通用的表达力。

    与其相反,DSL 都有相对应的专门的领域,在生活中常见的 DSL 如:HTML 是我们熟知的用于描述 Web 页面的标记语言;CSS 是用于描述页面样式的语言;SQL 是用于创建和检索关系型数据库的语言;这些语言都有一个特点,就是只能解决其特定领域的问题,正如你不可能拿一把菜刀来修汽车一样,你同样无法单独用 CSS 来搭建出一套证券交易系统,这也是正是 Martin Fowler 提出的 DSL 与 GPL 的根本区别,即 Limited Expressivity (有限的表达力)[3]。

    通用编程语言可以给任何事物建模,而 DSL 只适合给一个专门的领域建模。对于 DSL 与 GPL 的区别,可以借用编程语言 Lab 架构师徐潇在 QCon 大会上提出的一个例子来阐明,他将两种语言比作建筑材料,GPL 如水泥,而 DSL 如水泥做好的 “预制件”。

    图片
    图 1:GPL 与 DSL 区别的形象解释

    水泥可以做成任何建筑物,但是水泥管只能限定于做管道,而无法应用成楼板或其他建筑组件。但是当我们想要做管道的时候,我们更愿意接受可以直接使用的 “预制件”,而不是每次都从水泥铸型开始。这一例子也正是生动形象的描述出了 DSL 与 GPL 在表达力和易用度上的根本差异。

    1.3  DSL 的分类

    DSL 本身是一个宽泛的概念,它还可以细化成外部 DSL 和内部 DSL(Embedded DSL,简称 eDSL),像上述所列出的 HTML、CSS 以及 SQL,都是完全独立的语言,他们不依托于任何一门通用的宿主语言,我们称这种 DSL 为外部 DSL。

    与之相对应的,如在 UI 领域,基于 Swift 建立的 SwiftUI;基于 Ruby 设计的 IOS 依赖管理组件 CocoaPods;基于 Kotlin 或者 Groovy 设计的 Android 主流编译工具 Gradle;这些在现有宿主语言上实现的 DSL,我们称之为 eDSL。

    关于 eDSL 的详细介绍与优势对比,我们将在后续章节详细展开。

    1.4  DSL 的优势与劣势

    既然 DSL 的应用如此广泛,那么是否所有的项目都应该基于 DSL 开发?答案显然是否定的,没有一门技术具备完美解决所有问题的能力,DSL 同样在显著的优势下暗藏着危险,在确认是否引入 DSL 之前,我们需要评估一下 DSL 的优缺点。

    首先从 DSL 所扮演的角色来看,由于 DSL 更趋向于解决固定范围的事情,所以基于 DSL 的开发关注点会更加的集中,它仅需要提供范围足够小的一个领域的 API 接口,并且会将领域中的专有概念抽象成更加精确的统一语言来表达其语义(这一点将会在下一章节中说明)[2],这也就意味着 DSL 在有限的范围内具有更强的表现力,且可以消减开发人员与领域专家之间沟通的代沟。

    同时 DSL 是一层更高层的抽象,并不需要使用者懂得基于低层次语言的实现手法,所以对于没有编程经验和背景的领域用户来说,稍加学习便可以使用其来实现自己想要的程序,这也正是 DSL 最大的魅力。

    当然缺点也同样存在,首先不可规避的是 DSL 是一种语言设计类的工作,而要从零设计一门语言,需要设计相关的语法、语义,同时还需实现其对应的编译器(语法解析、类型系统和代码生成等),这并不是一个靠堆积人力就能解决的问题,而是对复杂度和专业度要求很高的工作,所以越来越多的人会将 DSL “寄身”于别的宿主语言,也就是所谓的 eDSL。即便如此,eDSL 的设计难度还是很高,对于 eDSL 的介绍将在第三章展开,这也将是本文的重点内容。

    再者就是一些配套开发工具的开发,如果从零开始设计一门语言,那么像 IDE、测试工具、调试工具和性能工具等相关配套工具都需要从零开始设计并实现,而 eDSL 可以让开发者复用宿主语言本身就具备的这些工具,这也是越来越多的人选择 eDSL 的原因之一。当然对于一些场景, IDE 或者测试工具还是有可能会需要基于宿主语言原生的工具做一些相对的扩展。

    另一方面,如果越来越多的外部 DSL 出现,那么对于开发者来说,将会出现语言永远学不完的现象,任何一个外部 DSL 出现,都需要开发者从零开始学习一门新的语言,而且由于这门新语言只针对特定领域,导致其使用场景有限,这也会带来学习成本与学习价值之间失衡的现象,这是另一个人们选取 eDSL 的原因,毕竟 eDSL 只需要开发者学习基于宿主语言新抽象出的接口即可。

    图片
    图 2:学不完的外部 DSL [4]


    2  建立一个简单的 DSL

    2.1 领域建模与问题域和解答域

    想要设计一款 DSL 需要从领域建模入手,领域建模用于以可视化的形式记录一个系统中的所有的关键概念和词汇表,并且描述出系统中各个实体之间的关系。在被用于软件开发阶段中,实体则可以演变为类别,方法和交互关系则可以演化为逻辑代码。上文中所提及的 “问题域” 和“解答域”则是领域建模的基本实践活动。

    那么什么是问题域?问题域是指我们在业务场景中的实体,过程和约束条件,如前面的例子中,芝士、冰、甜度、多肉和葡萄等这些主要元素即为问题域中所有的实体,其中葡萄和杨梅无法同时放入等规则是一些加在实体上的一些约束条件,再复杂的模型还会添加一些其他的行为,如是否需要打包、何时取餐等。

    解答域则为实现问题域的分析模型提供手段,换言之,问题域所有的元素都需要映射成解答域中的一种手段,如问题域中的冰度,则会映射到解答域中加冰这一解决方法上。而且这种组合必须符合映射的概念,即每个问题域在解答域中必须有且仅有唯一的元素与其对应,不能出现单对多或单对零的情况出现。如果是单对多,那么说明我们设计的解答对于当前的问题域出现了歧义;如果是单对零,那么说明我们设计的解答对于当前的问题域是不完备的。下图描述了领域建模的第一步,左边所有的实体,都可以在右边找到对应的表示。

    图片
    图 3:问题域到解决域的映射

    2.2 确立共通的词汇

    现在我们已经有了问题域和解答域,并且我们已经知道问题域和解答域的映射关系,那么设想如下场景:背景是作者接手了一个大型金融中介机构的后台操作建模的项目,有一次在参加金融中介机构的一次需求分析大会时,发现金融业的领域专家在会上大谈一些附息债券、折价债券等金融中介的常用术语,这便对建模实施者,也就是作者本身造成了困扰,因为对于作者而言,他并不是金融领域相关的从业者,所以不理解这些专有的词汇,甚至容易混淆一些同义词,这就导致作者难以明确最终的需求 [2]。(该实例来自于 Debasish Ghosh 《领域专用语言实战》一书)

    这里需要注意的是,这段故事中提到的两种人物身份,一类是身为领域相关从业者的领域专家,还有一类是身为建模人员的作者本身,当建模人员不熟知领域相关知识的情况时,那么领域专家与建模人员之间的交流便存在了问题。

    所以不难想出,为了解决这一问题,我们需要构建一门统一的词汇。在 “领域驱动设计之父” Eric Evans 所写的《Domain-Driven Design — Tackling Complexity in the Heart of Software》一书中,Eric 提出了 Ubiquitous Language(统一语言)[5],这一词的目的是创造一门可以在团队、开发者、领域专家、测试人员以及其余参与者之间共享的语言,而这种共通的词汇也正好是联系领域专家与建模开发者之间的桥梁。

    试想一下如果没有共通的词汇的存在,那么也就没有了一一对应的关系,这对于需求对齐来说是致命的,如此多的陌生词汇,甚至还参杂着同义词、近义词在其中,这些对于领域建模来说都是或多或少的噪音干扰。因此在领域建模的过程中我们需要设计这一门统一语言来作为需求对齐、会议研讨甚至测试编写的唯一语言,对于那种相同含义的词汇就应该按统一的一种名字来命名,这也正是 Eric 所强调的去除领域理解中难懂的术语与结构,避免设计中的歧义以及需求的不一致。

    请一定要注意这关键的一步,共通词汇的确立是需要时间反复提炼打磨的,它可以避免更多因需求没对齐而带来的返工开销。这就如同武侠小说中的内功心法一样,只要内力足够浑厚,后续只要学会了一两招的招式,那便是响当当的武林高手。

    所以统一语言的构建是建模的前提基础,有时我们在这上面花的时间甚至会比预期想象的要多得多。我们再回到上述买奶茶的例子,在确立共通的词汇前,我们问题域的一些实体,虽然小有体系,但却是杂乱无章的,甚至还会有混淆重叠的部分,如下图示:

    图片
    图 4:统一词汇前的问题域

    当建模者时而听到三分甜,时而听到 30% 糖度,又有时会听到 0.4Oz,虽然三者意思相近,但是对于建模者来说难免需要进一步思考三者的联系与差别,这还仅仅是一个词汇相对通俗易懂的场景,如果我们拿上文中所提到的金融中介的场景来看,那么这个问题的复杂程度可想而知,可不是简单的 “糖度” 可以比拟的。

    这时候统一语言的好处就显示出来了,当我们把所有的词汇都按照规定的统一语言规定好之后,对于上述场景,我们就统一规定这一规模的糖度为三分甜,那么对于建模者来说,这就是一档糖度的表示,同时对于领域专家来说,这就是代表着对于 500ml 的饮品需要添加 0.4Oz 的糖。这样当领域专家再和建模者讨论的时候,就达成了一致,而此时,我们上述的图就可以简化为下面的样子:

    图片
    图 5:统一词汇后的问题域

     同时好的统一语言对于 DSL 的设计是有着极大的正向促进效果的,建模者完全可以就把设计好的统一语言转换为 DSL 中的各个实体,比如在统一语言中,我们设置糖度为五个专有词汇 “全糖”、“七分糖”、“半糖”、“三分糖” 和“无糖”,且糖的种类可以分为 “果糖” 和“糖浆”,那么当建模者在设计一个添加糖度模块的时候,同样可以使用这些名字,如定义一个糖的对象,它具有糖度和种类两种属性,并设置这些属性的值就为这些统一语言规定的词。

    所以当我们的统一语言设计的足够好的时候,那么对应的 DSL 的实体的定义与词汇也就呼之欲出了。再进一步需要做的就是设计一层足够好的抽象和映射逻辑。回头看看,现在我们已经花了足够多的时间在领域词汇的确立和模型分析上,当然这一部分的开销是值得的,那么我们如何才能让领域专家直接基于系统的输入得到解答域的技术制品?或者说是否可以以上述设计的统一语言为基础,建立一种沟通模型,让无论是领域专家还是其他更多参与者都可以抛出问题并得到解答域制品?而这正是我们所需要的 DSL。

    2.3 设计 DSL 执行模型

    上文说到我们需要靠 DSL 来实现中间的映射关系,那么我们之前的图片就可以转换为下图:

    图片
    图 6:DSL 作为映射桥梁

     一个好的 DSL 脚本在联系两个区域时需要遵守一定的原则,Debasish 认为在设计 DSL 应该体现以下三项原则 [2]:

    • DSL 需要将问题域中的实体以同名的形式创建相对应的抽象

    • DSL 脚本的逻辑语言与词汇必须使用设计好的统一语言

    • DSL 脚本需要对语言实现进行抽象,DSL 脚本中不应该引入与解决特定领域问题本身无关的复杂逻辑

    显而易见的是这些原则在极力地用领域用户能看懂的方式来建立 DSL,并且尽力避免掉一些与领域用户无关的干扰,其根本目的就是为了加强与领域用户的沟通能力,使领域用户稍加学习便能基于 DSL 做出他们想要的应用程序。那么 DSL 脚本到底是如何执行的呢?

    图片
    图 7:三种常见的 DSL 运行方式

     上图展示了三种比较常见的 DSL 脚本执行方式:

    1. 源码可以直接执行

    2. 源码会编译成可执行的二进制

    3. 源码利用元编程等能力转译为另一份源码

    前两种并无过多需要描述的,直接执行就是指我们所建立的 DSL 基于的语义模型是解释执行的语言,类似于 Python 或者 JavaScript;而第二种就是指基于的语义模型是编译执行的语言,像 Java 或者 C++;第三种方式则被大量运用在 eDSL 之中,其利用宿主语言所具备的元编程的能力,将宿主语言的复杂性简化从而提高 DSL 的表现力和简洁度,对于元编程的介绍与优势将在后续的章节进行展开。

    2.4 初次尝试 DSL

    万事俱备,现在让我们回到最初的奶茶的那个例子,我们尝试着利用本章节所讲到的方法设计一个针对奶茶行业的简单 DSL,并用其做一个奶茶订单系统。

    在此之前我们需要做一些假设与背景故事的丰富来增强我们的体验感。我们假设现在有一台可以自动做奶茶的机器,它无需店员亲自手动的来搭配各种原料,店员仅需要依靠该奶茶制作系统点单,系统会依靠点单生成对应源码并运行调用奶茶机提供的接口,后者将自动做出店员想要做的奶茶。为了简化场景,我们的奶茶店仅有 3 种底料可供选择:杨梅汁、葡萄汁以及牛乳,对应的茶底也仅有三种:乌龙茶、红茶以及绿茶,同时我们有五种甜度(全糖、7 分糖、半糖、3 分糖和无糖)和四种温度(正常冰、少冰、无冰和加热)供用户选择。

    首先,我们先确立一下共通的词汇,由于本场景比较简单,上面的词汇已经能够很自然的作为我们所需要的共通词汇了。总结出如下表:

    图片
    表 1:统一词汇表

    现在有了共通的词汇,那么我们按照上文所提到的三项原则可以确定如下实体,我们采用枚举类型来表示出一杯饮品的各种属性,以及属性的值,在此次模型中,我们假定有这样一门宿主语言,它具备类型系统并可以与 JavaScript 互操作,我们将基于这一门宿主语言实现我们想要的 eDSL:

    // use enum to represent the tea taste
    ENUM Taste {
      bayberry | grape | milk
    }
    ​
    // tea types
    ENUM Tea {
      Oolong | black | green
    }
    ​
    // the sweetness types
    ENUM Sweetness {
      full | threeQuarter | half | oneQuarter | noSuger
    }
    ​
    // the temperature
    ENUM Temperature {
      ice | halfIce | noIce | heat
    }

    有了各种属性之后,我还需要定义一个订单的类,用于生成最后的订单发送到制作奶茶的机器:

    Class Order {
      constructor(taste, tea, sweetness, temperature) {
        let taste: Taste = taste,
        let tea: Tea = tea,
        let sweetness: Sweetness = sweetness,
        let temperature: Temperature = temperature
      }
    }

    现在我们已经有了订单,那么我们还需要一些行为来与奶茶店的设备做一些交互,比如假设奶茶制作机提供给我们一个 JavaScript 的接口 makeTea,接口的参数类型是 Object,并且,我们奶茶店的大屏也会提供给我们一个 JavaScript 的接口 showPrice,用于显示最终的价格(假定只按口味区分价格,分别为 15、14、16),那么我们现在借助语言互操作的能力给订单赋予这种能力:

    /* 借用语言和 JavaScript 互操作的能力,调取外部 machineAPIs 模块中的接口 */
    JSModule("machineAPIS") {
      func makeTea(order: Order): void
      func showPrice(price: String): void
    }
    Class Order {
      ...
      func getPrice() {
        let price = Switch (this.taste) {
          case: bayberry => "15"
          case: grape => "14"
          case: milk => "16"
        }
        return price
      }
      
      func sell() {
        makeTea(this)
        showPrice(this.getPrice())
      }
    }

    以上我们就简单地创建了一个极简的模型,那么当用户下发订单的时候,店员就可以直接用下面的代码实现:

    // 订单 A
    let orderA = Order(Taste: bayberry, Tea: Oolang, sweetness: halfSweetness, temperature: ice)
    orderA.sell()
    // 订单 B
    let orderB = Order(Taste: bayberry, Tea: black, sweetness: halfSweetness, temperature: heat)
    orderB.sell()

    我们由此可以发现 DSL 的神奇所在,即便你从未接触过这门假想中的编程语言,你仍然能够很轻易地理解这段代码在干嘛。下面我们再借用元编程的能力,使其变的更酷一些,我们可以通过宏定义的方式将上述代码中的一部分代码隐藏起来,即可变成下面的形式:

    @sellOrder
    Order(Taste: bayberry, Tea: Oolang, sweetness: halfSweetness, temperature: ice)
      
    @sellOrder
    Order(Taste: bayberry, Tea: black, sweetness: halfSweetness, temperature: heat)
    // 通过元编程的能力,上述代码在编译时将先转译成
    let orderA = Order(Taste: bayberry, Tea: Oolang, sweetness: halfSweetness, temperature: ice)
    orderA.sell() //元编程的能力将这句表达式折叠起来,靠宏定义将其展开
    let orderB = Order(Taste: bayberry, Tea: black, sweetness: halfSweetness, temperature: heat)
    orderB.sell()

    这样店员就可以编写简单的脚本来和奶茶制作机以及大屏幕做交互,哪怕他从未学习过这门语言甚至连编程也没有接触过,通过简单的学习,他同样可以上手写出相应的订单脚本。因为 DSL 提供了足够高的抽象,抛除了语言本身的学习成本,并且脚本中所使用的词汇全部都是建立在我们之前设计的共通词汇之上。


    3  DSL 的优势与发展

    3.1 eDSL 优势与分类

    在上述例子中,我们设计的是一门借助了宿主语言的 eDSL,由此我们也能看出当 DSL 借助宿主语言时的一些优势:

    • 最直观的一点,我们无需重新设计一门语言,这样就避免了语法设计和语义设计这种复杂的工作,我们要做的仅是利用宿主语言本身的特性来做抽象。

    • 正如上一条所提到的,我们可以利用宿主语言全部的语言特性。像例子中,我们就用到了 “枚举” 和“类”的语言类型,同时我们可以用到语言本身的类型系统或者语法糖等特性,并且可以直接借助语言本身互操作的能力与其他语言做交互,甚至可以借用元编程能力,使我们做更高一层的抽象,这都是 eDSL 本身的优势。当宿主语言特性足够强大丰富的时候,这也意味着相应的 eDSL 将有更多更灵活的功能,而且这些功能都是宿主语言 “免费” 提供的,eDSL 直接拿来使用即可。

    • 可以直接使用宿主语言提供的配套的工具,如 IDE 或者调试功能,无需从零开始投入到新语言的开发中。

    所以 eDSL 相比外部 DSL 来说,开发的成本更低,并且更易推广,这也是开发者更喜欢使用 eDSL 的根本原因之一。在 eDSL 这一类别下,我们还可以分成不同的形态模式,下图展示一些不太严谨的 eDSL 的各种实现模式 [2]:

    图片
    图 8:eDSL 细化分类

     相比于内嵌式,生成式则是指领域抽象可以通过使用一些转译技术转译到宿主语言,如编译时宏、预处理等。

    3.2 业界语言 eDSL 扩展能力分析

    如上文所说,eDSL 最大的好处之一就是可以借用宿主语言本身的特性,所以现如今很多主流语言本身就为实现 eDSL 设计了很多优质的特性,使开发者可以构建面向特定领域的扩展。接下来本章节会对 Swift、Kotlin、Dart 以及 Scala 展开分析,看看他们有哪些特性有利于其扩展出以其为宿主语言的 eDSL。
    Swift 的设计目标一直致力于 "Make Your Swift API Better",具体体现在有表现力、清晰无二义性且简单易用,这也正好是 DSL 所追逐的最终效果。关于 Swift 的 eDSL 分析如下:

    图片
    表 2:Swift 调研

     下面再来看看 17 年被 Google 官宣为安卓系统官方语言的 Kotlin,Kotlin 作为一个运行在 JVM 上兼容 Java 的静态语言,其语法更简洁,且兼具了很多实用功能,具体如下:

    图片
    表 3:Kotlin 调研

    目标成为下一代结构化 Web 开发语言,Google 主导开发的 Dart 语言也同样很易于扩展 eDSL:

    图片
    表 4:Dart 调研

     Scala 作为一门拥有强大类型系统和类型约束的语言,结合其本身简洁的语法设计,使得依赖类型化抽象能力实现的 eDSL 拥有较强的领域表现能力:

    图片
    表 5:Scala 调研

     从上述四门语言可以看出,易于实现 eDSL 的语言通常都具有以下特点:

    • 支持面向对象:可以用类或者接口等抽象映射出领域内专有的实体,甚至有时候会提供一些类型扩展的机制来对于无法修改的类型做扩展。

    • 元编程能力:同时我们可以发现以上四门语言都具备元编程能力,元编程能力可以将复杂的实现隐藏起来,使面对用户的语法保持简洁并且精炼,并且支持用户自定义语义,如利用宏或注解等编译时元编程能力创造出一种不同于宿主语言的语法。

    • 声明式范式:声明式范式完美契合 DSL 的理念,因为用户不用关心怎么做,他只需要关心自己要什么即可。为了达到这一功能,链式调用、宏、类型扩展等特性发挥了重大作用。

    • 语法简洁:为了减少宿主语言本身语法的噪音,语法糖是一种有效的手段,比如一些标点的省略,关键字的省略以及简化的 Lambda 或是尾随闭包。

    接下来我们将结合具体的 eDSL 实例来看看其相比外部 DSL 的优势与收益。

    3.3  UI 领域的 eDSL —— SwiftUI

    SwiftUI 是一门基于 Swift 构建的声明式 UI,这当然也是一门针对 UI 领域的 eDSL,下面是一段 SwiftUI 官网提供的代码 [6]:

    import SwiftUI
    Struct Content: View {
      @State var model = Themes.listModel
      var body: some View {
        List(model.items, action: model.selectItem) { item in
          Image(item.image)
          VStack(alignment: .leading) {
            Text(item.title)
            Text(item.subtitle)
              .color(.gray)
          }
        }
      }
    }

    当我们看到代码的时候,其实我们已经很容易的想像出对应的 UI 的布局,这便是声明式 UI 范式所带来的最大的收益。而为了实现这一范式,SwiftUI 借助了许多宿主语言本身的能力,这也正是 eDSL 的优势所在,通过这段代码我们可以看出上一章节所提到的所有四个特性:

    • 首先,它将组件等实体封装成为一个个对象,并且这些对象的命名都在前端领域的统一词汇中。这样当用户需要一个组件的时候,只需要将对应的组件实例化出来即可,这就加强了模型本身与用户的沟通能力,也是其为了实现 "UI as Code" 效果最根本的一步;

    • 再者,它通过注解的能力对其复杂的状态管理相关的逻辑代码做了隐藏,这段被隐藏的复杂逻辑在本文不做展开,有兴趣的读者可以去了解一下 SwiftUI 的 MVVM 模型以及其观察者模式;

    • 接下来,为了达到其声明式范式的效果,SwiftUI 借用了宿主语言命名参数以及链式调用的特性,使其达到用户可以通过 [组件名].[属性名].[属性名] 的形式绘制组件的效果。用户无需关心我如何去画这个组件,用户关心的就是我需要组件有哪些属性即可,这也正是上文提到的 "What";

    • 最后,SwiftUI 利用语法糖,如省略关键字 new 和 return,或者简化的枚举(比如例子中的 ".leading" 和 ".gray" )来消减语法的噪音。其还利用类型系统,如支持不透明返回类型,通过靠编译器本身的推导来简化开发者手写复杂的返回类型。

    同时 SwiftUI 可以使用 Swift 本身的开发工具如 IDE 等。正是得益于这些现代编程语言相关特性的发展,才使我们在现实的软件开发中见证了 DSL 所具备的潜力。


    4  总结

    4.1 小结

    本文到此就已接近尾声,回顾一下本文所有的内容,我们认识到了 DSL 是一种极其友好的领域建模方式,这得力于其强大的描述建模领域的表达能力。随着现代编程语言的发展,在语言层面对于 DSL 设计的支持越来越充分,比如借助高阶函数的能力,使用户在能够准确表达特定领域中的名词基础上,还能够很好地仿效该领域的动词 [2]。

    元编程的能力以及灵活的类型系统,更是打开了宿主语言本身表现力的限制,这里引用 Debasish Ghosh 说过的一句话 [2]:对于一种能力充分的语言来说,限制其表现力的只有使用者的创造力而已。

    总结最近发展起来的语言,不难发现众多语言的元编程的能力都在不断提高,这也正是各个通用语言为了实现 eDSL 所作的努力,所以元编程的发展对于 eDSL 的表现力与创造力是至关重要的一环,如果读者想了解有关元编程相关的细节,可以时刻关注 SIG-元编程 发表的相关文章,相信读者一定会大有收获。

    4.2 未来的展望

    像上述列举的 Scala、Kotlin、Swift 和 Dart 在 DSL 的发展上都有不同程度的布局,基于这些通用语言来看,类型系统以及元编程能力的发展,对于 DSL 未来的发展将会是挑战之一,同时如何最大程度消减宿主语言带入的噪音(如报错信息不够领域化、无关领域的类型信息)也是我们需要考虑的关键问题之一,再者我们还需要思考下如何让宿主语言配套的调试或者 IDE 支持其扩展的 eDSL。

    虽然仍有这么多挑战与问题值得我们去追寻,但是无论 DSL 如何发展,我们都需坚持其基本的设计原则,同时需多站在用户的角度来思考 DSL 未来的发展,这样 DSL 才会健康地成长。希望越来越多的软件开发者可以看见这一领域的价值与乐趣,并投身其中。

    参考:

    1. Domain-specific language - Wikipedia. (2021). Retrieved 28 June 2021, from https://en.wikipedia.org/wiki/Domain-specific_language

    2. Ghosh, D. (2010). DSLs in action. Simon and Schuster.

    3. Fowler, M. (2010). Domain-specific languages. Pearson Education.

    4. 可画 (2021). Retrieved 28 June 2021, from https://www.canva.cn/icons/MACF30PXThc/

    5. Evans, E., & Evans, E. J. (2004). Domain-driven design: tackling complexity in the heart of software. Addison-Wesley Professional.

    6. SwiftUI Overview - Xcode - Apple Developer. (2021). Retrieved 28 June 2021, from https://developer.apple.com/xcode/swiftui/

    在这里插入图片描述

     

    展开全文
  • 我喜欢开发有用的应用程序。 目前,我一家公司工作,这使得德国出售/购买房屋变得快速而直接。 我正在使用完全由Vue构建的 。 :laptop:‍:laptop:您可以看到我当前正在搜索和学习的内容。 :closed_mailbox_...
  • 第一部分中,将对领域特定语言进行简单介绍,并讲解如何使用Visual Studio 2012创建一个领域特定语言的开发解决方案,以及Visual Studio 2012集成开发环境对DSL开发的支持;第二部分中,将以实际

    前言

    本专题主要介绍在Visual Studio 2012中使用Visualization & Modeling SDK进行领域特定语言(DSL)的开发,包括两个部分的内容。在第一部分中,将对领域特定语言进行简单介绍,并讲解如何使用Visual Studio 2012创建一个领域特定语言的开发解决方案,以及Visual Studio 2012集成开发环境对DSL开发的支持;在第二部分中,将以实际应用为例,介绍开发DSL的主要步骤,包括设计、定制、调试、发布以及使用等。本文为本专题的第一部分。

    领域特定语言概述

    在软件开发过程中,领域特定语言(Domain Specific Language,DSL)可以是一种面向特定应用领域的编程语言,可以是针对某一类问题的表述形式或解决方案,也可以是一种规约(Specification)集合。给DSL下一个明确的定义并不是件容易的事情,比如XML,在大多数情况下,它当然不是DSL,因为能够使用XML进行描述的信息种类数不胜数,但如果我们把XML用于.NET应用程序的配置中,让配置文件以XML的形式进行组织,那么这种具有特定结构的XML就可以看成是一种DSL:这种DSL面向.NET应用程序的配置领域,为这一领域中的问题提供解决方案。在这里,我们暂且不讨论用XML来实现某种DSL是否合适。

    对领域驱动设计(Domain Driven Design,DDD)有一定了解的读者,一定对“通用语言(Ubiquitous Language)”这一词语并不陌生。不错,通用语言是DDD的讨论核心,换句话说,所有与DDD相关的理念和实践,都是围绕通用语言而存在和进行的。通用语言解决了软件系统(或者说应用程序)开发过程中的一个重要问题:沟通。目前的现状是:领域专家(业务人员)对软件开发技术和过程并不了解,甚至是一无所知;而软件开发人员又对其所涉及的领域难以理解。所以,DDD认为,应该基于软件系统所面临的领域,设计一套能够同时被领域专家和软件开发人员所理解的语言,以便尽量减少由沟通引起的误解和分歧。这就是通用语言的由来,这里我们还需要区分一下“通用语言”和“普通编程语言(General-Purpose Programming Language)”的差别,虽然两者都有“通用”的含义,但前者是指“在领域专家和软件开发人员之间的通用性”。

    由此引出两个问题:首先,通用语言的定义和设计是需要一定成本的,这对于经费本不充裕的项graph showing complexity and effort目来说,无疑是难以实践的;其次,通用语言的学习和普及也是需要一定成本的,相对于普通编程语言而言,通用语言的学习成本更大:整个团队需要了解并逐步接受一个新的事物,无论是时间上,还是经费上,都有着一定的开销。结合DDD来看,DDD已经在通用语言的基础上抽象了一些语言元素,比如:实体、值对象、聚合与聚合根、领域服务、领域事件等,然而让一个普通的团队来理解并在自己所面对的领域中准确把握这些元素,也不是一件容易的事情。我想,这也算是侧面解答了“为什么要领域驱动”的疑问:如果你的项目规模不是很大,并希望以最快速度看到开发结果的话,请不要选择DDD。相反,当项目达到一定的规模时,现实复杂度使我们不得不对其进行长远规划,通用语言的定义和学习成本也就变得不那么突出,更重要的是,通用语言的引入和DDD的应用将帮助项目向着良性的方向发展,使项目的各个方面处于一种可控状态。右图来自Martin Fowler《企业应用架构模式》一书,该图对Transaction Script、Table Module(Active Record)和Domain Model三种模式的应用进行了比较,可以看到,对于逻辑相对简单的情况而言,应用Domain Model模式的成本会比较高,然而随着领域逻辑复杂度的增加,相对于其它两种模式而言,使用Domain Model模式的开发和维护成本会更小。虽然DDD并非Domain Model模式,但我们同样可以用这幅图进行类比,以解答“为什么要领域驱动”的问题。

    “通用语言”就是面向特定领域的DSL,根据现行的DSL分类方式,“通用语言”基本上都是以“外部DSL”的方式实现,因为嵌入式(或者说“内部”)DSL都需要一种“普通编程语言”作为宿主,但领域专家不一定熟悉普通编程语言。相比之下,UML就不是一种DSL,因为UML并非专注于一个特定的领域。

    DSL一般分为两种:嵌入式(内部)DSL(Embedded/Internal DSL)和外部DSL(External DSL)。上面也简单提到过,内部DSL通常需要一种普通编程语言作为宿主,就编译器角度而言,内部DSL和普通编程语言之间没有差别,但对于开发人员来说,内部DSL提供了一种可读性更强的、更能表达特定领域语义的编程方式。较为流行的内部DSL实现方式就是我们熟知的“流畅接口”(Fluent Interface):通过一系列属性和方法的连贯调用,让人觉得好像是在使用一种自然语言来表达和解决特定领域的具体问题。在.NET中,LINQ就是这样一种内部DSL,它以另一种形式集成于宿主编程语言(C#或VB.NET)中,开发人员可以通过这种形式的代码来很顺利地表达查询语义;从编译器的角度看,LINQ形式的代码其实就是流畅接口的调用,如果您对这个问题感兴趣的话,您可以使用C#语言写两个方法,在A方法中使用LINQ方式对一个列表结构进行筛选,比如:var query = from l in list where l == 3 select l;;而在B方法中则使用System.Linq命名空间中的扩展方法,以流畅接口的方式对列表结构进行同样的筛选操作,比如:var query = list.Where(l => l == 3);,当你使用ildasm.exe工具查看这两个方法所产生的IL代码时,你会发现两者完全相同。至于“流畅接口”的实现方式,我已经在《在C#中使用装饰器模式和扩展方法实现Fluent Interface》一文中给出了解决方案。

    另一种是外部DSL,外部DSL的实现通常需要借助于新的编译器/解释器,这也就意味着团队需要设计并开发一套能够将外部DSL翻译成普通编程语言,或者能够将外部DSL转换为能在程序环境中运行的组件的编译器/解释器。外部DSL也有两种不同的形式:文本式的和图形化的。文本式的优点在于维护简单,冗余信息比较少(基于XML的外部DSL除外),而图形化的优点则在于直观,但它会连带很多冗余信息,在团队环境中使用图形化DSL会产生一些版本控制上的问题,因为这种图形化的DSL会夹带很多与显示相关的特性,比如图形位置、尺寸、颜色等等,而这些信息本不属于DSL的内容,但在版本控制系统中,又无法忽略对这些信息的更改操作,所以很容易增加解决版本冲突和代码合并的工作量。外部DSL的例子很多,例如:NHibernate的映射文件、web/app.config,虽然这两种是基于XML的;还有Entity Framework的图形化设计器,它是一种面向ORM(Object Relational Mapping,对象关系映射)领域的图形化DSL,它能通过T4将edmx转换成C#源代码,然后通过编译器联编并产生可执行程序。

    接下来,我们将讨论如何在Visual Studio 2012中使用Visualization & Modeling SDK(VMSDK)开发DSL。通过VMSDK开发的DSL属于外部DSL。

    使用Visual Studio 2012开发DSL的先决条件

    要使用Visual Studio 2012开发DSL,就需要安装Visual Studio Visualization & Modeling SDK(VMSDK),而安装VMSDK之前,需要确保Visual Studio SDK安装正确。VMSDK的前身是DSLTools,DSLTools是面向Visual Studio 2005/2008的DSL开发包。以下给出Visual Studio 2012 SDK和Visualization & Modeling SDK的下载地址:

    在后面的案例中可以了解到,我们所开发的DSL会被打包成一个VSIX的Visual Studio扩展包,于是DSL的发布也变得异常简单:只需要在客户机上安装这个VSIX扩展包即可完成发布。这也是为什么VMSDK需要基于Visual Studio SDK的原因之一。

    DSL解决方案的创建

    现在,我们使用Visual Studio来创建一个新的DSL解决方案,以便了解DSL的开发过程。在Visual Studio的New Project对话框中,在Other Project Types | Extensibility分类下,可以看到一个名为Domain-Specific Language Designer的工程模板,选择这个模板,并选择解决方案的保存路径,然后为解决方案设置一个名称,点击OK按钮:

    1

    现在可以看到Domain-Specific Language Designer Wizard对话框,这个向导对话框能帮助开发人员一步步地完成DSL解决方案的设置,它包含了以下这些内容:

    • Solution Settings页面:该页面提供了DSL模板的选择列表,开发人员需要根据自己的实际应用来选择一个合适的模板,例如,如果希望开发一个类似于UML中类图结构的DSL,那么就选择Class Diagrams模板,我们熟知的Entity Framework Model Designer所设计的edmx就属于这种结构的DSL。在这个页面中,还需要为DSL指定一个名称
      2

    • File Extension页面:在这个页面中,为DSL指定一个文件扩展名,比如Entity Framework Model DSL的文件扩展名是edmx。当输入文件扩展名后,向导会自动搜索系统注册表以确保所输入的扩展名没有被占用
      3

    • Product Settings页面:这里主要是对DSL作为一种产品的一些设置,包括三个方面的内容:DSL所属的产品名称、开发这套产品的公司名称,以及DSL所使用的命名空间。例如,Contoso公司正在开发一套软件产品,产品名为ContosoSoftware,并在这套产品中使用了一种面向某个业务领域的DSL,于是,在开发DSL的时候,就可以将这些信息填写在这个页面中
      4

    • Signing页面:Visual Studio会在DSL解决方案中创建一个产生Visual Studio扩展包(VSIX)的工程,通过编译和使用这个扩展包,就能很方便地将DSL部署到Visual Studio开发环境,这部分内容后面还会涉及到。根据Visual Studio扩展包的开发规范,工程需要签名,因此开发人员需要在这个页面中设置一个强名密钥文件。与程序集签名类似,可以创建一个新的强名密钥文件,或者使用一个已有的强名密钥文件
      5

    • Summary页面:在此列出了之前各个页面中的设置选项,以便开发人员能够在解决方案创建之前,对这些设置选项进行确认。当确认无误之后,单击Finish按钮以在Visual Studio中创建DSL解决方案
      6

    在Solution Explorer中,我们可以看到,Visual Studio为DSL解决方案创建了两个工程:Dsl和DslPackage。Dsl是DSL开发的主要工程,今后7我们对DSL的开发和测试都会在这个工程中进行;DslPackage则是一个Visual Studio Extension工程,其主要作用就是产生一个.vsix的Visual Studio扩展包,以方便DSL的部署。DslPackage相关的内容不是本专题的重点,请感兴趣的读者参阅MSDN中有关Visual Studio SDK和扩展包开发的相关专题内容。

    Dsl工程中比较重要的内容有:GeneratedCode文件夹、Resources文件夹以及DSL的定义文件:DslDefinition.dsl。GeneratedCode文件夹下包含了很多T4模板,这些T4模板会根据DslDefinition.dsl中DSL的定义产生相应的C#代码;Resources文件夹下则包含了DSL所使用的资源文件,比如用于在Visual Studio工具栏中表示某个工具的图标图片、在设计器中所使用的鼠标光标文件等等;我们开发DSL的大部分工作都是在DslDefinition.dsl文件上进行的,它指定了DSL包含了哪些领域类型(或者说领域概念)、这些领域类型之间的关系是什么,以及领域类型及关系在设计器上的展现形式。其它的两个文件不是我们讨论的重点,在常规的场景中无需深究这两个文件。

    接下来,让我们了解一下使用Visual Studio进行DSL开发的集成开发环境。

    DSL集成开发环境简介

    Visual Studio 2012 DSL集成开发环境主要由以下窗体构成:

    8

    • 工具栏(Toolbox):就像Windows Forms设计器工具栏一样,它提供了DSL的设计工具,包括领域类型(Domain Class)、关系(Relationship)等工具,我们会在后面对这些工具进行简要介绍
    • DslDefinition.dsl设计器:DSL设计器界面,其中定义了DSL所涉及的所有领域类型及其之间的关系。它同时还定义了这些类型和关系在实际应用中的表现形式,比如某个领域类型的实例是以圆形表示,还是以圆角矩形表示,包括这些图形的颜色、字体、线条粗细等定义
    • DSL细节(DSL Details):开发人员可以在这个窗口中对所选的DSL对象的某些属性细节进行设置,比如通过Mapping Details可以设置领域类型与所使用的图形之间的映射关系
    • DSL浏览器(DSL Explorer):事实上这里才是真正设计DSL的地方,DslDefinition.dsl设计器无非也就是对DSL浏览器中特定内容的图形化表示。在DSL Explorer中,我们可以定义领域类型(Domain Class)、关系(Relationship)、图形(Shapes)、连接器(Connectors),以及DSL本身所提供的工具(Tools)和验证机制(Validation)。在本专题的第二部分对案例进行介绍的时候,我们会使用到DSL Explorer,但并不一定会涵盖DSL Explorer的各个方面

    在日常开发过程中,主要用到的也就是上面所介绍的四个窗体,另外我们还有可能需要根据实际情况来编写一些定制化的C#代码,所以C#程序编辑器和解决方案资源管理器(Solution Explorer)也会被用到。在下一个部分的介绍中,我们会经常涉及到Visual Studio 2012 DSL集成开发环境的这些内容。

    DSL工具栏(Toolbox)简介

    DSL工具栏中常用的工具主要分为三类:领域类型(Domain Class)类工具、关系(Relationship)类工具以及图形(Shape)类工具,接下来让我们简单地了解一下这些常用的工具。

    领域类型类工具

    领域类型类工具包括:Domain Class和Named Domain Class。Domain Class就是DSL的重要组成元素,它对DSL中某个特定的概念进行了准确的定义;Named Domain Class其实就是Domain Class,只不过它默认包含了一个字符串类型的领域属性:Name属性。在实际应用中使用所设计的DSL时,当我们创建一个Named Domain Class的实例时,就可以通过Name属性给这个实例设置一个名称。需要注意的是,当某个Domain Class继承于Named Domain Class时,无需再对Domain Class指定Name属性,此时Name属性将会被继承下来。

    关系类工具

    关系类工具主要是用于指定领域类型之间的关系,这类工具包括:Embedding Relationship、Reference Relationship以及Inheritance。

    • Embedding Relationship:用于指定两个领域类型之间的包含关系。在定义Embedding Relationship的时候,可以在关系的两端指定对方类型的重复数(Multiplicity)。最常见的应用就是用于定义DSL模型与领域类型之间的关系:一个DSL模型可以包含某种领域类型,可以用Has一词来表述这种关系。下图中的ExampleModel和ExampleElement就是用这种关系关联起来的,它表述了这样的概念:ExampleModel可以包含0至多个ExampleElement,而ExampleElement则必须属于某个ExampleModel:
      9

    • Reference Relationship:用于指定两个领域类型之间的引用关系。比如在设计类图(Class Diagram)的DSL时,我们可以设计面向对象编程语言中的“类”可以引用关联到多个“接口”,当然在面向对象技术中,这种引用关联有个专业术语,称为“实现(Realization)”。试想一下,如果将“接口”方面的重复数设置为1,那么我们所设计的这门面向对象语言就仅支持“单接口实现”,也就是一个“类”只能实现一个“接口”。以下是引用关系的一个样例。在这个样例中,我们可以了解到,在我们所设计的DSL中,ExampleElement可以引用0至多个ExampleElement,而它也能被0至多个其它的ExampleElement所引用
      10

    • Inheritance:用于指定两个领域类型之间的继承关系。在DSL的定义中使用继承关系,可以将具有相同行为和属性的领域类型抽象为一个基类型,并在基类型中对这些行为和属性进行定义。比如:某个状态流的DSL定义中包含三种类型的状态:起始状态、中间状态和结束状态,这些都是“状态”概念的具体表述形式,因此,可以设定一个“状态”的抽象领域类型,并使得“起始状态”、“中间状态”和“结束状态”都继承于“状态”抽象领域类型。以下是DSL设计器中对继承关系的表现方式:
      11

    图形类工具

    在实际应用中,我们可以使用某种图形来表示DSL中的概念。这些图形的形式是多样化的,比如在状态流DSL中,我们可以使用空心圆来表示起始状态,使用圆角矩形来表示中间状态,以及使用实心圆来表示结束状态。Visual Studio 2012 DSL集成开发环境为DSL开发人员提供了丰富的图形类工具,包括:Geometry Shape、Compartment Shape、Image Shape、Connector、Port Shape以及Swimline。

    • Geometry Shape:表示一种几何图形,包括矩形、圆角矩形、椭圆形和圆形四种形式。在开发DSL时,可以在设计器上对几何图形的线条粗细、线条颜色、填充色等属性进行设置
    • Compartment Shape:这是一种组合型的图形,这种图形由多个部分组成,每个部分被称为一个“间隔”(Compartment)。例如:类图(Class Diagram)中就是使用Compartment Shape对类和接口进行展示的,类或接口的图形会被分为几个部分:首先是类或接口的名称,然后是“字段”部分,再是“属性”部分,之后就是“方法”部分。Compartment Shape对于创建类似于类图这样的DSL是非常适用的,以下就是一个类图的例子,可以帮助我们直观地了解Compartment Shape:
      12

    • Image Shape:使用一幅图片来表示某个DSL中的概念。比如可以在所设计的DSL中,使用一个“小人”的图片来表示“角色”的概念
    • Connector:这种图形主要用在领域关系上。例如领域类型A通过引用关联与领域类型B建立了关系,那么在DSL的实际应用中,我们就可以使用一根线条来连接A和B的实例,以表示两者之间的引用关系。这根线条就是一个Connector图形,在DSL的开发过程中,我们也能够通过DSL设计器对Connector图形的线型、线条粗细、颜色、箭头等属性进行设置
    • Port Shape:用以表示端点的图形。例如有些类图中,会以一个端点的形式来表示其所实现的接口,还有一些组件视图也会用这种图形来表示组件向外界提供的接口等
    • Swimline:用以表示泳道图形。泳道通常只有在一些非常特殊的情形下才会被用到,例如在设计分层架构的DSL中,可以把架构中不同的层看成是独立的泳道,在每个泳道中,只能包含一些特定的领域类型,比如“客户端展现机制”只能放在“展现层”泳道中等

    其它工具

    最后一个需要介绍的工具就是Diagram Element Map,它是一个连接工具,用于将DSL设计器中左边的领域类型/关系跟右边的图表元素(Diagram Element)连接起来,以表示领域类型/关系应该使用哪个图形进行展现。在开发DSL的时候,选择这个工具,然后用鼠标从领域类型/关系拖拽到相应的图表元素上,即可完成两者映射的建立。

    使用Visual Studio 2012进行DSL开发调试

    在解决方案资源管理器中,Dsl工程上单击鼠标右键,选择Set as StartUp Project选项将其设置为启动工程,然后按F5键即可启动Visual Studio 2012 Experimental Instance,并对DSL进行调试。

    13

    在调试环境中,可以在“解决方案资源管理器”中看到两个DSL文件:Sample.mydsl1和Test.mydsl1,双击Sample.mydsl1即可在设计器中看到DSL的范例,而Test.mydsl1则是供开发人员测试用,开发人员可以在Test.mydsl1的设计器中,使用工具栏中的工具添加一些领域类型/关系的实例,以便对自己所开发的DSL进行测试。在下一个部分中,我们还会使用这个Experimental Instance来调试我们的客户化代码,并创建一些T4模板以实现自动化代码生成。

    小结

    本文是《在Visual Studio 2012中使用VMSDK开发领域特定语言》专题文章的第一部分。本文首先对领域特定语言(DSL)进行了简单的介绍,包括DSL的概念、分类和例子;然后还讲解了Visual Studio 2012中开发DSL的先决条件、环境配置以及开发环境的窗口布局和工具栏等;最后简要地介绍了Visual Studio 2012下DSL的调试功能。在接下来的第二部分中,我们将从一个实际案例入手,介绍DSL开发的基本过程、客户化定制、T4自动化代码产生、DSL的部署,以及在生产环境中使用DSL等内容。


    展开全文
  • 自病情发生以来的短短几个月,学者就新冠和SARS病毒发表了成千上万的研究论文。这种爆炸性的增长激发了新冠开放研究数据集的创建,以促进研究和发现。但是,新冠大流行只是医学界普遍挑战中的一个明显例子。...

    1. 背景

      本文主要是介绍由微软研究人员针对生物医学NLP的领域特定语言模型预训练PubMedBERT。

      新冠凸显了全球科学家面临的一个长期问题:我们如何与最新的科学知识保持同步?自病情发生以来的短短几个月内,学者就新冠和SARS病毒发表了成千上万的研究论文。这种爆炸性的增长激发了新冠开放研究数据集的创建,以促进研究和发现。但是,新冠大流行只是在医学界普遍挑战中的一个明显例子。PubMed是生物医学研究论文的标准存储库,每天增加4,000篇新论文,每年增加一百万篇。

      仅靠人工就不可能跟踪如此迅速的进展。在大数据和精密医学时代,推进自然语言处理发展的紧迫性比以往任何时候都高,NLP可以帮助研究人员快速识别大量论文中的重要发现,而不是通过手动筛选论文以获取相关发现。

      质疑对通用领域文本进行预训练然后再对生物医学等领域进行微调的方法。这是因为生物医学文本与新闻文本和网络文本有很大的差异。 通过从头开始对生物医学文本进行预训练,PubMedBERT模型优于先前所有的预训练语言模型,并在生物医学应用中获得了最新的技术成果。 为了加快这一领域的进展,微软创建了一个综合基准,并发布了生物医学NLP的第一个排行榜。 上述发现也可能适用于其他高价值领域,例如金融和法律。

    2. 在生物医学和专业领域建立神经语言模型的新范式

      预训练的神经语言模型是最新NLP方法的基础。 预训练的工作原理是遮住文本中的某些单词,并通过训练语言模型来预测它们。 然后,可以使用特定于任务的训练数据针对各种下游任务进行微调。 与主流的NLP任务一样,预训练的先前工作在很大程度上与网络有关。 对于此类通用领域中的应用程序,先验知识是未知的,因此使用尽可能多的文本来训练模型是有利的。

      对于像生物医学这样的专业领域,该领域具有丰富的文本,而这些文本与通用领域的语料库完全不同,因此该原理不再适用。 PubMed包含超过3000万篇摘要,PubMed Central(PMC)包含数百万篇全文文章。 不过,一般性的假设是,域外文本可能会有所帮助,因此,现有工作通常从通用域语言模型开始采用混合域方法。
    在这里插入图片描述
    图1:神经语言模型预训练的两种范例。 图中的上半部分:流行的混合域范例假设域外文本仍然有用,并且通常使用通用域语言模型初始化特定于域的预训练并继承其词汇。 下半部分:从头开始的针对特定领域的预训练可以导出词汇表,并且仅使用域内文本进行预训练。

    在这里插入图片描述
    表1:标准BERT、SciBERT和PubMedBERT使用的词汇中常用的生物医学术语的比较。 复选标记表示生物医学术语出现在相应的词汇中,否则该术语将分解成小的子词。

      我们对此假设提出了质疑,并提出了一种新的范例,该范例将从头开始完全只针对特定领域内的域内文本进行预训练。 我们观察到生物医学文本与普通领域文本有很大不同。 如上图所示,在通用域文本上预训练的标准BERT模型仅涵盖最常见的生物医学术语。 其他的将被分解为无意义的子词。 例如,lymphoma(淋巴瘤)被表示为l,##ym,##ph或##oma。Acetyltransferase(乙酰转移酶)还原为ace,##ty,## lt,##ran,##sf,##eras或##e。 相比之下,我们的PubMedBERT将生物医学术语视为“一流公民”,并避免将宝贵的建模和计算带宽转移到无关的域外文本上。

    3. 创建一个全面的基准和排行榜,以加快生物医学NLP的进度

      例如GLUE之类的综合性的基准和排行榜大大加快了NLP的进步。 但是,对于生物医学而言,之前并没有这样的基准和排行榜。 先前的工作倾向于使用不同的任务和数据集进行下游评估,这使得很难评估生物医学预训练策略的真正影响。

    在这里插入图片描述
    表2:先前语言模型预训练研究和BLURB中生物医学数据集的比较。

      为了解决此问题,我们为基于PubMed的生物医学NLP创建了生物医学语言理解和推理基准(BLURB)的数据集。BLURB由13个可公开获得的数据集组成,这些数据集包含6个不同的任务,包括:命名实体识别、基于证据的医学信息提取、关系提取、句子相似度、文档分类和问题解答(参见表3)。 为了避免过分强调具有许多可用数据集的任务,例如命名实体识别(NER),BLURB将所有任务的宏观平均值作为主要得分。 我们还创建了一个排行榜,以跟踪社区的进度。 BLURB排行榜与模型无关。 任何能够使用相同的训练和开发数据生成测试预测的系统都可以参与。 BLURB的主要目标是降低生物医学NLP的进入壁垒,并加速这一对社会和人类影响至关重要的重要领域的进步。
    在这里插入图片描述
    表3:组成BLURB的13个可公开获得的数据集涵盖了各种NLP的任务。

    4. PubMedBert:优于之前所有的语言模型,并获得最新生物医学的NLP结果

    在这里插入图片描述
    表4:我们的实验中使用的各种BERT模型的详细信息摘要。 以前的BERT模型的统计信息是从出版物中获取的。 文本语料库(例如PubMed)的大小可能会有所不同,具体取决于下载时间和预处理

      我们从头开始在生物医学文本上训练我们的PubMedBERT模型。在过滤掉空的或简短的摘要之后,预训练语料库包含1400万篇摘要,其中包含30亿个单词(21 GB)。为了进行公平的比较,我们使用与以前的生物医学预训练工作相同的计算量。我们还通过添加PubMed Central的全文文章来对另一个版本的PubMedBERT进行预训练,使预训练语料库大幅增加至168亿字(107 GB)。

      如表5所示,在生物医学NLP应用中,PubMedBERT的效果始终优于先前所有的语言模型,而且差距比较大。最值得注意的是,尽管RoBERTa使用的是最大的预训练语料库,但它在生物医学NLP任务上的表现却是最差的,与原始BERT模型的效果是类似的。在预训练中使用生物医学文本的模型通常效果更好。但是,在预训练中混合域外文本通常会导致效果下降。尤其是,尽管临床注释与生物医学领域的关系比普通领域的文本更为重要,但将其添加不会带来任何优势,如ClinicalBERT和BlueBERT的结果所示。毫不奇怪,BioBERT最接近PubMedBERT,因为它也使用PubMed文本进行预训练。但是,通过从头开始进行特定于域的预训练,PubMedBERT能够在大多数任务中获得比BioBERT一致的收益。
    在这里插入图片描述

    5. 分析预训练和特定任务的微调策略

      除了在特定领域进行预训练具有优越性以外,我们还对预训练和任务特定的微调策略进行了详尽的分析,并得出了一些有趣的发现:

      与仅使用摘要进行预训练相比,对文章全文进行预训练通常会导致效果略有下降。 我们猜想原因是可能双重的。 首先,全文通常比摘要的噪声会更大。 由于现有的生物医学NLP任务主要基于摘要,因此与摘要相比,全文甚至可能会稍微超出域范围。 而且,即使全文本可以有所帮助,将其包括在内也需要额外的预训练周期才能利用更多信息。 实际上,通过将预训练延长60%,总体结果比仅使用摘要的标准PubMedBERT更好。
    在这里插入图片描述
    图6:评估预训练文本对PubMedBERT在BLURB上的效果的影响。 第一结果列对应于使用PubMed摘要预训练的标准PubMedBERT。 第二个对应于使用PubMed摘要和PubMed Central全文训练的PubMedBERT。 最后一个对应于使用PubMed摘要和PubMed Central全文训练的PubMedBERT,时间延长了60%。

      对抗性预训练已被证明在提升通用领域应用上的效果非常有效。 令人惊讶的是,它通常会导致PubMedBERT效果略有下降(请参见表7)。 我们假设原因可能与我们在全文预训练中观察到的原因相似。 也就是说,如果与下游任务相比,预训练语料库更多样化且相对域外,则对抗训练将更有用。
    在这里插入图片描述
    表7:使用标准和对抗性预训练的PubMedBERT在BLURB上的效果比较。

      命名实体识别和关系提取中的一些常用算法并没有使用神经语言模型。 具体而言,通过使用self-attention机制,显式顺序建模中的实用变得值得怀疑。 在消融研究中,我们发现线性层的性能与顺序建模方法(例如双向LSTM)相当或更好。 对于命名实体识别,只需区分实体内部和外部的标记方案就足够了。

    在这里插入图片描述
    表8:在命名实体识别和关系提取中使用特定PubMedBERT进行的针对特定任务的微调的线性层与递归神经网络的比较。在这里插入图片描述
    表9:使用不同的标记方案和标准PubMedBERT进行生物医学命名实体识别(NER)效果(F1)的比较。

    6. 一种专业领域的预训练方法,可补充通用语言模型

      重申一下,提出了一种针对特定领域预训练的新范式,它是通过完全在一个特定领域内从头学习神经语言模型来实现的。我们表明,对于生物医学等大批量、高价值的领域,这种策略优于所有先前的语言模型,并在生物医学NLP应用中全面获得了最新技术成果。

      该策略与通用的预训练语言模型没有冲突。这两者是相辅相成的,并且适用于不同的情况。在许多开放域应用程序(例如搜索,广告,生产力套件等)中,人们无法预期应用程序实例的域。因此,必须使用占所有域尽可能多的通用语言模型。另一方面,对于具有丰富文本的专业领域中的应用程序,特定领域的预训练效果更佳。在生物医学领域,突出的例子包括提取PubMed规模的知识图谱并从电子病历中提取有效证据。

      这项工作建立在Microsoft Research在生物医学NLP和深度学习方面的发展之上。我们在http://aka.ms/blurb上分享了我们的综合基准BLURB和生物医学NLP的第一个排行榜。我们希望这些资源将有助于降低这一重要领域的门槛,并促进这一进程。我们还在BLURB网站上发布了最新的PubMedBERT和特定于任务的模型,可在此处的“模型”选项卡下找到它们。我们鼓励研究人员参加排行榜,并希望您将PubMedBERT和特定于任务的模型下载并应用到自己的工作中。

    展开全文
  • 人工智能时代,所需要了解人工智能的基本常识

    万次阅读 多人点赞 2018-12-10 22:49:44
    国内对于人工智能的讨论大多是不成体系的碎片式,很难从中深入了解人工智能的发展脉络和技术体系,也很难有实际借鉴意义。... 近几年各界对人工智能的兴趣激增,自2011年以来,开发与人工智能相关的产品和技术...

      国内对于人工智能的讨论大多是不成体系的碎片式,很难从中深入了解人工智能的发展脉络和技术体系,也很难有实际借鉴意义。人工智能的历史、核心技术和应用情况进行了详细说明,尤其是其中重要的认知技术。这份报告将有助于我们对人工智能和认知技术进行深入了解,也有助于各行业的公司考量人工智能应用的实际价值。

      一、概述

      近几年各界对人工智能的兴趣激增,自2011年以来,开发与人工智能相关的产品和技术并使之商业化的公司已获得超过总计20亿美元的风险投资,而科技巨头更是投资数十亿美元收购那些人工智能初创公司。相关报道铺天盖地,而巨额投资、计算机导致失业等问题也开始浮现,计算机比人更加聪明并有可能威胁到人类生存这类论断更是被媒体四处引用并引发广泛关注。

      IBM承诺拨出10亿美元来使他们的认知计算平台Watson商业化。

      谷歌在最近几年里的投资主要集中在人工智能领域,比如收购了8个机器人公司和1个机器学习公司。

      Facebook聘用了人工智能学界泰斗YannLeCun来创建自己的人工智能实验室,期望在该领域获得重大突破。

      牛津大学的研究人员发表了一篇报告表明,美国大约47%的工作因为机器认知技术自动化而变得岌岌可危。

      纽约时报畅销书《TheSecondMachineAge》论断,数字科技和人工智能带来巨大积极改变的时代已经到来,但是随之而来的也有引发大量失业等负面效应。

      硅谷创业家ElonMusk则通过不断投资的方式来保持对人工智能的关注。他甚至认为人工智能的危险性超过核武器。

      著名理论物理学家StephenHawking认为,如果成功创造出人工智能则意味着人类历史的终结,“除非我们知道如何规避风险。”

      即便有如此多炒作,但人工智能领域却也不乏显著的商业行为,这些活动已经或者即将对各个行业和组织产生影响。商业领袖需要透彻理解人工智能的含义以及发展趋势。

      二、人工智能与认知科技

      揭秘人工智能的首要步骤就是定义专业术语,勾勒历史,同时描述基础性的核心技术。

      1、人工智能的定义

      人工智能领域苦于存在多种概念和定义,有的太过有的则不够。作为该领域创始人之一的NilsNilsson先生写到:“人工智能缺乏通用的定义。”一本如今已经修订三版的权威性人工智能教科书给出了八项定义,但书中并没有透露其作者究竟倾向于哪种定义。对于我们来说,一种实用的定义即为——人工智能是对计算机系统如何能够履行那些只有依靠人类智慧才能完成的任务的理论研究。例如,视觉感知、语音识别、在不确定条件下做出决策、学习、还有语言翻译等。比起研究人类如何进行思维活动,从人类能够完成的任务角度对人工智能进行定义,而非人类如何思考,在当今时代能够让我们绕开神经机制层面对智慧进行确切定义从而直接探讨它的实际应用。值得一提的是,随着计算机为解决新任务挑战而升级换代并推而广之,人们对那些所谓需要依靠人类智慧才能解决的任务的定义门槛也越来越高。所以,人工智能的定义随着时间而演变,这一现象称之为“人工智能效应”,概括起来就是“人工智能就是要实现所有目前还无法不借助人类智慧才能实现的任务的集合。”

      2、人工智能的历史

      人工智能并不是一个新名词。实际上,这个领域在20世纪50年代就已经开始启动,这段探索的历史被称为“喧嚣与渴望、挫折与失望交替出现的时代”——最近给出的一个较为恰当的评价。

      20世纪50年代明确了人工智能要模拟人类智慧这一大胆目标,从此研究人员开展了一系列贯穿20世纪60年代并延续到70年代的研究项目,这些项目表明,计算机能够完成一系列所本只属于人类能力范畴之内的任务,例如证明定理、求解微积分、通过规划来响应命令、履行物理动作,甚至是模拟心理学家、谱曲这样的活动。

      但是,过分简单的算法、匮乏的难以应对不确定环境(这种情形在生活中无处不在)的理论,以及计算能力的限制严重阻碍了我们使用人工智能来解决更加困难和多样的问题。伴随着对缺乏继续努力的失望,人工智能于20世纪70年代中期逐渐淡出公众视野。

      20世纪80年代早期,日本发起了一个项目,旨在开发一种在人工智能领域处于领先的计算机结构。西方开始担心会在这个领域输给日本,这种焦虑促使他们决定重新开始对人工智能的投资。20世纪80年代已经出现了人工智能技术产品的商业供应商,其中一些已经上市,例如Intellicorp、Symbolics、和Teknowledge。

      20世纪80年代末,几乎一半的“财富500强”都在开发或使用“专家系统”,这是一项通过对人类专家的问题求解能力进行建模,来模拟人类专家解决该领域问题的人工智能技术。

      对于专家系统潜力的过高希望彻底掩盖了它本身的局限性,包括明显缺乏常识、难以捕捉专家的隐性知识、建造和维护大型系统这项工作的复杂性和成本,当这一点被越来越多的人所认识到时,人工智能研究再一次脱离轨道。

      20世纪90年代在人工智能领域的技术成果始终处于低潮,成果寥寥。反而是神经网络、遗传算法等科技得到了新的关注,这一方面是因为这些技术避免了专家系统的若干限制,另一方面是因为新算法让它们运行起来更加高效。

      神经网络的设计受到了大脑结构的启发。遗传算法的机制是,首先迭代生成备选解决方案,然后剔除最差方案,最后通过引入随机变量来产生新的解决方案,从而“进化”出解决问题的最佳方案。

      3、人工智能进步的催化剂

      截止到21世纪前10年的后期,出现了一系列复兴人工智能研究进程的要素,尤其是一些核心技术。下面将对这些重要的因素和技术进行详细说明。

      1)摩尔定律

      在价格、体积不变的条件下,计算机的计算能力可以不断增长。这就是被人们所熟知的摩尔定律,它以Intel共同创办人GordonMoore命名。GordonMoore从各种形式的计算中获利,包括人工智能研究人员使用的计算类型。数年以前,先进的系统设计只能在理论上成立但无法实现,因为它所需要的计算机资源过于昂贵或者计算机无法胜任。今天,我们已经拥有了实现这些设计所需要的计算资源。举个梦幻般的例子,现在最新一代微处理器的性能是1971年第一代单片机的400万倍。

      2)大数据

      得益于互联网、社交媒体、移动设备和廉价的传感器,这个世界产生的数据量急剧增加。随着对这些数据的价值的不断认识,用来管理和分析数据的新技术也得到了发展。大数据是人工智能发展的助推剂,这是因为有些人工智能技术使用统计模型来进行数据的概率推算,比如图像、文本或者语音,通过把这些模型暴露在数据的海洋中,使它们得到不断优化,或者称之为“训练”——现在这样的条件随处可得。

      3)互联网和云计算

      和大数据现象紧密相关,互联网和云计算可以被认为是人工智能基石有两个原因,第一,它们可以让所有联网的计算机设备都能获得海量数据。这些数据是人们推进人工智能研发所需要的,因此它可以促进人工智能的发展。第二,它们为人们提供了一种可行的合作方式——有时显式有时隐式——来帮助人工智能系统进行训练。比如,有些研究人员使用类似MechanicalTurk这样基于云计算的众包服务来雇佣成千上万的人来描绘数字图像。这就使得图像识别算法可以从这些描绘中进行学习。谷歌翻译通过分析用户的反馈以及使用者的无偿贡献来提高它自动翻译的质量。

      4)新算法

      算法是解决一个设计程序或完成任务的路径方法。最近几年,新算法的发展极大提高了机器学习的能力,这些算法本身很重要,同时也是其他技术的推动者,比如计算机视觉(这项科技将会在后文描述)。机器学习算法目前被开源使用,这种情形将促成更大进步,因为在开源环境下开发人员可以补足和增强彼此的工作。

      4、认知技术

      我们将区分人工智能领域和由此延伸的各项技术。大众媒体将人工智能刻画为跟人一样聪明的或比人更聪明的计算机的来临。而各项技术则在以往只有人能做到的特定任务上面表现得越来越好。我们称这些技术为认知技术(下图),认知技术是人工智能领域的产物,它们能完成以往只有人能够完成的任务。而它们正是商业和公共部门的领导者应该关注的。下面我们将介绍几个最重要的认知技术,它们正被广泛采纳并进展迅速,也获得大量投资。

      一文了解人工智能的基本常识

      1)计算机视觉

      是指计算机从图像中识别出物体、场景和活动的能力。计算机视觉技术运用由图像处理操作及其他技术所组成的序列来将图像分析任务分解为便于管理的小块任务。比如,一些技术能够从图像中检测到物体的边缘及纹理。分类技术可被用作确定识别到的特征是否能够代表系统已知的一类物体。

      计算机视觉有着广泛应用。其中包括,医疗成像分析被用来提高疾病的预测、诊断和治疗;人脸识别被Facebook用来自动识别照片里的人物;在安防及监控领域被用来指认嫌疑人;在购物方面,消费者现在可以用智能手机拍摄下产品以获得更多购买选择。

      机器视觉作为一个相关学科,泛指在工业自动化领域的视觉应用。在这些应用里,计算机在高度受限的工厂环境里识别诸如生产零件一类的物体,因此相对于寻求在非受限环境里操作的计算机视觉来说目标更为简单。计算机视觉是一个正在进行中的研究,而机器视觉则是“已经解决的问题”,是系统工程方面的课题而非研究层面的课题。因为应用范围的持续扩大,计算机视觉领域的初创公司自2011年起已经吸引了数亿美元的风投资本。

      2)机器学习

      指的是计算机系统无需遵照显式的程序指令而只是依靠暴露在数据中来提升自身性能的能力。其核心在于,机器学习是从数据中自动发现模式,模式一旦被发现便可用于做预测。比如,给予机器学习系统一个关于交易时间、商家、地点、价格及交易是否正当等信用卡交易信息的数据库,系统就会学习到可用来预测信用卡欺诈的模式。处理的交易数据越多,预测就会越好。

      机器学习的应用范围非常广泛,针对那些产生庞大数据的活动,它几乎拥有改进一切性能的潜力。除了欺诈甄别之外,这些活动还包括销售预测、库存管理、石油和天然气勘探、以及公共卫生。机器学习技术在其他的认知技术领域也扮演着重要角色,比如计算机视觉,它能在海量图像中通过不断训练和改进视觉模型来提高其识别对象的能力。现如今,机器学习已经成为认知技术中最炙手可热的研究领域之一,在2011-2014年中这段时间内就已吸引了近十亿美元的风险投资。谷歌也在2014年斥资4亿美金收购Deepmind这家研究机器学习技术的公司。

      3)自然语言处理

      是指计算机拥有的人类般文本处理的能力,比如,从文本中提取意义,甚至从那些可读的、风格自然、语法正确的文本中自主解读出含义。一个自然语言处理系统并不了解人类处理文本的方式,但是它却可以用非常复杂与成熟的手段巧妙处理文本,例如自动识别一份文档中所有被提及的人与地点;识别文档的核心议题;或者在一堆仅人类可读的合同中,将各种条款与条件提取出来并制作成表。以上这些任务通过传统的文本处理软件根本不可能完成,后者仅能针对简单的文本匹配与模式进行操作。请思考一个老生常谈的例子,它可以体现自然语言处理面临的一个挑战。在句子“光阴似箭(Timeflieslikeanarrow)”中每一个单词的意义看起来都很清晰,直到系统遇到这样的句子“果蝇喜欢香蕉(Fruitflieslikeabanana)”,用“水果(fruit)”替代了“时间(time)”,并用“香蕉(banana)”替代“箭(arrow)”,就改变了“飞逝/飞着的(like)”与“像/喜欢(like)”这两个单词的意思。

      自然语言处理,像计算机视觉技术一样,将各种有助于实现目标的多种技术进行了融合。建立语言模型来预测语言表达的概率分布,举例来说,就是某一串给定字符或单词表达某一特定语义的最大可能性。选定的特征可以和文中的某些元素结合来识别一段文字,通过识别这些元素可以把某类文字同其他文字区别开来,比如垃圾邮件同正常邮件。以机器学习为驱动的分类方法将成为筛选的标准,用来决定一封邮件是否属于垃圾邮件。

      因为语境对于理解“timeflies(时光飞逝)”和“fruitflies(果蝇)”的区别是如此重要,所以自然语言处理技术的实际应用领域相对较窄,这些领域包括分析顾客对某项特定产品和服务的反馈、自动发现民事诉讼或政府调查中的某些含义、以及自动书写诸如企业营收和体育运动的公式化范文等。

      4)机器人技术

      将机器视觉、自动规划等认知技术整合至极小却高性能的传感器、致动器、以及设计巧妙的硬件中,这就催生了新一代的机器人,它有能力与人类一起工作,能在各种未知环境中灵活处理不同的任务。例如无人机,还有可以在车间为人类分担工作的“cobots”,还包括那些从玩具到家务助手的消费类产品。

      5)语音识别技术

      主要是关注自动且准确的转录人类的语音。该技术必须面对一些与自然语言处理类似的问题,在不同口音的处理、背景噪音、区分同音异形异义词(“buy”和“by”听起来是一样的)方面存在一些困难,同时还需要具有跟上正常语速的工作速度。语音识别系统使用一些与自然语言处理系统相同的技术,再辅以其他技术,比如描述声音和其出现在特定序列和语言中概率的声学模型等。语音识别的主要应用包括医疗听写、语音书写、电脑系统声控、电话客服等。比如Domino’sPizza最近推出了一个允许用户通过语音下单的移动APP。

      上面提到的认知技术进步飞快并吸引了大量投资,其他相对成熟的认知技术仍然是企业软件系统的重要组成部分。这些日渐成熟的认知技术包括决策最优化——自动完成对复杂决策或者在资源有限的前提下做出最佳权衡;规划和调度——使设计一系列行动流程来满足目标和观察约束;规则导向系统——为专家系统提供基础的技术,使用知识和规则的数据库来自动完成从信息中进行推论的处理过程。

      三、认知技术的广泛使用

      各种经济部门已经把认知技术运用到了多种商业职能中。

      1)银行业

      自动欺诈探测系统使用机器学习可以识别出预示着欺诈性付款行动的行为模式;借助语音识别技术能够自动完成电话客服;声音识别可以核实来电者的身份

      2)医疗健康领域

      美国有一半的医院采用自动语音识别来帮助医生自动完成医嘱抄录,而且使用率还在迅速增长;机器视觉系统自动完成乳房X光检查和其他医学影响的分析;IBM的Watson借助自然语言处理技术来阅读和理解大量医学文献,通过假设自动生成来完成自动诊断,借助机器学习可以提高准确率。

      3)生命科学领域

      机器学习系统被用来预测生物数据和化合物活动的因果关系,从而帮助制药公司识别出最有前景的药物。

      4)媒体与娱乐行业

      许多公司正在使用数据分析和自然语言生成技术,自动起草基于数据的的公文材料,比如公司营收状况、体育赛事综述等。

      5)石油与天然气

      厂商将机器学习广泛运用在矿藏资源定位、钻井设备故障诊断等众多方面。

      6)公共部门

      出于监控、合规和欺诈检测等特定目的,公共部门也已经开始使用认知技术。比如,乔治亚州正在通过众包的形式来进行财政披露和竞选捐助表格的数字化,在这个过程中他们就采用了一套自动手写识别系统。

      7)零售商

      零售商利用机器学习来自动发现有吸引力的交叉销售定价和有效的促销活动。

      8)科技公司

      它们正利用机器视觉、机器学习等认知技术来改进产品或者开发全新产品,比如Roomba机器人吸尘器,Nest智能恒温器。

      上述例子表明,认识技术的潜在商业收益远大于自动化带来的成本节约,这主要体现在:

      更快的行动与决策(比如,自动欺诈检测,计划和调度)

      更好的结果(比如,医学诊断、石油探测、需求预测)

      更高的效率(亦即,更好的利用高技能人才和昂贵设备)

      更低的成本(比如,自动电话客服减少了劳动成本)

      更大的规模(亦即,开展人力无法执行的大规模任务)

      产品与服务创新(从增加新功能到创造新产品)

      四、认知技术影响力与日俱增的原因

      在未来五年,认知技术在商业领域的影响力将显著增长。原因有二,首先,近些年来,技术性能有了实质进步,并处于持续研发状态。其次,数亿美元已经投入到技术商业化中,许多公司正致力于为各商业部门的广泛需求提供定制化开发和打包方案,以使这些技术更易购买和配置。虽然并非所有的技术提供商都能幸存,但他们的努力将共同推动市场前进。技术性能的改善和商业化正在共同扩大着认知技术的应用范围,这种情况在未来几年都将持续下去。

      1、技术提升扩展了应用范围

      认知技术大踏步前进的例子非常多。比如Google的语音识别系统,一份报告显示,Google用了不到两年时间就将语音识别的精准度从2012年的84%提升到如今的98%。计算机视觉技术也取得了突飞猛进的发展。如果以计算机视觉技术研究者设置的技术标准来看,自2010年到2014年,图像分类识别的精准度提高了4倍。Facebook的DeepFace技术在同行评审报告(译者注:同行评审,是一种学术成果审查程序,即一位作者的学术著作或计划被同一领域的其他专家学者评审。)被高度肯定,其脸部识别率的准确度达到97%。2011年,IBM为了让Watson在智力节目《危险边缘》中获胜,曾对Watson进行优化,提升两倍的答案精确度。现在,IBM又宣称如今的Watson比当时“智能”了2400%。

      随着技术的改进和提高,技术应用的范围也在不断扩大。比如,在语音识别方面,机器曾经需要大量训练才能在有限词库里勉强识别出来,由语音识别技术延伸出的医疗应用程序也很难得到真正普及。而现在,每个月互联网上都会有数以百万次的语音搜索。另外,计算机视觉技术过去被狭隘的理解为部署在工业自动化方面,但现在,我们早已看到这一技术被广泛运用到监控、安全以及各种各样的消费应用里。IBM如今正拓展Watson在竞赛游戏之外的应用,从医疗诊断到医学研究再到财务建议以及自动化的呼叫中心。

      并不是所有的认知技术都有如此令人瞩目的发展。机器翻译有了一定发展,但幅度很小。一份调查发现,从2009年到2012年,将阿拉伯语翻译到英语的精确度仅仅提升了13%。尽管这些技术还不完美,但他们已经可以影响到专业机构的工作方式。很多专业翻译人员依靠机器翻译提升翻译精准度,并把一些常规翻译交给机器,自己专注在更具挑战性的任务上。

      很多公司正努力将认知技术做进一步研发,并逐步将其融入到更多产品尤其是企业级产品里,以方便企业用户购买和部署。

      2、对商业化进行的大规模投资

      从2011年到2014年5月,超过20亿美元的风险投资流入到基于认知技术研究的产品和服务里。与此同时,超过100家的相关公司被兼并或收购,其中一些被互联网巨头如亚马逊、苹果、Google、IBM或Facebook收购。所有这些投资都在培育一个多样化的公司图谱,这些公司正在加速认知技术的商业化进程。

      在这里,我们并不会提供关于某公司在认知技术商业化方面的细节,我们希望说明,认知技术产品拥有丰富的多样性。下面就是致力于认知技术商业化的公司名单,这个名单既不是完整无缺也非固定不变,而是一个动态的,用于推动和培育市场的指标。

      数据管理和分析工具主要使用自然语言处理、机器学习等认知技术。这些工具利用自然语言处理来从非结构化的文本中提取出意思,或者借助机器学习帮助分析人员从大规模数据集中发现深层含义。这个领域的公司包括ContextRelevant(译者注:美国的一家大数据挖掘和分析公司)、PalantirTechnologies(译者注:这家公司称要将数据、技术、人类和环境连接起来)、以及Skytree(译者注:一家借助机器学习进行市场分析并提供决策依据的大数据公司)。

      认知技术的各个部分可以被整合到各种应用和商业决策中,分别起到增加功能和提高效率的作用。例如,Wise.io公司提供一套模块来促进商业决策,比如客户支持、营销和销售,这里面会用到机器学习模型来预测哪些客户比较容易流失,以及哪些潜在客户更加容易转化。Nuance公司通过提供一种语音识别技术来帮助开发者进行需要语音控制的移动APP的开发。

      单点解决方案。众多认知技术成熟的标志是它们正在被不断的嵌入到特定商业问题的解决方案中。这些解决方案的设计初衷是要比公司原有的解决方案更加有效,并且几乎不需要认知技术方面的专业人员。普及度比较高的应用领域包括广告、营销和销售自动化、预测以及规划。

      技术平台。平台的目的是为建立高度定制化的商业解决方案提供基础。它们会提供一系列功能,包括数据管理、机器学习工具、自然语言处理、知识表示和推理、以及将这些定制化软件整合在一起的统一框架。

      3、新兴应用

      如果这些技术的表现和商业化趋势继续发展,我们就能够大胆预测认知技术的应用将更加广泛,被接受程度也会大大增加。数亿美金的投资涌入这些基于机器学习、自然语言处理、机器视觉或者机器人技术的公司,这预示着许多新应用即将投入市场。在商业机构依托认知技术构建自动化业务流程、增强产品和服务方面,我们也看到了巨大空间。

      五、认知技术在企业的应用路径

      认知技术将在接下来几年里变得流行。在未来2-5年,技术层面的进步和商业化将扩大认知技术对企业的影响。越来越多的企业会找到一些创新性应用来显著改善他们自身的表现或者创造新功能,以增强他们的竞争地位。企业的IT部门现在可以行动起来,增加对这些技术的了解,评估出适用这些技术的机会,将这些技术可能带来的价值向领导进行汇报。高级商务和公共部门的领导应该思考认知技术将对他们的部门以及整个公司产生何种影响,这些技术将如何激发创新并提升经营表现。


    1.人工智能大发展时代,如何利用大数据改变现有商业模式?

    http://www.duozhishidai.com/article-17554-1.html

    2.人工智能来势凶猛,人工智能最热门的技术趋势是什么

    http://www.duozhishidai.com/article-923-1.html

    3.今年人工智能领域,十项中外人工智能领域富有突破性的技术

    http://www.duozhishidai.com/article-17560-1.html

     

    展开全文
  • 什么是数据结构?

    千次阅读 2019-06-19 20:25:39
    数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。 定义 名词定义 数据结构是指...
  • 第一 ~ 五章 ...第六章 目前,对水利工程进行可行性论证时,包含...进行区域水资源配置时,为贯彻公平正义的原则,应该考虑哪些因素? 区域对水资源总量的贡献 区域对水资源的依赖程度 区域的整体经济社会水平...
  • ArcGIS教程 - 2 ArcGIS基础知识

    千次阅读 多人点赞 2020-02-08 11:47:37
    机构部署GIS应用的起点和基础。 ArcGIS桌面是一系列整合的应用程序的总称,包括ArcMap、ArcCatalog、ArcGlobe、ArcScene、ArcToolbox 和Model Builder。通过通用的应用界面,用户可以实现任何从简单到复杂...
  • 软件测试面试题(面试前准备篇)

    万次阅读 多人点赞 2019-09-27 10:42:37
    1)键值(Key-Value)存储数据库:主要是使用一个哈希表,这个表中有一个特定的键和一个指针指向特定的数据。简单、易部署、高并发 典型:Redis、Memcached 2)列存储(Column-oriented)数据库:应对分布式存储...
  • 2019工程伦理慕课答案(2019秋)习题及期末答案

    万次阅读 多人点赞 2019-11-08 18:19:53
    程序公正 多选题 (1/1 point) 下列哪些属于工程项目社会评价的社会公平指标?() 基尼系数 恩格尔系数 就业率 公众参与度 第四章习题(下) 单选题 提出保护资源的目的是为了自然本身的...
  • 人工智能领域的应用

    千次阅读 2018-10-29 12:18:00
    人工智能领域的应用   虽然人工智能的很多研究和应用会基于一些通用技术,比如说机器学习,但不同的经济和社会部门还是会有所区别。我们称之为不同的领域(domain),接下来的这部分将介绍人工智能研究和应用...
  • 测试开发需要学习的知识结构

    万次阅读 多人点赞 2018-04-12 10:40:58
    努力成为一个优秀的测试开发从业者,加油!... - 假装测试的回答 - 知乎白盒与黑盒测试什么区分1、黑盒测试 黑盒测试也称功能测试或数据驱动测试,它是已知产品所应具有的功能,通过测试来检...
  • 软件测试面试题汇总

    万次阅读 多人点赞 2018-09-27 12:31:09
    2、我现在有个程序,发现Windows上运行得很慢,怎么判别是程序存在问题还是软硬件系统存在问题?   5 3、测试的策略有哪些? ................................................................................
  • 当最近全国范围对教育问责制的关注与当前对个人宪法权利的关注相结合时,有关课堂行为矫正的司法程序可能会增加。 因此,虽然行为技术伦理上保持中立(Kazdin,1977),并且虽然遵守法律条文可
  • 其理论基础坚实,其形式化系统不仅用于编译程序,还大量用于人工智能、多媒体技术、数据库等领域程序设计语言 低级程序语言 特定的计算机系统所固有的语言 即:机器语言、汇编语言 特点:执行效率高、编制效率...
  • 机器视觉(8)--机器视觉系统集成

    千次阅读 2019-10-05 16:34:47
    机器视觉系统集成发展的现状和前景 ...近年来,机器视觉行业全球范围实现了创纪录的增长,零部件3D制导与计量、光谱图像分析、高速检测、深度学习等前沿应用领域的可用性和能力不断增强。...
  • C#基础教程-c#实例教程,适合初学者

    万次阅读 多人点赞 2016-08-22 11:13:24
    本章介绍C#语言的基础知识,希望具有C语言的读者能够基本掌握C#语言,并以此为基础,能够进一步学习用C#语言编写window应用程序和Web应用程序。当然仅靠一章的内容就完全掌握C#语言是不可能的,如需进一步学习C#语言...
  • 《人工智能杂记》人工智能时间简史

    万次阅读 多人点赞 2018-03-13 08:54:55
    1人工智能基本概念 人工智能(Artificial Intelligence,AI)是指计算机像人一样拥有智能能力,是一个融合计算机科学、统计学、脑神经学和社会...人工智能的起源:人工智能五六十年代时正式提出,1950年,一...
  • 2楼 : JAVA篇 此篇收录:.《Java 2 核心技术》、2....《C程序设计语言》、2.《C和指针》、3.《C陷阱与缺陷》、4.《C专家编程》、5.《你必须知道的495个C语言问题》 4楼: C++篇 此篇收录:1.《C++ Primer》、2
  • 使用Eclipse开发Android应用程序

    千次阅读 2020-06-30 13:26:25
    本教程介绍了Eclipse环境中的Android应用程序开发,包括两个示例应用程序的构建。 第一个是基本的入门应用程序,包括构建和调试的所有阶段。 第二个应用程序检查了Android的更复杂功能,包括联系人搜索和Google Maps...
  • FPGA的应用领域

    万次阅读 多人点赞 2019-06-17 21:27:02
    1. 视频图像处理领域 1.1 视频编解码 1.2 目标识别 1.3 图像处理支持资源 2. 通信领域 2.1 有线通信 2.2 无线通信 2.3 通信领域支持资源 3.数字信号处理领域 3.1 数字处理系统模型 3.2DSP 实现方式 通用...
  • 计算机专业要学哪些专业课?

    千次阅读 2020-01-19 16:00:53
    文章目录专业课列表必学的专业课课程的重要性专业课难度专业课的考试建议 博主是一所一般的一本计算机专业毕业生,大学中所学的计算机专业课程有如下这些,可能有不少遗漏,后续会考虑补充: 专业课列表 程序语言...
  • 我国人工智能领域的科学技术研究和产业发展起步稍晚,但最近十余年的时间里抓住了机遇,进入了快速发展阶段。这个过程中, 技术突破和创造性高端人才对人工智能的发展起着至关重要的作用。 本周,清华大学AI...
  • 软件工程领域 相关概念

    千次阅读 2017-06-08 09:59:18
    两者是否有差异往往取决于专业背景、所在领域、以及视角。 Module:中文名为模块或模组。 它的核心意义是分离职责,本身是一组具有一定聚性代码的组合,职责明确。 对外的接口可以是松散的或集中的。 它以问题...
  • 一般来说,数据科学家应该具有操作数据库、数据处理和数据可视化等相关技能,还有很多人还认为计算机技能也是不可或缺的,可以提高数据科学家工作的效率。  开源社区多年来对数据科学工具包开发有着巨大贡献,这也...
  • 区块链金融领域的应用案例

    千次阅读 2018-09-21 10:22:16
    区块链这一颠覆性的技术作为当下...金融领域,区块链提供了一个 全新的视野来俯瞰各类传统金融业务,区块链将成为金融领域的技术重构者、业务重构者以及金融生态重构者。案例一:布比等公司尝试区块链进行股权...
  • 它可以5步帮你自动生成 查看/编辑/删除/添加 等一系列的ASP程序! ASPMakerASPMaker ASPMaker可以从Access 数据库或任何ODBC数据源中自动产生完整ASP页面,对记录进行查找、编辑、添加、删除等工作。对于高级...
  • 核心Java程序设计技术

    2021-04-16 12:20:13
    尽我所知,我国在程序设计领域的贡献很少,我的这个成果具备首创价值。我正在把它以新的语言形式展现出来。这应该是我国计算机领域贡献的第一个程序设计语言。现有成果已经开源,大家可以从GitHub上找到,链接是:...
  • 基于MATLAB的语音信号处理

    万次阅读 多人点赞 2018-07-15 01:21:20
    基于MATLAB的语音信号处理摘要:语音信号处理是目前发展最为迅速的信息科学研究领域中的一个,是目前极为活跃和热门的研究领域,其研究成果具有重要的学术及应用价值。语音信号处理的研究,对于机器语言、语音识别、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 56,091
精华内容 22,436
关键字:

在特定专业领域内使用有关的程序