Enterprise Just Builder

Solution for Enterprise Software Architecture

编程语言

将 Win32 枚举型 APIs 转换为 STL 迭代器

原文1

操作系统都有许多 API 用于存取实体集合的,比方说 Unix 的 opendir()/readdir() 函数。Win32 API 也提供了许多函数用来枚举集合内的元素,通常采用的模型无外乎下面几种:回调函数 (如 EnumChildWindows), get-first/get-next (取第一个/取下一个 比如FindFirst/NextFile), 或 get-nth (取第n个 如 RegEnumValue) — 其语义和前二者完全不同。

现在 C++ 社区正在逐步朝着符合 STL 的通用编码格式迈进,如使用容器 (序列和关联)、迭代器、泛函 (或函子或函数对象)、算法和适配器等等。这一做法的最大好处是可以采用一种通用的方法操纵不同的实体, 大大减少开发者的工作量, 同时提高健壮性、可维护性和重用。

STL 技术未被广泛运用的原因之一是除了标准库所提供的类和函数 (list, vector, for_each 等) 之外, 缺少可用的 STL 兼容库, 特别对于操作系统 API。原因之一是这涉及编程模型之间迁移转换的复杂性, 特别是对于集合和序列。本文通过将两种 Win32 枚举模型实际转换 STL 序列, 创建封装了 Win32 API 的轻量级序列类, 并提供了可按 STL 标准算法来操纵枚举实体的迭代器。

本文所演示的类是 WinSTL 库的一部分,WinSTL 则是 STLSoft 的子项目。STLSoft 是个开源组织,一直致力于将 STL 概念运用到多种技术和操作系统中去。

>>> 阅读全文

 

, , , ,

C++ 设计模式之一 建造型模式

设计模式既不是某种静态解决方案,也不是某种算法。设计模式通过其名称(大多数是对目标的简单描述)来介绍或引入一些常见设计问题的重复解决方案或方法,或者说是解决一般性问题的常用方法。因此作为对具体实现的一种抽象,设计模式在设计阶段就十分有用。有了这个概念,在做设计选择时作为标准技术进行沟通,可以让团队成员更容易分享其设计理念。

根据所解决的设计问题,设计模式主要分为以下几大类:

  • 创建型模式 (Creational Patterns)
  • 结构型模式 (Structural Patterns)
  • 行为型模式 (Behavioral Patterns)

模式在 C++ 或 Java 这类面向对象的编程语言中十分常见。它可被视为模板,用来说明如何解决某个在不同场景或应用中反复出现的问题。设计模式不是代码重用,因为它通常没有具体代码,但通过设计模式轻松创建代码。面向对象的设计模式通常显示的是类或对象之间的关系和互动,而无需涉及应用最终呈现的类或对象。

每个设计模式由以下几个部分组成:

  • 问题或需求(Problem/Requirement):它阐述了所要解决的问题的需求。通常是在多个应用中都会遇到的常见问题。
  • 制约条件(Forces): 它描述了技术限制,用来帮助指导创建解决方案.
  • 解决方案(Solution): 它描述了介绍如何编码来解决上述问题。这是设计模式的设计部分。它可能包含类图
    时序图等等。

设计模式可以视为一个标准,是广泛认可的用来解决某个特定设计问题的最佳实践。在应用程序内采用良好的设计模式,可以大大加速你的设计工作,并有助于和其他程序员进行沟通,从而避免解决方案陷入繁琐晦涩的境地。

>>> 阅读全文

 

,

用 PostgreSQL Schemas 创建多租户 Rails 应用

许多 Rails 应用有多租户的需求。为此可以采取多种不同的策略,而每种策略都各有利弊。Guy Naor 曾对每一策略的利弊都进行了详细论述,具体可以参考他的 2009 Acts As Conference talk(必看)。1

这些多租户策略之一运用了 Postgresql 特有的称为 “Schemas” 的特性。不过 Guy 只是在技术层面泛泛带过,并未深入到实现细节。要如何运用这一策略来实际完成多租户应用,你可以从网上搜到几篇博客、StackOverflow 的讨论以及一些半成品,但诸多细节还要自己推敲,这里我将之记录下来,以飨读者。

为什么使用 PostgreSQL Schemas
Guy 列举了多租户 Rails 应用的三种基本策略:2

  • 每个租户使用独立数据库
  • 单一数据库,用记录维护着租户关系的范围
  • 单一数据库,每个租户使用不同的 Schemas (只适用 PostgreSQL)

选择哪一种策略需要诸多考量,这里不一一列举,我想说的是,对于第 3 种策略,应用应有以下特征:

  • 租户的数据是私有的,不能泄露给其他租户
  • 几乎不进行跨租户数据聚合的查询
  • 租户数量很多,无法承担过高管理开销

由于应用间存在千差万别,所以个人建议你最好认真看完该演讲,然后自己阿里做决定。如果你最终还是选择了 PostgreSQL Schema ,你再回来继续读完这篇文章。

>>> 阅读全文

 

, , ,

无锁双向链表

基于锁的同步机制总是受到象优先级反转(priority inversion )和死锁的困扰,即使这样,无锁同步还未引起重视。原因是要编写正确且高效的无锁代码实在困难1。本文演示了一个无锁双向链表的实现,实用且易于理解。第一个无锁双向链表是由 H°akan Sundell 实现的,本文中的方案利用了单字 (single-word) 的比较并转换(CAS — compare-and-swap)原子原语。在附录中提供了本方案与 H°akan Sundell 实现的链表的比较结果。 2

背景: 原子操作与 CAS
原子操作是指一系列必须整体完成的操作步骤,如果任何一步操作没有完成,那么所有完成的步骤都必须回滚,这样就可以保证要么所有操作步骤都未完成,要么所有操作步骤都被完成。在单核系统里,单个的机器指令可以看成是原子操作(如果有编译器优化、乱序执行等情况除外);在多核系统中,单个的机器指令就不是原子操作,因为多核系统里是多指令流并行运行的,一个核在执行一个指令时,其他核同时执行的指令有可能操作同一块内存区域,从而出现数据竞争现象。多核系统中的原子操作通常使用内存栅障(memory barrier)来实现,即一个 CPU 核在执行原子操作时,其他 CPU 核必须停止对内存操作或者不对指定的内存进行操作,这样才能避免数据竞争问题。3

因此在 X86 平台上,Intel 提供了在指令执行期间对总线加锁的手段。CPU 芯片上有一条引线 #HLOCKpin,如果汇编程序中的某条指令带了前缀 “LOCK”,CPU 执行到这条指令时就会 #HLOCKpin 的电位拉低直到该指令结束,从而将总线锁住,这样同一总线上其它 CPU 就暂时不能通过总线访问内存了,这样保证了指令在多处理器环境中的原子性。

所谓比较并交换 (CAS) 是在多线程中可用来获得同步的原子指令。CAS 操作包含三个操作数 —— 目标值(V)、原值(A)和新值(B)。CAS 指令会先将目标值 V 与原值 A 进行比较,如果二者相同,那么就可以新值 B 赋予目标值。

在 Windows 和 .NET 平台,由于历史原因,CAS 被写做 Interlocked API。原子操作在 Intel 架构 CPU 对应的汇编指令有 XCHG、CMPXCHG、INC 等,当然还得加上 LOCK 作为前缀。

>>> 阅读全文

 

, , ,

在 .NET 4.5 中使用 Websocket

作为下一代的 Web 标准,HTML5 拥有许多引人注目的新特性,如 Canvas、本地存储、多媒体编程接口、WebSocket 等等。这其中有“Web 的 TCP ”之称的 WebSocket 格外吸引开发人员的注意。WebSocket 的出现使得浏览器提供对 Socket 的支持成为可能,从而在浏览器和服务器之间提供了一个基于 TCP 连接的双向通道。Web 开发人员可以非常方便地使用 WebSocket 构建实时 web 应用,

IETF 的 RFC 6455 对 WebSocket 协议进行了标准化, 在 Wikipedia 和 W3C 站点上提供了更多的介绍和详细资料。

WebSocket 连接是通过在客户端和服务器之间的 HTTP 握手来建立的(前缀是 “ws://” 或者 “wss://”) 。拿 Wikepedia 上例子来说明,客户端会这样发出请求:

GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com

之后服务器发出响应来接受连接:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

这里的 “Sec-WebSocket-Key” 和 “Sec-WebSocket-Accept” 用于通过密钥验证算法来确认客户端和服务器之间的连接。

>>> 阅读全文

 

, , , ,

Ada 语言编程 (二)

由于 Ada 出生年月略迟了一点,加上现在的操作系统基本上由 C 或 C++ 写成,导致 Ada 在“平民层”的推广比较糟糕,至今还不是很流行,Why Ada isn’t Popular 一文对此有比较详细的解释。而 Ada 爱好者们为了显示 Ada 的优越性(这种心情相当能理解),将 Ada 与 C、C++ 做了一系列比较,其结果反正综和指数都是 Ada 高,这方面文章有不少,如 Comparing Development Costs of C and Ada,Contrasts: Ada 95 & C++ 等等。在这里,我们只初略地了解一下 Ada 的优势即可,在读者朋友接下去的学习中,应该是能从心里感受到 Ada 的优点。1

  • 更高的安全性、可靠性。Ada 中对于访问内存、数值计算等很多方面有一些严格的规定,而没有 C 和 C++ 那么自由;程序的错误绝大部份能在编译和运行时检测到,另外,语言也包含异常特性,能方便地处理错误。
  • 更高的移植性。 Ada 最初的语言环境中就有了异常(约等于 Unix 下的 Signal)、任务(线程)、分布式计算、随机数产生、宽字符集等众多特性,而在其他语言中,这些特性往往随系统而异。即使 Ada95 里缺少一些功能,也可以通过额外标准和函数库来弥补:比如 GDI 库方面,可以使用 GtkAda;
  • 语法明确,基本上没有令人混淆的地方。Ada 程序的源代码远远比 C 或 C++ 的代码易懂。

总之,C 和 C++ 能做的 Ada 肯定能做,但 Ada 要省时方便得多。在学习 Ada之后,无需多说也就明白了。

第一个程序
大部份书籍一般都是用 “hello world” 程序来开始,我们就来看一下在屏幕上输出 “Hello World!”的简单例子。

— filename:hello.adb;
 with Ada.Text_IO;
 procedure Hello is
 begin
    Ada.Text_IO.Put ("Hello World!");
    Ada.Text_IO.New_Line;
 end Hello;

现在让我们分析上述的简单程序:

[000]标示该程序文件名为 hello.adb,在程序中并不需要;– 是注释符,表示从其所在位置至行尾都是注释,对程序没有什么影响,与 C 的 /* */类似。

>>> 阅读全文

 

用 libclang 实现代码生成器

文章评价:
代码生成器对大型 C++ 项目而言是非常有用的工具。由于语言层面上缺乏自省(introspection)机制,要实现反射、脚本绑定(script binding)及序列化都需要编写代码样板(boilerplate) 以保留相关信息,否则在编译时这些数据会全部被丢弃。大部分解决方案要嘛是侵入式的(严重依赖于宏 — Macro,结果难以调试且要求怪异的语法声明)要嘛非常脆弱(fragile)(要根据实际代码不断更新样板,常常没有任何警告就中止运行)。提高鲁棒性的方法之一是自动生成这类样板。要实现这一目标,需要用某种方式解析代码,换句话说,需要了解什么信息该被保留。然而,解析 C++ 本身就是极其复杂的工作,要考虑各种怪异情况,如果真想这样做,消费的时间可能相当漫长。 1

即使只针对 C++ 某个“差堪可用”的子集进行解析,这类尝试要嘛失败了要嘛对编码规则有严格要求。也就是说,要求避免使用解析器无法理解的语法 — 一旦有人不按规矩提交代码解析器就会中止工作。要解决这个问题,我发现 LLVM 项目中有一个很好的工具:libclang2。由于 CLANG C++ 前端 和 libclang 调用的代码是相同的,所以它了解 C++ 的一切。该类库的最新发布可以支持 C++1x(如不出意外将是 C++14)的功能。唯一略有欠缺的是文档方面:其官方文档不过是 Doxygen 生成的参考,虽然有用,但不足以介绍如何使用该类库;加上问题本身的复杂性,学习曲线将十分陡峭。

本文要讲述的是如何用 libclang 及其 Python 绑定来实现一个实用的 C++ 代码生成器。在某种意义上,“实用” 意味着这不是一个通用的解决方案。这里所演示的不是某种具体的实现,而是一种解决问题的思路、一个详细的范例。借助这些想法,你可以自己创建通用的反射方案。本文的另一设计原则是尽力减少代码侵入以便能按自然 C++ 语法编写代码。同时我也鼓励读者自己动手,从头开始尝试实现自己的代码生成器。

我必须感谢 Eli Bendersky 的有关帖子3,它是我收集的资料中最好的参考之一。

准备工作
要读懂本文,读者可能需要具备以下知识点:

>>> 阅读全文

 

, , , , ,

C++ 11 中的多线程

文章评价:

第一个 C++ 标准发布至今已经过去十三年了,随着新的 C++11(或称 C++0X)标准的推出,C++ 标准委员会所做出的显著改变之一就是支持多线程编程。这是首次在 C++ 语言中为并行编程提供支持,而且与平台无关。

在 C++11 标准之前,编写多线程应用需要依赖于特定的平台扩展,如 Intel TBB、OpenMP、Pthreads 等等。现在有了 C++11 的标准线程库就方便了应用移植(例如 Windows 上的 C++11 多线程应用将很容易移植到 Linux 平台),另外对于熟知 Boost 线程库的用户来说,由于 C++11 标准库中许多命名与结构都和 Boost 相同,上手非常容易。1

C++11 标准库中的类可用于线程操作与同步、公用保护数据及低层次的原子操作。

C++11 标准中涉及多线程编程的主要有四个头文件,分别是:<atomic> ,<thread>,<mutex>,<condition_variable>和<future>:

>>> 阅读全文

 

, , ,

你应该了解的 10 个 C++ 11 的新特性

文章评价:

本文 1对一些 C++11 标准中的新功能进行了探讨。这里我建议所有 C++ 开发者应该学习和使用这些特性。C++ 11 增加了许多语言特性和标准库,本文涉及的不过是皮毛。不过,我相信其中的一些新特性应该为所有的 C++ 开发人员所熟知,并在日常工作中普遍使用。网上可以找到很多类似的文章,涉及不同的 C++11 特性。这里我尝试将一些应该经常使用的 C++11 新功能串联起来。

auto
在 C++98 标准中,auto 关键字就用在存储期规范中(Storage duration: 定义了对象在内存中的最小生存时间。最常见的存储期是自动存储期:在堆栈上分配的对象是自动分配和自动释放的)。在新的 C++11 标准中,其新用途是类型推断(Type inference)。auto 现在变成了类型占位符,它告诉编译器,应该从变量的初始化式中推断出它的实际类型。auto 关键字可以在不同的作用域中声明变量如:名称空间、块、for 循环语句的初始化声明等等。

auto i = 42;        // i 为整型
auto l = 42LL;      // l 为 long long 型
auto p = new foo(); // p 为 foo* 指针

使用 auto 意味着减少代码。(除非是 int 型,这样比 auto 要少输入一个字母)。回忆以前为了遍历 STL 容器元素,你会使用 typedef 来简化迭代器的编写,现在这种方法落伍了。请看:

std::map<std::string, std::vector<int>> map;
for(auto it = begin(map); it != end(map); ++it)
{

}

请注意,auto 不能被用作函数的返回类型,不过在函数有尾随返回值(trailing return type 2)的情况下,你可以用 auto 来代替函数的返回类型。此时, auto 告诉编译器不需要推断而只是直接在函数末尾查找返回类型。比如在下面的例子中,compose 函数的返回值就是操作符+ 的返回值,该操作符用于将类型 T1 和类型 T2 的值相加。

>>> 阅读全文

 

, ,

.NET 4.5 的五大最佳特性

.NET 4.5 已经发布了将近一年了,现在有个问题是 .NET 开发者的对于微软最新的发布版,通常只约略知晓一到两个特性,其它则只流于表面,它们最终不过成为 MSDN 上的简单文档说明而已。

如果你问个开发者 .NET 4.5 核心框架中多了哪些新特性,大部分人只会回答 async 和 awaitt。(至少和我打交道的人只提到了上面这些特性。)

确实,要深入了解所有的新特性非常困难。特别是,是否值得去了解这些特性完全取决于你手边的工作。

因此,在这篇文章中,我会介绍我所喜欢的几个 .NET 4.5 核心特性。这只是我个人的偏爱,未必就是你的最爱。不过如果我选的这些话题对不断壮大的 .NET 社区能有所帮助,那我就心满意足了。

注意: 本文只会涉及与 .NET 核心框架相关的新特性,而不讨论诸如 ASP.NET、 WCF、 WPF、 WWF 等等特性。

>>> 阅读全文

 

, ,

Scala 指南

一种可伸缩语言

Scala 是一种函数对象混合的语言,具有一些强大的优点:

首先,Scala 可编译为 Java 字节码,这意味着它在 JVM 上运行。除了允许继续利用丰富的 Java 开源生态系统之外,Scala 还可以集成到现有的 IT 环境中,无需进行迁移。
其次,Scala 基于 Haskell 和 ML 的函数原则,大量借鉴了 Java 程序员钟爱的面向对象概念。因此,它可以将两个领域的优势混合在一起,从而提供了显著的优点,而且不会失去我们一直依赖的熟悉的技术。
最后,Scala 由 Martin Odersky 开发,他可能是 Java 社区中研究 Pizza 和 GJ 语言的最著名的人,GJ 是 Java 5 泛型的工作原型。而且,它给人一种 “严肃” 的感觉;该语言并不是一时兴起而创建的,它也不会以同样的方式被抛弃。
Scala 的名称表明,它还是一种高度可伸缩 的语言。我将在本系列的后续文章中介绍有关这一特性的更多信息。

下载并安装 Scala

可以从 Scala 主页 下载 Scala 包。截止到撰写本文时,最新的发行版是 2.6.1-final。它可以在 Java 安装程序版本 RPM 和 Debian 软件包 gzip/bz2/zip 包中获得,可以简单地将其解压到目标目录中,而且可以使用源码 tarball 从头创建。(Debian 用户可以使用 “apt-get install” 直接从 Debian 网站上获得 2.5.0-1 版。2.6 版本具有一些细微的差异,所以建议直接从 Scala 网站下载和安装。)

>>> 阅读全文

 

, , , , ,

C++11 智能指针

文章评价:

许多程序员总避免使用指针,因为一旦处理不当,就会带来很多问题。所以新手程序员都不太喜欢指针。使用指针可能会引发许多问题,例如需确保指针所引用的对象的生命周期、虚引用(dangling references)和内存泄漏。

如果某内存块为多个指针变量所引用,而其中有个变量释放了这片内存,就会造成虚引用(dangling references)。另一种情况是,程序员从堆里申请了内存块,但未进行释放,这时则会造成内存泄漏。

某些资深程序员可能会说,你看我正确地从堆里获得了内存,进行相关操作,最后也正确地释放了内存, 这段代码干净漂亮,为什么还需要智能指针呢?

void Foo( )
{
    int* iPtr = new int[5];
    //manipulate the memory block
    .
    .
    .
    delete[ ] iPtr;    
}

的确,上面的代码目前工作正常,在理想情况下也能正确地释放内存。但如果考虑运行代码时的实际环境,在内存分配与释放之间存在着许多指令,这些指令可以做一些乱七八糟的事,比如访问无效的内存位置、除零错,甚至可能你的同事修改了你的代码,添加某种条件下的 return 语句。

>>> 阅读全文

 

,

Spark,一种快速数据分析替代方案

Spark 是一种与 Hadoop 相似的开源集群计算环境,但是两者之间还存在一些不同之处,这些有用的不同之处使 Spark 在某些工作负载方面表现得更加优越,换句话说,Spark 启用了内存分布数据集,除了能够提供交互式查询外,它还可以优化迭代工作负载。

Spark 是在 Scala 语言中实现的,它将 Scala 用作其应用程序框架。与 Hadoop 不同,Spark 和 Scala 能够紧密集成,其中的 Scala 可以像操作本地集合对象一样轻松地操作分布式数据集。

尽管创建 Spark 是为了支持分布式数据集上的迭代作业,但是实际上它是对 Hadoop 的补充,可以在 Hadoop 文件系统中并行运行。通过名为 Mesos 的第三方集群框架可以支持此行为。Spark 由加州大学伯克利分校 AMP 实验室 (Algorithms, Machines, and People Lab) 开发,可用来构建大型的、低延迟的数据分析应用程序。

Spark 集群计算架构
虽然 Spark 与 Hadoop 有相似之处,但它提供了具有有用差异的一个新的集群计算框架。首先,Spark 是为集群计算中的特定类型的工作负载而设计,即那些在并行操作之间重用工作数据集(比如机器学习算法)的工作负载。为了优化这些类型的工作负载,Spark 引进了内存集群计算的概念,可在内存集群计算中将数据集缓存在内存中,以缩短访问延迟。

Spark 还引进了名为 弹性分布式数据集 (RDD) 的抽象。RDD 是分布在一组节点中的只读对象集合。这些集合是弹性的,如果数据集一部分丢失,则可以对它们进行重建。重建部分数据集的过程依赖于容错机制,该机制可以维护 “血统”(即充许基于数据衍生过程重建部分数据集的信息)。RDD 被表示为一个 Scala 对象,并且可以从文件中创建它;一个并行化的切片(遍布于节点之间);另一个 RDD 的转换形式;并且最终会彻底改变现有 RDD 的持久性,比如请求缓存在内存中。

>>> 阅读全文

 

, , , , ,

通过 C# 使用 ZeroMQ (二) 多段式消息,JSON 和同步发布/订阅模式

文章评价:

这是该系列文章的第二部分。在这部分文章中,我们会讨论 ZeroMQ 所能发送和接收的两大类消息,并且如何用 JSON 来格式化消息。我们还会学习 如何使用轮询 (polling) 机制。在文章的最后,我们举例说明什么是同步发布/订阅模式。

ZeroMQ消息
ZeroMQ 套接字可以发送或者接受单段式消息(single-part)或多段式消息(multi-part)。

单段式消息
所谓单段式消息,就是一个消息只包含一帧。所谓帧是一个字节数组,其长度可以零以上的数值。在 ZeroMQ 参考手册中,帧也被叫做“消息段 message parts”。

举个单段式消息的例子,就比如说上一篇文章中我们发送/接收的所有消息都是单段式消息。在发送和接收的操作中,我们使用的是字符串,而字符串实质也是一个字节数组。

>>> 阅读全文

 

, , , ,

ADA 语言编程 (一)

文章评价:
在上个世纪 70 年代,美国国防部 (DoD) 发现其所属的嵌入式计算机系统项目中,使用的编程语言数量逐日增多,其中很多语言十分陈旧或者需要依赖于硬件,而且没有一种语言支持安全的模块化编程,对此 DoD 感到十分担心。为此,DoD 在 1975 年成立了高级语言工作组 (HOLWG),它的使命是就是寻找或者创造某种适合国防部需要的编程语言,以便减少现有编程语言数量。该小组最终的工作成果就是 Ada 语言。由此,这类项目中使用的高级编程语言的数量从 1983 年的 450 种编程语言,减少到 37 种(1996年)。

高级语言工作组精心设计了 Steelman 语言规范,这是一系列用来述明编程语言需要满足哪些要求的文件。许多既有的语言按次规范进行了审查,但最终(1977年) 团队得出结论:没有现有的语言符合规格。

最终 HOLWG 提出了开发一种新的编程语言的建议,并且雇佣了四个承包商分别进行有关方案开发,代号分别是红 (Benjamin Brosgol 所领导的Intermetrics)、 绿 (Jean Ichbiah 所领导的 CII Honeywell Bull)、 蓝 (John Goodenough 所领导的 SofTech) 和黄 (Jay Spitzen 所领导的SRI International。1978 年 4 月公开审查之后 红和绿这两个方案进入了下一阶段。在 1979 年 5 月,最终选择了 Jean Ichbiah 所领导的 CII Honeywell Bull 所实现的“绿”方案,并定名为 Ada — — 这是为了纪念 Augusta-Ada-Lovelace 伯爵夫人。该方案受到了上世纪 70 年代 Ichbiah 和他的小组所开发 LIS 编程语言的影响。

由于 Ada 以安全性为第一(safety-critical) 的特性 ,因而 Ada 除了在军事上得以应用,也应用到了那些软件 bug 会产生严重后果的商业项目中,例如航空和空中交通管制、 商业火箭 (例如阿丽亚娜 4 和 5),卫星和其他空间系统、 铁路运输和银行。例如,波音 777 的线传飞控系统软件就是 Ada 编写的。加拿大的自动化空中交通系统是由 100 万行的 Ada (源代码计数) 构成的。得益于 Ada 的高级分布式处理、 分布式的 Ada 数据库和面向对象的设计,Ada 也用在其他的空中交通系统,如英国的下一代 iFACTS 空中交通管制系统是用 SPARK Ada 设计和开发的, 同时它也运用于法国 TGV 高速铁路系统中的 TVM in-cab 信号系统,以及巴黎、 伦敦、 香港和纽约地铁信号系统。

标准
1983 年该语言成为了 ANSI 标准 (ANSI/MIL-STD 1815A), 该版本未做更多的修改就在 1987 年成为了 ISO 标准 (ISO-8652:1987)。该版本就是我们知道的 Ada 83,(按 ANSI 接受为标准的时间),有时也按 ISO 接受为标准的日期称为 Ada 87。

>>> 阅读全文

 

, , , ,

Previous Posts