Apache ActiveMQ

June 27, 2011

Just for fun, I am interested with building a chat system using Apache ActiveMQ, a messaging broker. ActiveMQ supports multiple messaging protocols, and I am interested with the STOMP protocol.

Download and Install

On Mac OS X, ActiveMQ can be installed using Homebrew:

brew install activemq

On Linux and Cygwin, ActiveMQ can be installed by downloading the binary package from http://activemq.apache.org/activemq-550-release.html.  Because ActiveMQ is written in Java, we need to install Sun’s J2SE for Windows if we want ActiveMQ run with Cygwin.

Start with STOMP Support

To make ActiveMQ support STOMP protocol, we can run it with a pre-distributed configure XML file:

cd activemq-install-directory
./bin/activemq-admin start xbean:./conf/activemq-stomp.xml

Write a Client

ActiveMQ can take charge of the server-side, but you need to write your own client program of the chatting system. A client library of the STOMP protocol in C is libstomp.  A slightly modified version of libstomp and a client program can be checked out from Google Code:

svn checkout https://yiwang-learning-projects.googlecode.com/svn/trunk/libstomp

Objective-C for C/C++ Programmers

June 19, 2011

Here is a very good tutorial: http://www.otierney.net/objective-c.html, it shows how to use Objective-C in Mac OS X, Linux and Cygwin/Windows. This post complements the tutorial with some details.

To programming using Objective-C on Mac OS X, we need XCode, which contains the Objective-C compiler that we need. On Linux or Cygwin, we need to install GNU Compiler Collection (GCC) in order to get the compiler.

However, programming in bare-bone Objective-C is not funny. Instead, we want a versatile toolkit which helps us with UTF-8 strings, memory management, parallel computing, GUI and etc. This is like how C++ programmers rely on STL (and maybe boost) and how Java developers rely on JDK.

On Mac OS X, this versatile toolkit is Cocoa, which is installed as part of XCode. On Linux and Cygwin, we have the sibling of Cocoa, GNUStep. Both Cocoa and GNUstep are descendants of OpenStep, a product created by NeXTSTEP and Sun jointly.

XCode can be downloaded from Apple’s developer program, and the installation process is straight-forward. On Ubuntu/Debian Linux, we can install GNUstep from binary package:

sudo apt-get install gnustep-devel

On Cygwin, we have to build and install GNUstep from source package. Here is a step-by-step guide.

Given Objective-C compilers and Cocoa/GNUstep installed, we can start working on a hello world program:

#import <stdio.h>
#import <Foundation/Foundation.h>

int main(int argc, const char *argv[]) {
  printf("Hello World!\n");
  NSLog(@"Hello World!\n");
  return 0;
}

To build this program on Mac OS X (using GCC distributed with XCode):

gcc main.m -framework Foundation -o hello

or, using Clang instead of GCC:

clang main.m -framework Foundation -o hello

Where, the term “framework” comes from NextSTEP and indicates a package of header files and libraries.

To build the program on Linux:

gcc -o hello main.m -I/usr/include/GNUstep -lgnustep-base -lobjc

You can checkout above source code and Makefile from the following SVN repository:

svn checkout http://yiwang-learning-projects.googlecode.com/svn/trunk/objc-runtime

For a concise description about the Objective-C language, please refer to: http://cocoadevcentral.com/d/learn_objectivec, or the official document.


杂谈现代高级编程语言

June 19, 2011

几个月之前,Slashdot转载了Robert Harper教授的一篇博客,说卡内基梅隆大学计算机系把”面向对象编程“从大一新生的必修课中删掉了,其原因是

Object-oriented programming … is both anti-modular and anti-parallel by its very nature.

这两个原因(anti-modular和anti-parallel)都是很重的指责了;尤其是anti-modular,因为OO的基本思想通常被理解成“封装”,从而实现模块化。

我是在1995年第一次听说“面向对象”(Object Oriented)这个说法。当时在学习正在成长过程中的C++,用的是Borland C++ 1.0。从那时开始的很多年里,”类“(class)、“对象”(object)和“方法”(methods),以及在这些概念之上构建的”继承“(inheritance)和”多态“(polymorphism)都是我理解中OO最核心的思想。我猜大多数程序员在这方面的认识都和我差不多。

但是“封装”真的是OO的本质嘛?直到最近为了给iPhone写个玩具程序而学习Objective-C(一种非常古老和原始的面向对象编程语言)的时候,才注意到早在1998年,OO之父Alan Kay就曾经在一篇邮件中说,他很后悔发明了“object”这个词,从而误导大家,把注意力都集中到“封装”,而忽视了OO的本质——messaging(消息传递)。Alan Kay的原话是:

The big idea is “messaging” … . The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be.

Objective-C的设计是非常强调“消息传递”(messaging)的——对一个object的method的调用,被称为“给这个object发了一个消息”。为了突出调用method时指定的参数(parameters)实际上是消息中的一些内容,Objective-C不惜把method的定义方式都做了相对于C的很大的修改,从而把参数嵌入在method的名字里。比如在一个叫做myWebView对象中搜索一段文字,要求不区分大小写,从前往后搜索,用Objective-C来描述是:

[myWebView searchFor:myString 
           direction:YES
       caseSensitive:NO
                wrap:YES]

而用C++或者Java来描述,则是

myWebView.searchFor(myString, YES, NO, YES)

乍看上去,C++ 或者Java的方式更简短,但是Objective-C的方式更强调“发消息”。实际上,上面Objective-C语句会被翻译成如下C函数调用:

objc_msgSend(myWebView,
             searchFor:direction:caseSensitive:wrap:,
             myString, YES, NO, YES)

从强调messaging的角度看,Objective-C确实比C++和Java更符合Alan Kay对OO思想的描述。

OO中的messaging思想不仅体现在Objective-C语言以及在其上构建的NextSTEP/Cocoa GUI编程套件上。在Cocoa因为Mac OS X和iPhone流行起来之前,很多人都接触过Qt(一种基于C++语言的GUI开发套件)。Qt对messaing的支持比Objective-C/Cocoa更彻底——每个object可以发出若干signal,每个signal可以触发这个object自己的或者其他objects的若干个slot。

有意思的是,为了支持messaging,Qt对C++语言做了扩展,而Objective-C对C语言做了扩展。这两套扩展都利用了起源于C语言的“宏”机制(macro)。类似的做法也可以用于Java,前提是我们在调用Java编译器之前,先调用一下cpp宏展开程序来预处理一下我们的Java程序。这事儿可以留待Java爱好者们来搞?

不管是Objective-C还是Qt,都会“尽力”去检查一个object是否支持一个method(或者叫message),但是并不禁止程序员向一个object发送一个它不认识的message(或者调用一个object没有的method)。说“尽力”检查,是因为两者都不能保证检查的完备性。这是因为Objective-C和Qt都支持多态;具体的说,接受message的object可能是表示为一个指针(指向object),所以直到运行时候,当一个message抵达某个object的时候,系统才能(通过查这个object对应的message list)知道这个object是否认识这个message。

这种灵活性在Google新推出的Go语言中也同样实现了,而且做的很极致——Go语言中没有class的概念;换句话说,不需要是class类型的object才能有对应的方法(methods)——Go允许给几乎任何类型附上methods。而且程序中可以很方便的检测一个object是否支持(一组)methods,比如:

type Stringer interface {
        String() string
}
s, ok := v.(Stringer)  // Test whether object v implements "String()"

【和Go的这种灵活性类似的,Objective-C允许给已经定义了的class增加一些methods,而不需要derive subclass;Objective-C的这种机制被称为category。和Go不同的是,一个category是对某个class的一个扩展,而Go语言里完全没有class了(但是有interface的概念)。】

说到这里,我觉得差不多可以反过来理解Robert Harper教授对OO的评价了——其实Robert不是在藐视OO,而是在指责很多imperative OO languages(我理解包括Java和未经Qt扩展的C++;详见后述),认为这些语言没有完成实现OO中object messaging的核心思想,从而不算实现了“模块化“(modulization)的思想。

上述都是关于程序的模块化。实际上,模块化的另一个主要方面是对“数据”(data)的模块化。从图灵机和lambda-calculus开始,计算机科学家们就注意到程序和数据是统一的;比如在冯诺依曼的“二进制存储电子计算机”模型里,程序和数据都是bit stream。即时我们在讨论高级编程语言的时候,程序和数据也不应该被分开。因为现代数据操作和模块化的基础是并行程序(parallelism),而有效实现并行的基础是程序的first-class表达,也就是把程序作为一种基本数据类型。

鉴于这篇帖子已经很长了,这段话就作为下一篇帖子的提纲吧。下一篇帖子里,我们来说说XML、JSON、MessagePack、Protocol Buffers这些persistent data structure,以及用源于古老的functional programming paradigm的Go语言和MapReduce实现的并行数据操作。


关于 Dhanji R. Prasanna 的一篇博文

June 14, 2011

有朋友推荐我看到一篇前 Google Wave team 的员工的博客。其中对于 Google 工作环境的评价,让我很自卑。进入 Wave team 是当时好多中国工程师梦寐以求的,老外自由度就是高,进去了还能挑三拣四的。

其中对于 Google 软件技术的部分评价,我实在不敢苟同。原文如下:

Protocol Buffers, BigTable and MapReduce are ancient, creaking dinosaurs compared to MessagePack, JSON, and Hadoop. And new projects like GWT, Closure and MegaStore are sluggish, overengineered Leviathans compared to fast, elegant tools like jQuery and mongoDB. Designed by engineers in a vacuum, rather than by developers who have need of tools.

这里提到的有些技术确实不怎么的,比如 MegaStore。有些技术我不了解,比如 GWT 和 jQuery。但是要说 Protocol Buffers 不如 MessagePack,是有问题的。MessagePack 在他的主页上说,serialization 和 deserializtion 的速度是 Protocol Buffers 的四倍,而且提供了强大的 RPC 机制。(Google Protocol Buffers 的开源项目中没有 RPC 功能,有很多其他开源项目作为 Protocol Buffers 的扩展,加上了RPC 功能。)但是 MessagePack 好像没有 versioning 功能,而这个才是 Google Protocol Buffers 的核心设计思路 —— 要能支持大规模系统,大到我们不能保证其中所有涉及通信的模块能同时更新;而 serialization 不是什么神妙的东西 —— 从 MFC 和 Java 的 serialization,到 XML、JSON、BSON 都在搞这个。你要是不喜欢,自己做一套自己的也不难。

MapReduce 不如 Hadoop,这个就更不靠谱了。 Hadoop 才应该是博客原文中所说的“恐龙”。用 Java 实现 —— 在并行计算中放弃效率去追求莫名其妙的“可移植性” —— 现在谁家搞 datacenter 还去找些 MIPS 处理器的机器混合着 Intel 机器来用啊?!过分复杂的设计(各种 readers、writers)来追求支持各种文件格式 —— MapReduce 相对于 MPI和BSP 的最根本优势就是“限制很多、可定制程度很低、不给程序员出错的机会”,从而提程序员遮掩并行程序设计的复杂性。Google 这么多年里做了这么多产品,而 MapReduce 只支持四种文件格式:初学者好玩用 text、需要支持 key-value pairs 用 SSTable、不需要则用 Record file、要扫描数据库则使用和 BigTable 的接口。而且 Google 是个代码公开的公司,鼓励大家修改代码;如果这些文件格式不够用、可以自己从标准的 reader、writer base classes 派生支持其他格式。但是却没有人真的这么做。

最后说一点最关键的:Google MapReduce 的每个并行计算作业(job)有自己的 master 调度和控制作业;而 Hadoop 在一个 datacenter 上的所有 jobs 共享一个master(称为 JobTracker),只要这个 JobTracker 挂了,整个 datacenter 就得重启 —— 这种shi一样的设计,何先进之有啊?!在 Apache Hadoop 的官方博客上,赫然写着“下一代Hadoop计划”是让每个 job 有自己的 master,并且要学习 Google 用一个专门的分布式操作系统来管理机群硬件的做法。


MongoDB, Redis, BSON, JSON and etc.

June 1, 2011

The network communication and disk storage of data in MongoDB is based on BSON.

BSON (binary JSON) is a binary-encoded serialization of JSON-like documents.

JSON (JavaScript Objective Notation) is a lightweighted data-interchange format.

JSON is built on two structures:
– object: a collection of unsorted name/value pairs, and
– arry: an ordered list of values,
where each value could be either of the following:
– object
– array
– string
– number
– true/false/null

BSON is comparable with Protocol Buffers, where BSON is schema-less
and thus flexible, but has the overhead for field names in the serialized data.

document := int32 e_list ”
elist := a list of element
element := e_type e_name value

Note: compared with JSON, there is only “object”, but no “array”, in BSON.

The C++ implementation of BSON is provided by MongoDB:

http://www.mongodb.org/pages/viewpage.action?pageId=16646453

Both BSON and MongoDB have Go API.

MongoDB v.s. Redis v.s. memcachedb v.s. Berkeley DB

Redis, memcachedb and Berkeley DB manage key-value pairs. MongoDB is
more powerful and support geo-indexing.

Redis and memcachedb run as services, but Berkeley DB, as a library,
runs in the client process space.


Follow

Get every new post delivered to your Inbox.