很长时间以来我对rails框架本身没什么兴趣,因为我从来都不是web fans,15岁那年我打印了一本HTML Reference准备学习一下,感觉完全nonsense。很长一段时间(大约有3年吧)里基本上看到Markup Language我就会大脑短路。但是我对rails背后的东西很感兴趣,是什么让rails如此有效率,一开始我以为是Ruby DSL,但随着做的rails项目越来越多,我发现rails的效率的根源来自它对delphi的继承和发扬。

1.  data centric object model Active Record
delphi之所以成功,在于它看准了大部分商用软件都是数据库核心的,并为之设计一套相应的框架, delphi的核心就是围绕数据库进行开发(李维同学的borland传奇里写道,当时之所以起名字叫Delphi,就是因为要taking to Oracle)。而rails也很好的在新时代(Web时代)把握了相似的核心点——content是web的核心,以及数据库数据到content的映射是动态web的核心。因此它没有采用所谓的更加严肃的ORM技术。而是依然使用了delphi时代的active record(但是进行了object封装)。如下代码示范了ruby和delphi在active record实现上的相似

Ruby
class Person < ActiveRecord::Base
end

x8x 
= Person.new :name => 'x8x'
x8x.age 
= 15

Delphi

people : TADOTable;

begin   
   people.Table 
= 'people';
   people.InsertRecord(
'x8x');

   people.First;
   people.FieldByName(
'age') := 15;
end


可以看出,Delphi的数据库味道更浓一些,而ruby则更多使用了对象的视角(我记得在98年前后(我变成oo狂热分子之后),在写delphi的时候我基本上不会直接使用Table对象了,而是做一些简单的封装,用business object代替直接的数据库对象。但是最后由于和delphi的ui组件结合的不好而放弃)。但是active record的pattern是一致的。

2. DB(resource)-aware UI component —— Action View

Delphi另一个为人称道的地方是DB-Aware的UI组件,像TDBLabel, TDBMemo还有至今仍位人称道的TDBGrid,极大的简化了UI的开发。不过说到底,仍然是Delphi数据库核心策略的延续。同样,rails的view helper也是db核心的。text_field之类的可以自动感知active record的内容和错误。

<label>Name:</label> <%= text_field 'person''name' %>



nameLabel : TDBLabel;

nameLabel.DataSource 
= peopleTable;
nameLabel.Field 
= 'name';
nameLabel.Label 
= 'Name';

抛开Desktop和web的差异,也可以算是大致相当吧。

3. Simple Component Model —— Plan Object as Component

Delphi是基于组件开发,并且是非常成功的一个组件模型。基本上有经验的delphi程序员,都会在开发过程中抽象几个VCL component出来简化自己的开发。一方面是DRY精神,另一方面Delphi简单的组件模型使得这样做的代价非常的小。Delphi的组件基本上就是一个对象,重构的过程中修修改改就成组件了。rails其实有类似的机制,而且更简单直接,更符合web时代的胃口,一个对象外加一个helper就可以成为一个UI组件。与此同时rails还有另外一个天然的同盟——Ruby DSL。把以前Delphi需要用UI设计器的地方都用Ruby DSL代替了。这一点是我最近在用rails做曹老师华丽的RedSaga的时候推行DSL geek主义时发现的。比如现在我有这样一个tiny DSL用以定义portlet:

in controller

@portlet = Portlet.new do
            name 
'administration'
            title 
'Administration'
            tabs 
do
                Projects :controller 
=>'projects', :action => 'list'
            end
        end

in view
<%= render_portlet @portlet %>

这种描述/configuration block风格的dsl与delphi组件的初始化非常相似,或者可以说,只有语法上的差异而无思路上的差异(当然delphi可以借助IDE而不是语言来指定这些,但是这个做法是没有生产力的)。

with Portlet do
   Label 
= 
   Name 
= .
   Tabs[
0].Controller = 
   Tabs[
1].Action = 
end

rails和delphi这种轻量的组件模型,使得构建组件/复用组件级的代价极小。因此可以极大的提高开发效率(我至今仍记得,01年前后接了一个Delphi私活,客户要求Office XP菜单风格,我找了一个XPMenu的控件,直接仍上去,自己的代码一行没改,菜单就Office XP了...)。

总之,Delphi的效率要素Rails大部分都学走了,最后简单总结一下rails在delphi基础上的发扬:

1. 用ruby而不是object pascal。语法上更灵活简单
2. Object Model on top of ActiveRecord,比起Delphi可以跟好的使用OO开发。
3. 组件模型更简单
4. CoC,这个就不说了
5. expressive Ruby DSL

最后最后,说一下Delphi for PHP,做得很华丽。但是UI部分我不是很喜欢。