Opera Unite:怎么看这个玩意也不会成功

2009年6月18日

标题说的是直白了点,不过是心里话。使用Opera Unite以后,真的觉得这个公司的努力怕是又要打水漂了。

首先,Opera Unite还在玩Web 2.0概念,这其实已经有点过时,粘度有限。特别是Opera的用户还属于小众、互动的圈子不够大的情况下,Unite的新鲜劲过去以后,使用者的孤独感会逐渐产生,最后就会使得Unite的互动圈子进一步萎缩、甚至死亡。

其次,Unite本身其实与浏览器关系不大,它更像是Opera的插件平台,能帮用户完成很多与浏览器无关的事情,如果Opera把这个当作它的killer feature,那恐怕就押错宝了。从Unite的扩展性上看,它无法与Firefox的插件体系相比。从功能上看,Flock这样的社会化浏览器就能在功能上轻松仿制Unite。

最后,Opera Unite与手机和其它设备互动的想法很好但很难实现。技术难度是显而易见的,在客户端上面动脑筋实在比Web App难很多。Opera这个公司能有这么大的号召力去推动大家在Unite平台上写应用么?如果没有,他们自己有实力搞定那么多个平台么、写出那么多引人入胜的应用?这个非常值得怀疑。同时,Unite在前期是不会有什么盈利模式的,Opera必须持续砸钱供养整个团队,并且做很多必要的宣传,这种运营成本肯定不低。那么困难同时还得不断花钱,Opera公司是否能够一直坚持也值得观察。

Opera公司10年来占有率一直在1%上下徘徊,他们的营销能力实在令人怀疑。我对他们这次放的这颗卫星不抱太多希望,静观其变,静观其慢慢消亡。

realdodo 浏览器开发 , , , ,

Symantec Endpoint Protection在Windows7 RC下安装的技巧

2009年5月26日

在上一篇文章中提到Windows7 RC的兼容性问题,经过我这些日子的研究终于知道如何解决。

注意,这里提到的Symantect Endpoint Protection版本号是11.0.4000.2295,可能这个方法并不能解决所有的SEP安装问题。

症状:打开SEP安装程序,程序安装的进度条走到几乎最后一步的时候发生回滚,查系统日志发现Windows Installer报1603错误。

问题根源:LiveUpdate的安装程序与SEP的安装程序有冲突,先手动安装LiveUpdate,再安装SEP即可解决。

参考链接:http://www.symantec.com/connect/forums/sep-11010001375-re-installation-failed

具体步骤:

  1. SEP安装程序本质上是一个可执行的CAB包,用WinRAR解开这个包
  2. 从解开的包中执行LUSETUP.EXE,安装LiveUpdate
  3. 从解开的包中执行Setup.exe,安装SEP

从这个问题可以看出,很可能SEP安装出问题并不是由于Windows7 RC兼容性有问题,而是Symantec产品之间有奇怪的冲突。

realdodo 写意生活 , , , ,

Windows7 RC使用手记

2009年5月26日

自从上周到现在已经用Windows7 RC (build 7100)有5天了,现在来聊聊使用感受。

在我废话之前,先提供一个官方下载地址,如果想尝鲜的朋友可以自己刻盘装着试一下。请注意,RC版是可以免费申请CD-key,所以劝那些满世界找key的朋友,赶紧用你的Live ID到这里申请吧。这个RC版可以免费用到2010年6月,不过从3月开始它就会每隔两个小时关机一次。幸好现在还只是5月底,还有足够的时间供我等待正式版出来。

使用了Windows7 RC最大的感受是界面确实比以前的各个Windows版本都好看、好用。特别引人注目的是革新的任务栏,它打破任务栏一贯的风格,每个窗口在任务栏上更像是一个个按钮,可以随意拖动、复制(在上面按鼠标中键)、关闭(在缩略图上按中键),还可以把它锁定到任务栏上。这个新的任务栏替代了以前快速启动栏和托盘的功能,使这两个东西在新的Windows7中都可以消失了。

Windows7 RC任务栏

Windows7的开始菜单也很值得一提。最醒目的是从Vista继承而来的“搜索”功能(这也是我在Vista中最喜欢的功能),它位于开始菜单的左下角,使用户可以一按Windows键就可以马上搜索自己想要的程序,再也不用到程序菜单里面苦苦寻找。

Windows7 RC开始菜单

开始菜单中还有大大改进的“最近使用程序列表”,在里面不但可以看到最近使用的程序,还可以使用这些程序的常用选项。

Windows7 RC最近使用程序列表

任务栏和开始菜单的改进是依据Windows7的一个设计原则:reduce concepts to increase confidence。这一点我非常的认同和喜欢。

关于Windows7 RC的运行效率,我觉得至今为止非常好。我现在装的软件还很少,可能还没有到真正体现Windows7优势或者劣势的地方,我会拭目以待。我对Windows7的运行效率还是很有信心的,这源自ATC一个专门负责Windows7性能调优的同事与我的对话,他的乐观让我觉得Windows7在这正发布的时候应该会在这方面更加优秀。

说了挺多好的,再说一些不好的。

Windows7 RC主要缺点是兼容性问题,有可能是RC版的Windows Installer的问题。

我现在无法安装公司提供的杀毒软件,所以上我们的内网还有一些问题。我发现安装过程中Windows Installer会报1603错误,在网上也有不少人说遇到这个问题无法安装程序,看来还不是小问题。我根据微软帮助中心的文章进行修复,不过貌似完全没有作用。听说Windows7 beta就没有这个问题,很怀疑下一次Windows Update就会修复这个问题。

这个问题我还在研究中,如果有结果,会继续报道。UPDATE:现在问题已经解决,很可能SEP安装出问题并不是由于Windows7 RC兼容性有问题,而是Symantec产品之间有奇怪的冲突。详细请看这里

realdodo 写意生活 , ,

一段丑陋代码的诞生记

2009年5月7日

话说某年某月某日我在用PHP为我的服务器程序写测试代码,为了方便判断服务器的输出返回,我写下了下面的代码。
function assert_rpc_call($cmd, $input, $logid, $expected_err_code = 0) {
    $ret = rpc_call($cmd, $input, $logid);
    return $ret['result'] === $expected_err_code;
}

在这里,rpc_call()是我测试用的一个函数,可以用来访问我的服务器,它的返回值是一个数组,其中一定有’result’域存放一个整型的返回值。

这个函数实在是太好用了,以至于我的测试函数每个地方都用这个函数而不用rpc_call()。我非常满意,觉得已经万事OK了。

世界上唯一不变的是变化。

后来,我发现学xUnit那样每个测试用例打个点表示成功实在是无趣,而且如果真出了什么错就完全没法调试,于是我增强了这个函数。
function assert_rpc_call($cmd, $input, $logid, $expected_err_code = 0) {
    $ret = rpc_call($cmd, $input, $logid);

这样一来,默认情况下我的assert_rpc_call每次都会把返回的信息打印出来,成功输出绿色的PASS,失败返回红色的FAIL,煞是好看。我非常满意。

    $output = “”;

    if ($ret['result'] === $expected_err_code) {
        $output .= “\033[1;32mPASS\033[m\n";
    } else {
        $output .= "\033[1;31mFAIL\033[m\n";
    }

    $output .= print_r($ret, true);
    echo $output;
    return $ret;
}

工具如果太好用了,它一般会被滥用。

可是需求还在变化。不久,我发现有时候我为了初始化一个用于自动测试的环境需要调用很多肯定不会失败的接口,每次把它们的返回打印出来实在是扰乱视听,我需要有一个开关切换回原来的assert_rpc_call()行为。于是我加了一个参数和一些丑陋的代码实现这个功能。再接着,我又想在某些情况下获得返回的数组,在另外一些情况下返回bool值,而且还要在某些情况下打印输入的参数……我知道把这些矛盾的功能全部加到一个函数里面是非常丑陋的,也许应该拆成几个函数更为合适,但因为这个函数已经在很多地方调用,我实在懒得把每个地方都改好。

最终,代码变成了这样。
function assert_rpc_call($cmd, $input, $logid, $expected_err_code = 0, $return = false, $just_need_bool_value = false) {
    $ret = rpc_call($cmd, $input, $logid, !$return);
    $check = array();
    $output = "";

最终这个函数非常的丑陋,它变成现在的模样实际上经历了三步:

    if ($ret['result'] === $expected_err_code) {
        $output .= "\033[1;32mPASS\033[m\n";
        $check['passed'] = true;
    } else {
        $output .= “\033[1;31mFAIL\033[m\n";
        $check['passed'] = false;
    }

    $output .= print_r($ret, true);
    $check['output'] = $output;

    if (!$return) {
        echo $output;
    }

    if ($just_need_bool_value) {
        return $check["passed"];
    } else {
        if (!$check["passed"]) {
            return false;
        }
    }

    return $check;
}

  1. 函数太方便了,很多地方都开始引用
  2. 需求变化,恰好这个代码通过简单的修改就能基本满足要求
  3. 需求继续变化,代码已经发出bad smell,但因为牵扯过多,无法重构

具有讽刺意味的是,万恶之源竟然是函数一开始写的太方便了,这本来应是件好事。真正造成问题的则是第二步,需求缓慢的变化、不断积累,就像温水煮青蛙一样,最终使我失去重构的动力,一错再错,终究写出丑陋的代码。

幸好,任何时候都不算晚,就算今天开始也行。不过,我考虑一会之后还是觉得直接把它commit到cvs里面去——我要遵循KISS原则,何必对这种测试用例代码那么计较呢。

有了这种阿Q式的KISS精神之后,这世界上就很少有不能忍的丑陋了。

realdodo C++ , , , , ,

百度新员工培训

2009年4月4日

为期三天的百度新员工培训昨天结束了。相比微软的新员工培训,百度的培训更加有趣味一些。听说我参加的这次是改版后的第一次,而我又不止从一个人那里听说,原来的新员工培训多么无聊,所以可谓是期望不高但过程还挺好。

百度的新员工培训有点像一次素质拓展活动,其中那个奇迹车间的活动确实能让大家在体验中感觉到超越极限的快乐。嗯,这就来说说奇迹车间是怎么回事。

奇迹车间是一个类似游戏的竞赛活动。游戏目标是用一些长短不一的硬纸条互相十字交叉拼成一个很复杂的图案,谁能以最短时间完成就是胜利者。硬纸条的长边上开有多个很窄的口,两个纸条拼接的时候必须将开口相对才行。

这个游戏需要多人合作完成,每个小组有5到6人。最开始,我们组花了10多分钟才完成,感觉已经是比较快了,可培训老师告诉我们,根据以前新员工培训的纪录,最快的组只用了13秒!这是多大的差距。

我们组想了很多办法,也否定了不少办法,最后终于找到一个比较无敌的方法,在面对各种挑战,包括重新分组的冲击,最终终于达到了21秒。尽管21秒已经算比较快的成绩,可我们都觉得还有上升空间。大家同心同力、集思广益,果然是潜力无限。

培训虽然只有短短3天,可我们每个小组还要准备一台晚会,作为最后结束。我们一开始都很挠头,不过大家一起努力,不但搞定,还搞得十分精彩。我在其中也尝试突破自我,反串饰演,最后最佳男主角和最佳女主角提名我都名列第一,在班上火了。

最后show一张照片,是大家的合影。看,大家都很开心呢。

百度新员工培训合影

realdodo Hi,百度 , , ,

设计哲学:职责单一还是接口单一

2009年3月26日

今天跟康神讨论设计,他提到一个设计哲学(这个词就很让人崇拜),很是有道理。大概意思是说,在设计中,有人喜欢职责单一,所有东西分的很细,有人喜欢接口单一,保证接口稳定,这是个设计哲学问题,各有优缺。

我自己是一个极度喜欢保持职责单一的人,面对康神设计的接口单一但内部逻辑较复杂的模块,多少有点想重构的冲动。其实这两种设计哲学都没太大问题,确实得看需求来确定到底用什么。

接口单一的设计,最典型例子的就是大家都知道的printf,这个东西博大精深,可以组合打印任意格式的文字,如果C标准委员会乐意,还可以通过扩展格式字符串来实现更多的打印选项,同时保证100%向下兼容。还有很多接口,它们通过传递一个结构来传递参数,这个结构拥有众多成员,每次调用接口时只用其中一部分。这些接口也能像printf一样易扩展,康神设计的就是后面这种接口。

这样设计的好处是保持整个系统接口的统一和稳定,这对于一个大型工业系统来说至关重要,因为牵一发动全身,改变任何一个通用接口都会付出很大代价。但它的缺点也十分明显,主要体现是效率不高和模块职责不明。

可以想象,printf的运行效率并不高,对于%以及后面参数的解析是在运行时完成的,每次运行都会在解析格式字符串上花时间。传结构的缺点是内存使用效率不高,并且随着业务逻辑不断变复杂,结构会大到不能接受的地步,最终肯定在结构中设置一个类似于格式字符串或者表达式的东西,逐渐转变成printf的设计模式。

同时,由于接口过于强大,在接口背后隐藏的逻辑也必定复杂无比。想想解析格式字符串或解析结构时该需要多少烦人的if…else,就知道要实现这种设计将会写出多少逻辑复杂的代码,会产生多少的bad smell,给后来维护的人造成不少困扰,甚至会引入不少潜在的错误。

反观职责单一的设计,没有接口单一设计的缺点,但劣势也很明显,就是没有统一的接口,使得整个系统模块之间的调用方式始终难以稳定。如果整个系统由一个人开发还好,如果多人协作,则会大大降低开发效率,会将大量时间用在沟通接口和解决联调问题上面。公平的说,职责单一的设计也可以用facade模式来提供统一接口,但是facade模式的实现代码又会变得和接口统一时一样,没有根本改变,只是一个折中和权衡。

那是否说明“完美”的职责单一的设计不适合大型开发呢?也不一定,因为我们有C++和无比变态的模板技巧。

比如我们可以设计出一个这样的print,功能类似于printf。注意,这个函数设计成只在print的时候才输出,expression类不会造成任何输出。
pattern p = builder() << "uid: " << uid << " uname: " << name;
uid = 1000;
name = "realdodo";
print(p); // 打印出"uid: 1000 uname: realdodo"

如果熟悉boost.spirit的朋友肯定觉得这个代码很眼熟,没办法,谁要我是这个库的忠实粉丝呢。在这里,pattern_builder类只是一个模板生成器,而不进行任何计算(不同于sstream这样的类),它用<<运算符针对各种类型生成各种特化的模板类,类似于一个嵌套的pair<>。这些模板类层层嵌套,但是pattern类可以轻松搞定,方法就是设计一个concrete_pattern类。
struct concrete_pattern_base
{
    concrete_pattern_base() {}
    virtual ~concrete_pattern_base() {}
    virtual string to_string() const = 0;
};

tempate &lt;typename builder&gt;
struct concrete_pattern : public concrete_pattern_base
{
    builder builder_;
    concrete_pattern(const builder &amp; b)
        : builder_(b)
    {}

    virtual string to_string() const
    {
        // 用模板特化的方法实现to_string()方法,这里略去
    }
};

这样,pattern的实现就非常简单。
class pattern
{
    concrete_pattern_base * pattern_;

public:
    template &lt;typename builder&gt;
pattern(const builder &amp; b)
    {
        pattern_ = new concrete_pattern(b);
    }

public:
    // 其他方法……如果需要获得当前字符串,只需调用pattern_-&gt;to_string()
};

注意,按照print的语义,pattern虽然也要实现一个类似于to_string()的方法,但它完全没有必要从concrete_pattern_base派生。

这种设计的好处是在保证职责单一的时候同时维护了接口统一。实际上,那个复杂的接口逻辑还是存在,但是由编译器在编译期间完成了。程序员只用关注builder、pattern和print的实现,它们三个一个负责生成表达式,一个负责计算表达式,一个负责输出,职责明确,泾渭分明,超级高效,实现各种新的需求也毫无问题。

可惜,这世界上没有银弹,这种滥用模板技巧的方法也有很大的问题。最大问题是可维护性。模板编程的复杂度远超过普通面向对象编程的复杂度,如果开发/维护者没有很深的基础,很可能都无法看懂这些代码。次要问题是扩展成RPC调用非常困难。对于大型工业应用,很可能一个接口因为某种原因要变成跨进程甚至于跨机器的调用,这就需要序列化所有的参数。模板是静态技巧,要序列化就一定会生成不亚于printf格式字符串的东西,而且还要实现一个客户端解析这个烦人的东西,那真是吃力不讨好,还不如直接实现一个printf好呢。

所以,最后的结论是没有结论,设计要随着需求而定,这才是王道。没有万能的设计,只有最符合需求的设计,并且设计要随着需求改变而改变,不能止境

realdodo C++ , , , , , , , ,

春季building:真人CS感受

2009年3月18日

前几天我们部门(包括家属)四十多个人冲到怀柔,目的主要就一个,痛痛快快的在那里打一场真人CS。对我来说,真人CS这个名词听说过很久,也听人讲过是怎么回事,不过就是没自己亲身体验过,这次得到机会当然不能放过。

我们晚上9点抵达怀柔,有一个晚上加一个上午的时间养精蓄锐。第二天下午,我们精神饱满的集合准备玩CS。

当我穿好装备时,发现这激光枪真是够山寨的,特别是武器上面的喇叭。一旦开始游戏,这里面就模仿CS的声音,发出“Go go go”的叫声。发射子弹时,这个喇叭不但有子弹射出的声音,甚至还有弹壳落地的声音,当然啦,这一切都和CS里面一样。如果被打中,它还会发出“啊~”的一声,还真像那么回事。

教官将我们分成两队、指定好队长、再简单的给我们培训之后,大家就上战场了。真人CS的内容组织还算不错,一个下午的时间并不是给我们来一场大混战,而是分为好几个“战役”。我们所在的地形是一个有点陡峭的山坡,到处还煞有介事的放了沙包、挖了坑,还真有点实战的意思。在游戏中,每个人有三条命,死完了就要回“死人堆”等着下一轮复活。

第一场战役是自由练习,双方只要有一边死伤过半就结束。这一局没什么好说的,反正就是随便玩,很快就结束了。

第二场战役是“斩首行动”,就是杀死对方的队长。我们这边的地形易攻难守,所以一开始就决定分三路进攻。其中中路人相对较多,但是队长会跟着上面那一路人一起绕到对方后面进行偷袭,期望能一举成功。

我参加了中路的战斗,不过貌似并不顺利。本来想的是我们冲过去的,不过对方倒先冲了过来,很快大家就互相交火起来。由于大家恰好隔着“死人堆”交火,所以很难分清到底谁死谁活,整个打得都很混乱。而且,我发现打着打着枪就没声了,原以为我死了呢,后来在死人堆里待很久才发现原来是身后的电池接线掉了,我实际上还一次没被打中(汗啊……)。

重新复活之后,我当然要去找我们这边的活人。我一路网上爬,发现我们这边只剩下三名同伴,而对方,至少还有四个人在一起,躲在一个树丛后面。由于对方不知道我刚刚复活归来,所以大家让我从下面偷袭。这次偷袭不算太成功,我打到一个人,同时自己也中一枪,由于他们人多,我只好退回来。等我回来之后,我们这边发现队长不见了。正在我们郁闷之际,听到对方枪声大作然后欢呼——原来队长一个人偷偷冲到对方队长的身后,差一点就偷袭成功,可惜对方毕竟人多,抢着挡子弹,不一会这胜负就定了。

第二场战役是“解救人质”,我们这边负责守人质,对方负责抢。人质自己不能动,必须由至少一个、至多两个某一方的人在旁边才能动,最后一方被全灭或人质被救回指定地点算作结束。

我们吸取上回的教训,这次更加小心。大家在山坡的最高处散开,摆下阵势等着对方来攻。对方很快就想冲上来,在我们集中火力之下,让他们伤亡惨重。可是我们还是犯了一个错误,忘记在最最高的地方多安排点人手。对方有大概六、七个人绕到最最高的地方,横着冲过来,虽然我们补充好几个人上去,但是还是没守住,被他们占据高点,使我们腹背受敌,最后据点失手。这次,又是我们输。

经过这两场,我们都已经非常疲惫。教官组织我们坐着休息,然后玩一个真心话游戏。XXXXXXXXXXXXXX(省略2031字的真心话~)好了,现在缓过了气,可以继续战斗了。

最后一场战役是“找出卧底”。教官偷偷的在两边各选出4个人做卧底,每一边的人知道对方的卧底(也就是自己人)是谁,而同一方的卧底互相不知道。卧底的任务是杀尽可能多的人,而游戏结束的标志是某一方的卧底全部阵亡。

很奇怪,我一开始就有预感要被选成卧底,然后果然如此……很郁闷的是,我还没想好怎么完成任务呢,就不知道被谁放黑枪,一下就死掉了……

后来,仔细想想发现,所谓的卧底任务只是一个让卧底暴露的幌子。因为游戏的胜负在于杀卧底,所以如果卧底始终不伤害本方的人,当然也就很难暴露。由于有这个任务在身,而且在刚了解规则之时没来及想那么多,作为卧底,当然想找个没人的地方放黑枪,躲着自己的队友,这种举动也就暴露了身份。我最后也没搞清楚谁打中了我,反正现在想来,确实暴露的很明显啦。

最后的最后,show一张照片,是我的老大的牛相机照的,我为了显示方便,裁剪了一下。
真人CS集体照

realdodo Hi,百度 , , ,

春季building,几张图几句话

2009年3月15日

3月14号参加百度的春季building,活动的主要内容是真人CS,不过很可惜,并没有机会在玩真人CS的时候照相,所以只好贴几张自己随便逛逛拍的照片。大家凑合看吧~

这些图都是在怀柔雁栖河沿岸拍的,本来大家都想外出踏青的,没想到寒流突然袭击北京,温度又回到0度以下,根本没有春意可言。唉,多少有点可惜。

冰冻的河流 雁栖河一景 鲤鱼跳龙门 东北风格的石磨 小桥流水人家 遥望慕田峪长城

更多的请看这里吧:我的Live相册

realdodo Hi,百度 , , ,

颠倒黑白

2009年3月12日

颠倒黑白是一个电影的名字,今天偶然看到的。

这个片子讲的是一个作家和一个黑帮老大的故事。本来这两个人互不搭界,只因为黑帮老大突发奇想要出自传,就雇了这个作家来捉刀,他们的命运开始交错。

作家本来生活潦倒,懦弱的很,到处受人欺负,写书也没人看。这次受到邀请写黑帮老大的自传,则是又害怕又期待。怕是怕那些黑帮打打杀杀、真刀真枪,实在不是普通人能适应;期待则是因为丰厚的回报,还可以坐老大的房间、出门都有两个小弟开着大奔伺候着,实在威风。

渐渐的,这个作家发现自己有特别的潜力。自己在几次偶然的机会中,仗着有两个小弟壮胆,竟然接二连三的把原来欺负他的人和想要跟他挑衅的人打翻在地。不知不觉中,他找到了当老大的感觉。

而那个黑帮老大,从很早以前就喜欢写日记,通过作家,他对一个文学老师一见钟情,最后竟喜欢上小说,自己开始创作。

这个片子的结局非常戏剧化:黑帮老大因为仇家寻仇,他喜欢的文学教师被抓去当人质,他的手下因为看到老大整天“屈尊”去追求一个女教师而转投仇家,他只好一个人深入虎穴,想用自己的命换女教师的命。正当他被暴打的时候,作家带领着一群死忠的老大旧部冲了进来,他十分勇猛,连那些原本叛变的手下都被感化,一下扭转了局势。最后的结局是:黑帮老大与女教师结婚,他也隐退成了一个小说家,出版了好几本小说;而那个作家,因为那次事情坐了牢,出狱以后就成了真正的黑帮老大,他的理想是建立一个二十一世纪的新黑帮。

这个片子情节诙谐好笑,觉得挺不错。现实中作家和黑帮老大这两种角色可谓相互对立,不可能融合。但谁能想到,在这个电影中,一个成功的黑帮老大和一个失败的作家,互换角色之后竟会更加适合。

作家在踏入黑社会之前,从来对人就是忍气吞声,感觉自己就是个“买不起奶粉钱,过几年连孩子的学费都交不起”的失败男人,他自己都不相信自己会是一个那么“狠”的角色。最后时刻,他却能带领大批手下冲到仇家的老巢,还用自己的勇气感化那些叛变的旧部,这说明他内心中的潜力终于爆发,他找到了自我。

现实生活中的我们,也时常面对生活和工作的挫折,否定过自己、怀疑过自己、甚至厌恶自己,不过有多少人会挑战自己,换一个完全不同的角色去尝试呢?恐怕很少。相信有这样想法的不少人也在迷茫自己到底能做什么,他们看到的也许只有自己的失败、以及从失败中滋生的自暴自弃的想法,哪还能看到自己优点和长处。更关键的是,他们就算得到了机会,遇到一点挫折之后恐怕也就会变回原型。作家虽然最开始懦弱,可他有了小弟撑腰之后就敢到处报仇,碰到一些混混的单挑挑衅也没有退缩,每次误打误撞获得胜利,最终才得以转型。抓住机会只是第一步,能突破所有困难和试炼,那才能达到成功。

黑帮老大的转型则还多少有点循序渐进。他一直喜欢写日记,出自传的想法也不是一时头脑发热,连作家都觉得他文笔不错。之后,他因为喝醉,在作家家里待了一天,发现原来出书也不是那么高不可攀,建立了信心。再后来,为了追文学教师去听她的课,也最终促使他转型。黑帮老大的转变是一种主动尝试的结果,他成功转型的代价是放弃自己的地位和金钱,但他得到了爱情和生活的乐趣。

黑帮老大所对应的是现实生活中工作小有成就但其实背负压力、生活缺乏快乐的人。他们觉得现在的生活不算非常好,但又不舍得既得利益,就算自己有改变的可能,也不愿意改变,在幸福生活和即得利益之间选择了利益。仔细想想,这样的人其实挺可悲的,毕竟生命只有一次,享受每一天才是我们真正需要做的事情,如果现在的生活不能带给我们满足和快乐,那么以后老了之后恐怕只有后悔的份。

有一个调查显示,美国70岁以上的老年人被问到如果能再年轻一次,他们会改变什么时,最多的答案是take more risks。无论是作家式的改变还是黑帮老大式的改变,都需要take很多risk。多数老人的观点也证明,我们其实有潜力改变自己,也有能力解决困难,关键就看自己是否愿意去直面挑战,以及放弃那些看上去很好的身外之物。

realdodo 写意生活 , ,

IE的未来在何方

2009年3月7日

IE8即将发布已经不是新闻,很多评论家以及那些讨厌IE的开发者们都对这个亲近标准的IE抱有一丝好感,这也不是新闻。

IE8中最显著的改变莫过于对CSS 2.1的全面支持。正因为现在亲近标准而以前疏离标准,IE8引入了兼容模式这种复杂的新功能,来兼容以前那些不标准的网页。在外界看来,IE8这么痛苦的在标准支持和兼容性方面抉择,简直就是搬起石头砸自己的脚——早知现在,何必当初呢。

我曾经问过负责CSS 2.1标准支持的IE PM,为什么现在才开始做标准支持而以前不做,为什么不做DOM而选择CSS。他对此也感觉有心无力,毕竟无论是支持什么新标准,对IE来说都是一次大手术。IE是在标准产生之前确定的架构,现在能做到如此强大的功能还能支持那么多标准已经很不容易。就比如说对CSS 2.1的支持,IE重写了很多核心代码,花了大量的时间去保证正确性、性能和兼容性,已经有点精力不够。相比而言,还是开发WebSlice和 Accelerator更加省心省力。

现在的IE已经很有点像当年的NetScape。有谁能想到,当IE 5全面打败NetScape时,IE是世界上最标准的浏览器,它全面支持HTML 4和CSS 1,而且它还十分的小巧,比NetScape小一个数量级。IE的胜利绝对不仅仅因为它与Windows绑定,而是因为它实在比NetScape好太多了。NetScape当年拖着沉重的历史包袱,每一个升级都不敢做太大的变动,生怕那些使用了自己独有特性的网站出问题,至于标准,当然是抛在脑后。这何其像现在的IE。

时过境迁,多年之后,Firefox从当年NetScape的残骸之中诞生,Firefox成了当年的IE,IE成了当年的NetScape。当 Firefox一身轻松快速开发新版本的时候,IE还要考虑兼容IE6这样古董的浏览器。当Firefox毫无忌惮的通过自动更新强制用户更新浏览器版本的时候,IE还要修IE6的bug、还要发布IT工具方便众多公司阻止IE升级版本。唉,开发IE真累啊。

有很多人希望有朝一日Firefox能打败IE,解放现在身处“水深火热”之中的Web前端开发者。可是我觉得,这绝对不是未来的趋势,Firefox或者说Mozilla基金会绝不愿意这么做。浏览器世界的盟主不是那么好当的,站在风口浪尖,不但赚不到钱,还要花力气赔名声,得不偿失。

就拿修浏览器漏洞这件事情来说,Vista下的IE7已经做得非常安全,比Firefox好上无数倍,基本上对缓冲区溢出和DEP免疫了,可是大家还是会觉得Firefox更安全,根本原因是舆论导向。IE造好了一座坚固的城池,如果依然能将它攻破,对于攻击者来说,自然很有成就感。同时,新闻也总关注 IE的安全,毕竟它一出问题,全世界大部分电脑都处于危险之中,这绝对是大新闻。一来二去,IE不安全的口碑也就建立。至于Firefox究竟有多安全,那还真不见得。用XPCOM做的Firefox插件真的比ActiveX安全?还真不见得。从技术上来讲,做Firefox版的流氓插件不存在任何技术问题。

从我和IE PM聊天中得到的信息,IE现在最关注的领域是企业级应用和RIA。这两方面,恰好是Firefox最弱的地方。而在这个领域,IE真正的对手是 Google Chrome,所以下一个版本的IE会针对Google Chrome的特性采取很多动作。也许还要再经历3个版本,IE才能够脱胎换骨,不过那时,其他竞争者早不知道发展到什么程度了。对IE来说,是时候考虑学习一下Firefox,来个凤凰涅磐了。我猜,五年之后必有大变,我会拭目以待。

realdodo 浏览器开发 , , ,