目标经常不是目标

开车上下班,常看到要速度不要安全的。为了三秒钟闯红灯的,为了多走几米就在后面狂闪灯的,更有一路狂飙,在高架上蛇行的。

如果你说他们是赶时间,我看未必。这只是个习惯。其实真实的原因,绝非别人以为甚至是自己以为的那个目标。很多人就是为了这种竞争或者动脑子的乐趣。

说是为了赶时间的,说不定回家就是坐在沙发上百无聊赖,或者明知道到了也是早到,但这丝毫不影响一路超车,见逢插车,丝毫不会对行人有任何的顾及,或者手下留情而不去动自己的喇叭。这些真的是和时间有关吗?

打电子游戏,天天睡不着觉的想着的不外乎是自己的那些积分。自己以为这是自己打电子游戏原因。如果真的给他的无敌帐户,谁也打不死他,积分自己想写多少就是多少,任何任务只要按一个键就可完成,他在游戏里梦寐以求的一切都可以弹指之间得到满足?你猜会怎样?他会立刻放弃这个游戏。‘

哦。我知道了,原来他要的是挑战,而不是他以为的积分。

说到钱,也是一样。很多人都成功的让自己觉得,自己工作就是为了赚钱,其实远不是那么回事。当收入已经可以支付基本的生活支出以后,绝大多数人工作已经不仅仅为了钱。如果不相信这个论断,看看退休的人,已经是亿万富翁的人,还有休过漫长的产假归心似箭的冲回公司的人就知道不仅仅是为了钱那么简单。就算节约成癖的人,看似是钻到钱眼儿里面,其实,你不觉得天天想尽办法省钱,不是一种有趣的智力上的挑战吗?

所以只有个人的成就感,也来的更真实。而此之外,虽然是包括自己在内的所有人都以为是自己的目标,却不见得是真实的目标。

追求外在的目标让人忙碌,就像我们终生都在忙于追求幸福,却没有发觉,幸福就在忙碌本身之中。

注:弗洛伊德马斯洛的需求理论很有道理。上面的推论,也仅仅是对于满足下面几层需求以上的人才生效。

为什么HTML里的Comment是<!–开头?

最近做了两周的产品组培训,让自己对于技术的兴趣又重新燃起。我觉得一个好的技术人员要至少做到两点:开放(或者说有好奇心)和深入(或者是打破沙锅问到底)。在准备下周的UI训练营之前,我简单的看了一些HTML代码,发现还有很多以前忽略的东西。比如我问的这个很白痴的问题:

为什么HTML的comment都是写成

<!– 这是段注释 –>

形式?

这个看起来最不像HTML的语法,正是源于HTML的父规范 – SGML。在SGML语言里面,<! >表示SGML中的声明,比如

<!ELEMENT IMG – O EMPTY — Embedded image –>

而在SGML里面,评论是用简单的两个横线表示的。第一对横线表示评论的开始,而第二对表示评论的结束。在HTML里面,就直接继承过来,用<!– –>来代替。

就像还有另外一个SGML语法写出来的东西,我几乎从来没有真正关心过,或者说还很少手写的,就是XHTML 1.0或者HTML 4.01前面的DOCTYPE,比如:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>,这真正代表着什么呢?难道就是一行字符串吗?其实,可以说浏览器就把它当作一段字符串,但字符串的生成,还是有历史原因的。

比如说

  • <! 表示SGML的声明的开始
  • DOCTYPE是SGML的语法的以部分,就像另外一个常用的,ENTITIES,在DTD结构的语法里面常常用到。
  • html说明了这个SGML文档的根tag。
  • PUBLIC和SYSTEM相对。SYSTEM 会制定这个文档相对应的DTD的未知,应该是:SYSTEM "/dtd/xhtml.dtd"这样的形式,而PUBLIC表示下面将不用URL而仅仅是一个字符串规定DTD的位置,而这个字符串是如此的特殊,我们有一个名字来规定,叫做Formal Public Indentifiers (FPI)。
  • “-//W3C//DTD HTML 4.0//EN”这就是FPI。云里雾里的字符串也是有意义的:ownername//class description//language。其中,ownername 是 -//W3C。其中减号表示W3C是一个还没有在ISO(或者其下的ANSI注册的机构),+号代表的是注册的(这里感觉到了1960年代那种互联网之前的迂腐的味道。以后所有的这些复杂的注册统统都用基于现在的域名注册系统中了,比如xmlns命名空间的注册借用URI就显得聪明的多)。就连W3C都没有注册,可见注册机制已经名存实亡。DTD表示了类型,而HTML 4.0是这个DTD的描述性的名字。最后的EN同样借用了ISO 639的语言代码。
  • “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”这个按道理是不需要的,因为如果有了FPI,所有的现代浏览器应该都自带从这个著名的FPI到本地缓存的一份DTD文件的对应表,但是如果没有(这是严谨的考虑),才把URL作为PUBLIC的第二个参数,传进去。。。(顺便提一句,FireFox不会去读任何外部或者内部的DTD,用来验证HTML的合法性,换句话说,FireFox不支持DTD验证).
  • >跳出SGML世界,回到HTML文档中去。

这样分析,也就大概的知道这里是怎么回事了,至少对于记忆这个字符串有好处。

Web的历史一直是借用和采纳的历史,HTML借用SGML的规定,SGML有借用ISO的定义,就像SMTP借用了URI的定义作为自己的规范中的一部分一样。。。

而且,这种过去的规范对于新技术的影响,就有点像两匹马的屁股决定了古代车辆的宽度,之后决定了地上的车辙,进而影响到了铁路的宽度,限制到了铁路运输的货物到校,随之限制了运载火箭的直径,知道决定了卫星的直径。。。这听起来虽然有点牵强,但说的就是这种例子。

技术加上一点点考古,真有趣。

Symbol表的启发

本文是《google.loader 代码欣赏》系列的一部分。

这段代码原本是非常好读懂的,但是当所有的函数名和变量名都用小写的a到z之间的一个字母代替以后,就变得不好读起来,尤其是这段令人抓狂的代码,

function k(c,a,b,d,e,f){
this.a=c;
this.g=a;
this.f=b;
this.d=d;
this.e=e;
this.b=f
}

不死一堆脑细胞是很难摸得到门路的。

其实,这说明,这个代码一定是经过编译的。说编译可能有点不是很准确,说“转化”或者更恰当些。为什么要这么做呢?

Symbol表

在整个代码的最后一句

g(“google_exportSymbol”,g);

泄露了些原因。

Symbol是什么?在Windows的世界(或者几乎所有的编译语言,或曰高级语言的世界里),都少不了Symbol这个东西。在编译的时候,所有的函数名,变量的名字,都会被一个地址或者一个标记代替,写进二进制文件里面,所以如果从一个.exe文件反编译出来,还是可以看得出执行的语句逻辑的(用汇编的形式),却永远无法获取原来的源代码。而Symbol文件,就是连接编译好的二进制程序,和源代码的桥梁,包含了关于函数,变量的名字以及源代码的文件名以及行数的信息。而Symbol文件编译以后,一般不和执行文件一起发布,需要另外去找。比方说当年调试IIS的时候,就把IIS的Symbol拿过来,再把源代码拿过来,用Windbg就可以开工了。。。这是以前的古老的Windows时代一个程序员要做的事情(对了,现在所有的Windows公开的Symbol可以在这里获得)。Symbol简直就是Windows世界里的解开二进制文件的一把神秘的钥匙。

Google Loader的Symbol库

既然有编译,就一定要有一张自己存着的对应表格。我猜测这个表格应该是这样样子的:

function “google_exportSymbol” => function “g”, @d:\my\code\uds\uds.js line #122
function “setApiKeyLookupMap” => function “p”, @d:\my\code\uds\uds.js line #102
function “load” => “o”, @d:\my\code\uds\uds.js line #77
function “writeLoadTag” => “m”, @d:\my\code\uds\uds.js line #115
var “google_exportSymbol”::”funcNameString” => “c”, @d:\my\code\uds\uds.js line#122
var “google_exportSymbol”::”function” => “a”, @d:\my\code\uds\uds.js line #122

需要说明的是,我没有原来的代码,也彻底不知道这个Symbol表是不是存在,甚至在这里开玩笑一样的假设原来的代码放在一台Windows的机器上面(显然这不是很可能),但我希望就是表达这么一个意思,就是说,如果有编译,就应该附属产生这样的一个Symbol表,只不过没有公布而已。如果没有这个表,debug会是一件和我们直接看源代码一样痛苦的过程。

DLL的exportSymbols

如果大家熟悉Windows的DLL文件结构的话,就会发现exportSymbols和importSymbols是一个常见的概念。就是说,虽说在DLL内部所有的函数的名字已经被编译的面目全非,就像这里的函数g(),函数q()一样,但是为了方便外界的调用,还是把一个标准的接口给输出(export)出去。打个比方,一个Windows XP上的c:\windows\system32\user32.dll就export了732个之多的函数(函数名是字符串,比如ActivateKeyboardLayout,实际的函数确实一个地址为:7E42D32Ah的EntryPoint。

微软的世界和Google的世界

一个微软的世界的基石应该是PE(Portal Exexcutable)的文件格式(也就是.EXE, .DLL所使用的格式),这些格式让DOS操作系统可以”load”到内存里面执行。

那么在Google的世界里面先出现了一个loader(就好比DOS的loader),然后作为load的基础函数出现了这么一个google_exportSymbols,这是巧合呢,还是意味着什么呢?

且听下回分解。

注:第二次(其实是不知道多少次)声明,以上纯属个人的主观臆断,就好像听到了“咕咚”的声音就惊呼“咕咚来了”的猴子一样。或许是真的“咕咚”来了,或许仅仅是一个熟了的果子掉到湖里而已。是哪一种?只有时间告诉我们。

用匿名函数避免命名冲突

本文是google.loader 代码欣赏系列的第二部分。

第一个匪夷所思的地方,可能就是这一段了

if (!google.loader) {
google.loader = {};
google.loader.ServiceBase = “http://www.google.com/uds”;
google.loader.ApiKey = “internal”;
google.loader.KeyVerified = true;
google.loader.LoadFailure = false;
google.loader.AdditionalParams = “”;
(function() {
//大量的函数定义,变量声明以及函数的执行(整整100多行)
})()
}

基本上就是说,它写了一个这样的语法:

(function(){})()

就算是看得懂,这么绕来绕去,除了炫耀之外,又有意义呢?

匿名函数

先撇开Google的代码,看一下JavaScript其实是支持这种形式的行数定义的:

function(msg){ alert(msg); }(“hello world”);

这其实是两步:第一步,定义了一个函数,相当于:

var abc = function(msg) { alert(msg);}

第二步,立刻执行它:

abc(“hello world”);

把两个语句拼接在一起,然后去掉abc这个函数的名字,就成了现在的语法形式。

结合前面的

google.loader = {};

一起看,其实在这里是定义了google.loader这个对象的一个匿名的成员函数,并且立刻执行了这个成员函数(就是说完成里面的一些列初始化的时候需要干的事情)。

匿名函数的用处

虽然可以理解这里是个匿名函数,但是为什么要这么做呢?

我猜想(请注意,所有这里想的都是一个猜想,并且可能是众多原因之中的一种而已,欢迎大家补充),最主要的考虑是避免命名冲突。

因为这段JavaScript作为Google的其他的各项服务的入口,是会被全球很多的网页引用的。像任何的JavaScript引用(包括PHP的引用),如果被引用的代码和外面的代码一不小心用了同样的名字,就不可避免的发生命名冲突。对于小范围的代码或许还可以用起很怪异的名字的方法企图避免,而对于Google这样的应用,靠运气就有些说不过去。如果是一个匿名函数,外面将永远无法直接访问它(总不能写一个这样的一个没有函数名的调用吧:())。从这一点来说,不可能有命名冲突。

封装

另外的一个好处,有可能是为了更好的封装。比如在这个函数里面,有很多的函数定义,比如

q(); p(); m(); g(); i()

还有大量的变量:

var j; var h; var l;

等等。在JavaScript里面没有简单的private这样的定义私有函数或者私有函数的方法。如果调用者可以随心所欲的访问到这些中间的(随时可能变化,甚至移除)成员。对于这么一个开肠破肚,一览无余的对象,从一个API提供者的角度来看(和使用者的角度来看),的确是个挺恐怖的事情。

如果放在一个匿名的函数里面,外界就再也没有办法直接访问到里面的函数了。内部的逻辑被完美的封装了起来。这样一来,这些函数和变量多么的安全!

安全是安全了,但是定义了这么多的函数,仅仅是为了不被外界访问吗?显然不是,所以接下来要做的事情,就是把这些函数输出出去,也就是google_exportSymbol,或者说是函数g()要做的事情。

且听下回分解。

注:接下来,或许还要说说: 输出函数供开发者使用, JavaScript中的面向对象, prototype的扩展方式, Undocumented的神秘参数, 编译后的JavaSscript好比汇编语言,和 Symbol表的启发。

google.loader 代码欣赏

缘起

五一期间和老冒聊天,其中就提起来保持技术的敏感性是聊起技术型CEO的优势,也是一直需要不断努力充电的。很受启发,所以就顺手拿起一段Google的Javascript,欣赏一番。

这段JavaScript的URI(沿用Tim Berneris Lee喜欢用的URI而不是URL)很酷:

http://www.google.com/jsapi

在我写这篇文章的时候,也可以用这个URL也可以访问到:http://www.google.com/uds相同的内容。

单单挑这一段代码有几个原因:

  1. 这是分析最近的Google的所有代码的起点。在最近的Google AJAX Feed API文档里面提到,“Google正在向一个新的编程模式转移”,说的就是这一行代码。比如AJAX Feed API的开始调用就用如下语法:

    <script type=”text/javascript” src=”http://www.google.com/jsapi?key=YOUR_KEY_HERE”></script>
    <script type=”text/javascript”>
    google.load(“feeds”, “1”);
    </script>

    其中调用的就是这段神秘的JavaScript。

  2. 这段在浏览器里看起来不过27行,按照最标准的折行以后也不过100行的代码,第一遍看起来,真是彻底不知道它在干些什么,甚至怀疑它是不是用JavaScript写的。如果能很透彻的看懂这个代码,也就说明JavaScript的基本概念掌握的还可以。研究的时候,的确重温了n年前学习JavaScript的一些概念。
  3. 第三个原因,就是通过研究这个代码,可以隐约的感觉到一个新的基于Web的操作系统的到来。这个Google Loader,和早年的DOS加载模块是如此的神似,却有几乎没有任何形似的地方。通过这个代码,让我们可以窥到一些未来的样子。
  4. 最后一个原因就是,在我写准备写点东西的时候,把这段代码中最有标志性的google_exportSymbol函数拿到Google里面搜索,居然只有一篇文章提到,而且还仅仅是贴了代码。难道这么重要的一个文件,全世界的开发者没有兴趣分析一下吗?

好了,现在开始看代码。

代码全文

经过简单的代码格式化(仅仅加上回车),这段代码看起来是这样的。努力想想,他究竟是干什么的呢?

if (!google) {
   var google = {};
}
if (!google.loader) {
   google.loader = {};
   google.loader.ServiceBase = “http://www.google.com/uds”;
   google.loader.ApiKey = “internal”;
   google.loader.KeyVerified = true;
   google.loader.LoadFailure = false;
   google.loader.AdditionalParams = “”;
   (function() {
      Function.prototype.__google_inherits=function(c){
         var a=function(){};
         a.prototype=c.prototype;
         this.prototype=new a;
         this.prototype.__google_super=function(b,d,e,f){
            var n=Array.prototype.h.apply(arguments,[1,arguments.length]);
            return b.apply(this,n)
         }
      };
      var h=null;
      var l=false;
      function i(c){this.a=c}
      i.prototype.c=function(c,a){
         var b=””;
         if(a!=undefined){
            if(a[“locale”]!=undefined){
               b+=”&hl=”+encodeURIComponent(a[“locale”])
            }
            if(a[“nocss”]!=undefined){
               b+=”&output=”+encodeURIComponent(“nocss=”+a[“nocss”])
            }
            if(a[“other_params”]!=undefined){
               b+=”&”+a[“other_params”]
            }
         }
         if(h!=null&&!l){
            b+=”&key=”+encodeURIComponent(h);
            l=true
         }
         return google.loader.ServiceBase+”/?file=”+this.a+”&v=”+c+google.loader.AdditionalParams+b
      };
      function k(c,a,b,d,e,f){
         this.a=c;
         this.g=a;
         this.f=b;
         this.d=d;
         this.e=e;
         this.b=f
      }
      k.__google_inherits(i);
      k.prototype.c=function(c,a){
         var b=””;
         if(this.d!=undefined){
            b+=”&”+this.d+”=”+encodeURIComponent(h?h:google.loader.ApiKey)
         }
         if(this.e!=undefined){
            b+=”&”+this.e+”=”+encodeURIComponent(c)
         }
         if(a!=undefined&&this.b!=undefined){
            for(var d in a){
               if(this.b[“:”+d]!=undefined){
                  b+=”&”+this.b[“:”+d]+”=”+encodeURIComponent(a[d])
               }
               else
                  if(d==”other_params”){
                     b+=”&”+a[d]
                  }
               }
            }
            google[this.a]={};
            if(!this.f&&b!=””){
               b[0]=”?”
            }
            return this.g+b
         };
         function o(c,a,b){
            var d=j[“:”+c];
            if(!d){
               var e=new Error(“Module: ‘”+c+”‘ not found!”);
               e.toString=function(){
                  return this.message
               };
            throw e;
         }
         else{
            m(“script”,d.c(a,b))
         }
      }
      function q(c){
         var a=window;
         if(a.addEventListener){
            a.addEventListener(“load”,c,false)
         }
         else if(a.attachEvent){
            a.attachEvent(“onload”,c)
         }
         else{
            a[“onload”]=c
         }
      }
      function p(c){
         var a=window.location.href;
         var b;
         var d=a.length;
         for(var e in c){
            var f=a.indexOf(e);
            if(f!=-1&&f<\/script>’)
         }else if(c==”css”){
            document.write(‘<link href=”‘+a+'” type=”text/css” rel=”stylesheet”></link>’)
         }
      }
      function g(c,a){
         var b=c.split(/\./);
         var d=window;
         for(var e=0;e

真的要分析完全这里面的有趣的东西,还真是要点时间。不如分步骤,一个话题一篇文章,这样看起来容易一些。估计一天晚上也写不完,正好大家和我一起来看这段代码。

技术人员写KB的好处

早上和Wendy在车上谈起对于微软里面技术人员写知识库文章(Knowledge Base)的好处。总结起来有三条:

  • 积累公司的技术财富(Accumulate knowledge legacy of the company)
  • 促进技术人员追求技术卓越(Driving for personal technical excellence)
  • 营造互相帮助的氛围。(Cultivate a culture of helping each other)

两个人都同意。

P.S.每天都有一个小时什么事情不做,仅仅在路上聊天,这在夫妻中间倒是很难得的机会。

关于生活

我不喜欢绅士这个词。要不是横戈用一个别克君越的车模在MSN上面晃来晃去的诱惑我,让我一定围绕这个词写点东西,我真的不想提起绅士这个词。绅士这个词描绘的是大众对于一群人的看法,而鲜有自己在独处的时候用这个词来称呼自己。对于个体,快乐,安逸,智慧等等是不错的形容词,却都和绅士无关。那就不妨偷梁换柱,来谈一谈自己对于生活的看法。

关于尊重

社会对钱和名的追逐,归根到底就是对于社会的尊重的追逐。如果这种尊重不是建立在钱或者名望之上,而是建立在某种特殊的塑料片上面,我相信也会有人每天忙于收集他们,并且互相比较。网络游戏就是这样的一个例子,可是又有谁能看到现实社会其实也是练级和积累各种各样“经验值”的地方呢?

关于时间

所有人对时间的珍惜,就源于每个人必死的事实。对自己的老去和死亡的恐惧,让每个人对时间的珍惜到了无以复加,诚惶诚恐的地步。有一个行为艺术作品就是连续一年什么事情都不做,仅仅每小时打卡一次。这个名为《打卡》的行为艺术让我很受启发,就是每个人可以选择随意的支配时间,甚至用什么也不做的方式来支配,而不是让时间支配。

关于名声

很多人想要出名。美国的一个谚语说,每个人这一生都有15分钟的成名机会。此话不假。当很多人谈及你的时候,自己应该意识到,这仅仅是短暂的15分钟而已,没有什么值得庆幸的。尤其当名声传播超出自己日常的圈子,当那些从来没有和自己促膝聊天的人也开始对这个名字进行评论的时候,更要意识到,公众的那个名字和自己根本不是一码事。就像无数的公众名字一样,那个名字是个近乎于虚构的小说人物了 。尼采的看法我非常同意,我们总被人赞美,或者指责,却很少被理解。赞美和指责的人的观点相对于自己的观点来说,相差并不太远。对于出名,的确是获得的越多,失去的越多。

关于幸福

幸福或许来之不易,却和金钱无关,和名声也无关。

幸福或许和期待相关,当我们对物质的期待提高的时候,我们就不幸福。我们要汽车更快些,但到底多快才算快呢?我们要屋子更大些,但多大才算大呢?我们不断的用一代又一代的努力把奢侈品变成生活必需品,又创造出更多的遥不可及的奢侈品。直到我们形成一种奇怪的现象,就是我们的财富开始用我们不需要的东西的多少来衡量了。

幸福或许与智慧和理性相关。不是每个人都有足够的智慧,来平衡心中的烦躁,去除心中的时刻都会到来的心魔,或者能够理解世界上种种和自己的想法不一致的现实的。这和改变社会无关,只和增加理解的能力有关。

幸福或许还和时间有关。当自己要的,可以安全,舒适的放在自己有的时间里面,人就相对容易幸福。在小城市里,即便步行上班,只要时间在自己的控制之内,也比开着宝马拥阻在大城市的马路上来的开心,因为前者,时间是自己的财富,后者,自己是时间的棋子。

关于内心

关注外界的,物质的世界,关注社会的大多数人的想法,会让人沮丧;我们不如关注内心,关注艺术。

绘画让人掌握美,让人发现自己不曾注意到的细节,让人更清楚地看到世界的一部分;哲学可以慰籍各种不完美的现实,让人可以永远在迷宫里面可以抬头看到相对稳定的星斗,从而获得信心;诗歌纠正不是那么健全的人的思想,治愈城市给于人的心灵的创伤;小说可以让我们换一个角度来看这个社会,更多的理解以前自己不理解的现象;以及散文,不断提醒人们自己已经拥有的,却不曾留意的。只有这些,才比金钱,物质,名声更容易让人幸福。

总之,我认为,生活永远的是美好的,虽然我知道很多人不这么看。

身份认知?

明天请大家到家里来做客,不知不觉的,准备收拾一下,或者去添几盆花。再平常不过的想法,每个人都有的类似于只要在镜头前就要扒拉一下自己的头发的小动作,是不是在提醒自己,自己的身份总要由别人的认可才得以确认呢?为什么三个礼拜没有扫的院子,一定要在来人的时候才要清理一下呢?

客齐集桌面包

庆祝五一劳动节!劳动人民出身的我在家里闲着,就自己动手写了一个客齐集桌面包,只要把这个HTML文件存在自己的桌面上,就可以访问客齐集最新的上海的帖子了。

自己写代码总是可以丰衣足食。特别庆幸自己是技术出身,在互联网的世界里,或许商务很重要,或许资金很重要,但只有深切了解技术的人才能享受编点程序比吃个苹果还开心的那种心情

互联网归根到底,首先是技术的革命才带来了信息革命,才有了商业的革命。

如果谁想把这个东东放在自己的blog上面,只管看这个文件的源代码,拷贝粘贴过去就好。





客齐集桌面包


招聘求职
房屋
服务

同城寻缘
学习与培训
同城活动
二手跳蚤市场



做平台还是做应用

PC史和互联网历史一次一次的向大家证明,做平台比做应用赢的可能性更大。微软是做平台的,Netscape不是;Google现在开始做平台,而很多网站不是。

什么叫平台?我太愚钝,花了很多年(至少是5年)才弄清楚。直到现在我也没有办法用一句话做一个定义。只好不断的举例再举例。

数据存储的平台

任何一款产品,都是由平台和应用程序混在一起出厂的。DOS的平台就是让应用程序做一个简单的INT 21调用,就把文件操作等等复杂的和不同的硬件打交道的事情完成了。当然,DOS还有一个叫做cmd.exe的命令行程序,是这个平台的应用程序。只有平台没有应用的系统,就好似没有命令行的DOS,或者没有Windows Explorer的Windows一样,用户无法直接使用。而各种厂商都会使用INT 21或者Windows下的WinMain为代表的一系列平台提供的API来开发,形成了一个平台上面百花争艳的格局。Windows世界就是这样。Linux世界的平台很好,应用程序,尤其是消费者端的应用程序,也在苦苦追赶。

微软和Netscape

当年微软和Netscape之争,从技术上讲,一个重要的区别就是一个是做平台的,一个是做应用程序的。Netscape Navigator装上去就是囫囵一个,无法再利用,而装了Internet Explorer就等于装了Web Browser的控件,只要在开发工具Visual Basic里面,把这个控件拉过来,再拉一个文本框,作为输入网址的地方,一个简单的自己的浏览器也就做出来了。于是,Web Browser控件是那个遥远的1995-2000年最酷的控件。当大家用这个控件做了很多应用程序以后,IE就更加流行。至于这个还是不是Internet Explorer?这个和IE会不会竞争?平台厂商不这么问问题。

平台等于开放

平台的思维,是API的思维,是开放的思维。开放平台就是把之所以自己可以开发出来现有程序的技术和功能开放给所有其他的人,让他们也可以和自己一起在自己的平台上面开发和自己相竞争的应用程序。

从广义上来说,Windows是平台,Office是应用程序;Google Data API, Google Map API是平台,Google Map是应用。好的平台厂商,一定要有一到两个杀手级的应用程序,然后还要有众多的开发者支持,才能让平台持久发展。

最近Google也开始往平台厂商方向转移。大家只要看一看http://code.google.com/apis上面的东西,就觉得Google开始往平台厂商转移了。眼花缭乱的API,其实就是平台的表现。

比方说Map API,让任何人都可以做一个Google Map出来,其实,也就是抓住了平台,而不在乎应用程序。再比如说Google Data API,说白了,它就是让文件处理和数据读取再进了一步,从DOS中INT21的硬盘读取,到Win32的 ReadFile()的局域网32位读取,跨越到了GData的互联网读取。总之,他们都是平台。

平台是让开发者在其上开发更多应用程序的。平台厂商最喜欢的是开发者。微软的开发工具(从Visual Basic开始)和微软的开发者日,就一直受人欢迎。Google最近的开发工具(包括GWT),和五月底的开发者日,也开始慢慢的受开发者的追捧。这就是平台厂商该做的。

在我的眼中,微软是做平台的,Google也是,Yahoo!显然是家媒体公司,eBay是家商业公司(或说杂货公司)。

Anothr的平台

刚刚和Anothr的Stan聊起来Anothr的发展,我的建议,如果有实力的话(主要是技术和资金),可以考虑做平台。提供个这个世界的,不仅仅是囫囵一体,密不可分的一个应用,更是一个平台。让自己的合作伙伴可以用自己内部实用的一系列产品框架,辅助工具,数据接口可以开发出和自己一样的应用程序,在这个平台上面开发的应用程序多了,也就占住了为了的最稳固的先机。更具体的说,就是把加入feed,显示,提醒等等的部分API化,让别人站在前面,自己退到后面去,就是平台的做法。或者说,如果有人用这个平台(后端的存储,逻辑,和功能)花几分钟就做出来一个anothr2.com来,说明平台就成了。