python quine

s="s={quote}{content}{quote};print s.format(quote=chr(34), content=s)";print s.format(quote=chr(34), content=s)

一段小脚本,将 MongoDB 中所有 DB 的 Collection 按大小排序。

最近接到的一个遗留项目,数据库用的是 MongoDB,年久(?)失修,磁盘满了运维报怨。

实例里面有多个库,每个库中又有很多 collection
于是想要看看哪个 collection 占用的空间比较大,想 remove 掉一些过期数据。

发现 pymongo 取出 collection 之后,无法像 mongo 客户端一样可以直接用 collection.stats() 的方式获取状态。
于是很郁闷。

登上 mongo 查看了一下:

?View Code JAVASCRIPT
// db.col.stats
function ( scale ){
return this._db.runCommand( { collstats : this._shortName , scale : scale } )
}
 
// db.stats
function (scale){
return this.runCommand( { dbstats : 1 , scale : scale } );
}

这才发现,原来 db.state 和 collection.state 都是通过 mongodb 的内部命令实现的。

所以就有了如下代码:

?View Code PYTHON
from pymongo import Connection
db = Connection(HOST, PORT)</code>
 
print sorted(
    [(
        "%s -&gt; %s" % (dbn, coln),
        db[dbn].command('collstats', coln)['storageSize']
    )
    for dbn in db.database_names()
    for coln in db[dbn].collection_names()
    ],
    key=lambda x:x[1])

PS:这篇日志是 惰性的 Blade 大大两年之后头一次在这个布珞阁更新,大家鼓励他一下吧。

关于IP和域名的几个命令行技巧

1. 如何获得自己的公网IP,还用ip138?你真的out了。

% curl ifconfig.me

219.239.108.78

2. 如何给某个IP快速绑定一个域名

比如要给192.168.0.1绑定一个域名,这样vhost就可以用了

% dig 192.168.0.1.xip.io

; <<>> DiG 9.6-ESV-R4-P3 <<>> 192.168.0.1.xip.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43766
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;192.168.0.1.xip.io. IN A

;; ANSWER SECTION:
192.168.0.1.xip.io. 599 IN CNAME a0ips.xip.io.
a0ips.xip.io. 599 IN A 192.168.0.1

;; Query time: 808 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Mar 24 12:12:49 2013
;; MSG SIZE rcvd: 72

 

3. 如何反向解析域名

% host 8.8.8.8
8.8.8.8.in-addr.arpa domain name pointer google-public-dns-a.google.com.

 

开源云计算技术初探

云计算的大潮向我们奔涌而来。而国内的云计算却是乌云一片,搞云计算的多数是骗子,政客,核心学者,偶尔几个技术人有点儿实际研究也敝帚自珍,奉之如圭臬,搞点神秘主义,喜欢被别人崇拜,但又不喜欢与人分享。我是实在看不惯的,而且那些藏着掖着的技术多半不怎么样。这让我想起一个故事,我的很多同学还在航天系统服务,有次聚会他感慨:“我终于知道我们国家为啥要保密了,因为怕被美国人知道我们有多落后。”作为强烈的对比我们看看美帝的云计算,尤其是开源的云计算都已经有了哪些成熟的成果,有什么东西我们是可以轻而易举地借鉴的。

首先我们来看看云计算的三个层次:IaaS,PaaS,SaaS。其中SaaS比较特殊,因为你总不能做出的应用也和别人一模一样吧,除非你是企鹅公司,否则多多少少还是会不太一样的,所以构建完全一样的SaaS是没有意义的,但是可以通过很多有意义的组件快速地搭建你的SaaS,也就是应用。至于各种各样的组件,我想这已经是老生常谈了,毫无新意,也就不说了。那么这里我们就详细说说PaaS和IaaS吧。

IaaS

先说IaaS吧,这个可能对初学者比较好理解,就是可以按照需求弹性地提供计算和存储资源(狭义地讲:内存资源),比如EC2。很长时间除了Amazon提供的服务,我们别无选择。自然很多厂商是不甘心的,其中就有Rackspace,于是乎经过苦心寻找终于锁定了openstack。这个项目最早由NASA发起的,现在已经有很多公司入伙了,包括Citrix Systems, Dell, AMD, Intel, Canonical, SUSE Linux, HP, and Cisco等。发展势头正旺。想看更多的openstack内容请移步这里

openstack的官方网站在这里

当然openstack也有一个严重的问题,就是目前还不是很成熟,主要表现在部署很麻烦。这样就有了devstack,一个专门用于部署的脚本。让部署的工作轻松不少。openstack也有竞争对手的,比较有名的就是Eucalyptus官方网站在这里。不过相比于openstack的火爆,Eucalyptus真是门可罗雀。另外还有两种NimbusOpenNebula也有自己的特色,大家可以在选型时酌情参考。

当所有人都把目光聚集在Linux时,一个被人遗忘的骑士发出了他的吼声。这个贵族就是solaris,没错你没看错就是那个被oracle收购去的的solaris。个人觉得sun在被收购前做得最有意义的事儿就是做了open solaris,最大的遗憾就是没有开放sun studio,也就是sun的编译工具。当大家都热捧linux的时候不要忘了solaris的很多特性正是云计算尤其是多租环境特别需要的。在oracle无耻地绞杀了open solaris后,很多衍生版本应运而生,其中最著名的要算Illumos了,而Node.js背后的公司Joyent更是在其基础上发扬光大,加入了KVM支持,推出了SmartOS。SmartOS集各种武器于一身,在硬件虚拟化,操作系统虚拟化,安全存储和全面调试等方面都有很强的优势。

PaaS

下面讲讲PaaS。额外说一句为啥node会火呢,我发现所有开源的PaaS都支持Node。

Cloud Foundry

从前大家都认为VPS提供服务就可以了,至于怎么做的大可以不必告诉用户。这种思路貌似也延伸到了做PaaS上,当然不得不承认很多用户并不想知道PaaS究竟是什么,也不想知道机理,只不过想用而已。这也说明了目前处在第一阶段,先要满足用户的功能需求。但是对以PaaS为生的企业来说,往往情形就不那么简单了,是将PaaS作为服务还是将其作为平台,在商业模式上可是很不一样的啊。很多人都对服务和平台之间的区别不是很清楚。国内目前的环境也更是如此,比如国内很多微博产品,还是停留在做服务的简单路线上,缺少纵向合作,不能形成有力的产业上下游,虽然口口声声说是开放平台,但开不开放不是自己标榜的,而是开发者说的。这里要说的是,做PaaS,更要做成平台才有未来,要能集成各种第三方服务,想尽一切办法让开发者降低成本,还能让第三方服务提供商获得利益。这里我就不特别细说平台模式的细节了,感兴趣的同学可以买一本《商业模式新生代》自己研究一下。

显然,一大批云计算业界的翘楚认识到这一点了。你看Salesforce旗下的heroku.com对如何做平台的思路非常清晰,路线明确。真是不看不知道,一看吓一跳。恍然间大悟,原来PaaS还可以这么玩。恍然大悟的不止我一个,VMware也在冥思苦想,作为业界虚拟化技术的霸主,怎能对PaaS不闻不问呢。平台构建好以后,后进者的门槛是非常高的,例如没有后进者可以撼动纽约证券交易所的地位,那么怎么开始呢?VMware想到了开源,以争取更多的开发者支持。当然借助VMware强大的资金支持,这个开源的PaaS一定会成为PaaS的一支重要的力量,尤其是构建私有云的环境中。

Cloud Foundry推出的时机非常好,对比较潮流的几个技术有内置的支持,比如Redis,MongoDB,RabbitMQ,MySQL,PostgeSQL。这些东东无异是现代互联网应用的必要组件,很难想象什么应用能够完全避开上述所有产品。同时CF对Java,Ruby,Node.js都有原生支持,对Python和PHP也有合作支持,这些都是它的优势。但从目前来看CF的缺点也是非常明显的。显然VMware对于如何做好社区产品是缺乏经验的,集市不是大教堂,很多做法是不一样的。开源和开放也不完全是同义词,缺少对应用开发者的真正理解是CF的头等硬伤。相比于Heroku的整体体验,CF太繁琐太重型了,那种复杂的企业级的思路用在做PaaS上,开发者买不买账还得时间来检验。不过什么东西都自己搞一套,最后吃亏的总是自己。想当年微软自己搞得版本控制系统,最后还不得放弃掉,集成了第三方的版本控制系统。CF目前有这种趋势,明显对于社区的一些PaaS理念置若罔闻,很多地方非常难用。

难用归难用,CF在设计上还是值得学习的,从VMware选用Ruby作为Cloud Foundry的主要开发语言,我觉得应该作为一个信号。Ruby的确是云时代的语言,这点下面会继续说。有个开源的PaaS可以学习,总归是件非常不错的事儿。Cloud Foundry也是业界的一个起点,其标志性的意义也非常重大。在此之后,很多PaaS项目都开放了源码。

Haibu

很多人看到这个名字都会感到非常陌生。不过它的东家nodejitsu在Node.js圈子里可是举足轻重的一家。Joyent虽然掌控着Node.js,但似乎并没有开源其Node PaaS的想法(或许真的没有PaaS也说不定),而nodejitsu则提供了很好的Node PaaS,不但能在Joyent的云上部署,也可以在EC2,Rackspace之类的地方部署。总的来说,Haibu的设计更加社区化,模块之间独立性更高。有很多组件被广泛用于其他项目。同时也使用了很多其他的开源组件,这点和Cloud Foundry完全不同,后者甚至连消息传递都是自己实现的一套。Haibu的代码不是很多,不用说基本上都是Node代码,所以有心的话,看一遍应该不是很困难。

当然haibu的缺点也是比较明显的。仅就只支持一种语言来说就不那么让人欢心鼓舞了。不过谁知道今后Node.js会不会成为诸如awk这样的经典之作呢?所以只做好一件事情也算符合KISS原则。至于对于其他相应的第三方组件,貌似不用担心,全交给Node.js本身去考虑了。但这些组件能不能有效的云化,能不能结合得好,只有使用者自己心里清楚了。所以说,haibu这种着眼点比较小的项目需要的是喜欢自己折腾的文艺青年,估计普通青年不会太喜欢。

Nodester

这是一个看上去不起眼的项目。但是我却越看越觉得十分有趣。个人感觉他们充分学习了heroku的精华,这点非常重要。可能有的朋友会说,为什么不学Google App Engine,我只能说,在玩PaaS这个领域,Google真的是有点烂泥扶不上墙的感觉。项目维护得非常活跃,也是学习PaaS的好材料。至少国内的几家觊觎PaaS的公司应该好好学学,说句真心话,你们目前做得PaaS或者严格讲叫做伪PaaS真心叫人反胃。个人觉得问人要钱的底线是提供一些比免费更好的产品或者服务,所以有了这些免费的产品应该大幅提高自身的质量,否则死的会很惨。历史上做编译器的故事大家可以自己找找,觉得和今天的一些事情非常类似。

彻底的RESTful设计,虽说只用到REST的第二层(关于哪一层,详见《REST实战》),但不得不说有这种想法的人设计的API就是令人赏心悦目。学习云时代的API设计的话,这个应该是一个不错的范本。PaaS的本质不就是把运维专业化,从而彻底分离,降低开发和运维的依赖性,从而使得运维专业化,甚至独立出来形成专门的公司。此处省略马克思关于分工合作的论述数千字。这种解耦的核心看点就在于接口的设计啊,所以各位看官,一定要好好留意这个REST。我知道这不是他们首创,也不是他们最先鼓吹的,但若是和我们自己的设计相比有优点就该学习嘛。

 

周边开源技术

puppet

这是一项现在很火的技术啦。管理大规模服务器的首选。国内很多同学管理server farm时都很挫的。有人用SecureCRT复制击键,有的人用bash写个循环。如果还这么个方式做云计算的话,恐怕会死得很惨的。云计算将一些原有的软件过程分工细化出来,其存在的意义无非是成本比原来要低。万事归一都在一个钱字上面,说什么功能,说什么服务,说什么扩展性,说白了都是因为成本。问问EC2的使用者为什么要用EC2,说来说去无非就是便宜。原来这种“非研发”成本不被人注意,主要是因为“研发”的浪费太多了,所以处在一个不引人注意的位置。现在到了第二个阶段,大家发现这部分还是挺混乱挺浪费钱的,于是就有了各种各样的方法。

其实在puppet之前还有一个类似的管理工具叫做cfengine,国内用的很少。因为这个东西配置起来比较麻烦,而且像我刚才说的,那时候很多人还没有意识到管理很多机器是个麻烦的事情。这些软件的目的就是让机器管理轻松一点儿,随着这些工具的出现,一些对运维层面深入的思考也不断涌现。其中有几条精华得以在各个工具中有所体现:

  • 故障是常态的,包括各个层面,硬盘的,内存的,整机的,网络的无所不包。
  • 迁移和部署应该是容易的
  • 机器的角色是动态调整的
  • 自动化的,完全自动化的
后来的一些思潮,比如Infrastructure as Code等等都是对这些理念的总结和提高。puppet是Ruby写的,相对于cfengine,性能不高。但这里的场景和Could Foundry一样,真正的问题是我们需要那么高的性能么。cfengine有着非常令人讨厌的语法,尽管其作者的文档能力十分彪悍,甚至还出版过专著,但cfengine依然很难用。puppet在概念上要好很多,据说算是cfengine的直接继承人,所以算是第二代。
统领一群机器不容易,想要高效统领就更困难了,如何用计算机解决一个貌似管理的问题十分有趣,看puppet代码一定要带着这一目的,要思考的是这么设计背后的原因。

chef

这个东西号称是第三代,也就是puppet的下一代,但是目前还不是很成熟。其借鉴了很多puppet成熟的思路,又有很多创新。比如配方(菜谱)的概念,比如配方托管的云化管理思路都是非常值得学习和借鉴的。但目前来看,还处于一个上升期,社区不如puppet那么强大,支持机器的种类也不如puppet那么多。而且puppet也学习很多他的理念,所以今后一段时间二者的相互争辉还是有的看的。

Lustre

哦,这是一个超级文件系统,全世界最牛的500强超级计算机有很多都是用的这个文件系统,开源的,对于学习文件系统还是挺有帮助的。这里我又要免不了八卦一下。这个技术本来是CMU的一个牛人做的,后来成立了公司,借着被sun收购。哎,后面的事儿你们都知道了。不过,当初sun的想法是将其精华融入ZFS,具体融合的怎样,还得进一步考证。不过在sun手里的这些年倒是挺发扬光大的。要知道美国无论是政府还是军方有好多超算中心,sun最愿意搞这些体现技术牛逼的工程了。但贵族以没落,被暴发户收购了。这项技术命运多舛,放在社区手里,我总觉得不放心。大家若是对存储有兴趣,多留意这个就好了,相对来讲资料非常全。

题外话

Ruby和JavaScript是云时代的主流编程语言,Python紧追,PHP应了那句话了“not even close”。heroku将matz叔挖过去的时候,明确放话Ruby是云时代的语言,heroku的整个工程实践也是按照Ruby的最佳工程实践来做的。另外一块那肯定是JVM平台了,云计算肯定会带来JVM平台的另一轮繁荣。至于.NET,本人毫无研究,就不妄加评论了。

网络虚拟化技术下一步会得到很大的发展。原有在多种操作系统下的独有技术将快速融合,比如DTrace,ZFS移植到Linux,KVM移植到Solaris。以DTrace为首的强大工具将会得到非常大发展,成为各种开源产品的标配,以增强在发杂环境下的调试能力。个人认为未来有经验的DTrace工程师会活得非常滋润,有点供不应求,请联想那么多云,尤其是国内的烂云,少不了要调试的人吧。

云计算红红火火,但繁荣的市场上也到处是骗子无赖,踏踏实实做点事情不容易。个人认为踏踏实实学好云计算的相关技术,比肤浅地开发几个手机应用有意思。国外很多大学也开设了相关的课程,大家可以多多关注。

还有些没有说完的话题今后会在补遗中写写。

 

 

包管理器杂谈

前言

今天我想思维跳跃一下,讲讲包管理器,这是一个相当有趣的话题。因为程序员年复一年的写程序,大多是为了娱乐他人,好吧,有的人管那叫创造价值,有的人叫养家糊口。其实没所谓了,本质上来说大部分程序员并不是自己程序的受害者,所以你知道为什么这个世界上有那么多烂程序了吧。让我们回来,聚焦在那些极少的程序员写给自己的程序,除了编译器,版本控制工具以外还有一种非常非常重要,那就是包管理器。

你知道的这个世界上真正了解编译器的人据说坐不满一间教室。我想了解包管理器得人也多不到哪去。首先我们要看看今天要出场讨论的一些候选人。

  • apt 具有超级牛力Debian系猛男
  • yum 为Redhat延寿20年的黄狗
  • homebrew Mac下的青年才俊
  • rubygems Ruby下的魔法大师
  • npm Node.js的超级保镖
  • elpa Emacs的小宝宝

我今天要忽略一些内容,很可能引起某些人的不满。比如像Perl,Python,PHP,Haskell,Lua,R都有一些类似的设施,所以就不一一讨论了。明眼人也许看出来了,六个男嘉宾可以分为两组。一组是系统级别的(system-level),一组是应用级别的(application-level)。维基百科基本上对系统级别的包管理器做了一些介绍,应用级别的仅仅是列举了几个,并没有详细的介绍。但我认为包管理器都是完成类似的工作所以放到一起来讨论。

验证

从单个包的角度来说,一定要确保其来源,否则会轻易受到中间人攻击。所以一般的包管理器都具备简单的验证环节。常见的手法是MD5校验,或者其他Hash校验,homebrew提供的大部分安装包都是用这样的方式校验的。较为严格的应做签名验证,apt和yum都有相应的机制来验证软件包是否来自可信的源。综合来讲Hash的方式加密强度较低,而且严格说来这种校验只应作为下载的完整性检查,并属于授信操作。

依赖性

可以说包管理器解决最为重要的问题就是依赖性关系的问题。我相信在没有yum的RedHat中世纪,大家需要参考n多资料才能正确编译内核。那个时候他们是真心羡慕Debian的。在elpa出现之前,配置一个贴心的emacs环境简直就被视为高手的验证标准。依赖性关系其实并不像看上去的那样容易解决。很多年来make为了解决编译依赖性关系遭受不少的冷嘲热讽。尤其是这种依赖性关系比较松散的时候,看上去就不那么好解决。A依赖于B的3.2.1以上但不超过3.3的版本,这种有时候行有时候不行的条件判断构成了一个非常复杂的逻辑关系。但包管理器必须处理好这个关系,知道哪些依赖条件没有得到满足。依赖性关系的管理是一个生态系统的核心价值。Perl有了CPAN所以带来了一个非常美好的世界,甚至有人说CPAN比Perl的语法更吸引他。依赖性可以让程序员不那么纠结去手工寻找所需要的包,而这个过程可能是相当费时,步骤非常繁琐,而且极容易出错的。对,就好比不使用make工具来编译内核,不是不可能,但阿汤哥会做一些更有利于世界和平的事情。依赖性带来的好处就是开包即用,开袋即食,完全不必担心由于依赖性造成的破损。我猜测由于包管理器提供了一个可信的,可重复的,健壮的依赖性管理,每年程序员节省下来更多时间用于创造新的垃圾代码。

多版本

传统上的包管理器的互斥关系管理有点粗放,apt和yum在处理升级之类的问题时基本就是粗暴地将老的版本替换掉。当然这样设计是比较简单的,可是我们的系统并不美好,经常会有一些遗留软件需要老版本的库。而且从实践的角度来讲这也是一个不太难解决的问题,很多人的机器上都有各种版本的软件,所以后来设计的包管理器就注意了这方面的改进,比如homebrew和rubygems都可以支持同一个软件的多个版本,相互不影响,用户可以随意指定使用软件的版本。多版本是松散型依赖关系必然会出现的特性,也是简单粗暴转向优雅设计的拐点。一个随之而来的问题就是清理不用的版本。这是原来简单粗暴方式比较好解决的一个问题。将原来的是非判断变成了一个寻求最优解的优化问题了。

相对独立的环境

有的时候我们希望严格限制程序的运行环境,但由于包管理器为了便于升级和追新设定了比较宽松的限定条件,使得构建相同的运行环境在相当长的一段时间都是一个非常困难的任务。随着云计算的兴起,基础设施代码化这种思潮逐渐深入实践,诸如bundler这样精巧的工具诞生了。环境配置再也没有手工操作了,而且可以确保所有系统完全一样,简直帅呆了。如果你不觉得帅,那你定没有半夜被狗血电话叫起来去修复线上bug,结果发现这是某个库包与开发者的环境不一样导致的。相对独立的环境在开发者之间也非常重要,任何差异都可能导致惨痛的教训,真金白银的教训啊。相信越来越多的开发者会在云端部署自己的应用,构建相同的环境今后会成为开发者的基本要求的。

发布

有的包管理工具还提供非常便利的构建工具,可以快速构建自己的软件包,并将其发布。开发者可以随时贡献自己的智慧。rubygems就是这样的典型。homebrew可以本地构建一个配方,然后发起pull request,一旦获准别人就能使用了。这个对于未来的开发模式非常重要。Node.js社区的蓬勃发展就是很好的例证。实践证明降低参与者的参与成本特别有利于大家为社区做贡献。

源码还是二进制

我倾向于homebrew的源码编译方式,虽然有点慢,遭到一些诟病,不过我觉得看着代码打补丁,编译是我的个人乐趣。

传输问题

考虑到中国网络的多样性问题,在此我讨论四个方面:网速测试,断点续传,多点传输,下载调度。无疑elpa在这几方面做得奇差无比,简直就是各个方面的反面教材。yum提供插件可以检测最快的镜像源,apt做得也还可以。但都不能同时从多个源下载同一个包,有时候我们还是很需要迅雷或者BT的功能的。断点续传不用多说了,算是一个基本功能。同时开启多少个并发就不能智能点么,非得一个或者n个,就不能自动调节么。

甚至我觉得包管理器应该构建于BT或者电驴之上。

关于源

私自搭建一个源应得到鼓励,应该几乎没有成本地加入到整个全球分布式的系统中,源之间的同步应该也是开箱即用的。这方面做得最好的我认为是全球的公钥分发系统,BT和eDonkey次之。

结语

生态系统无论对一门语言还是对一个系统来说都是非常重要的,人们不会凭着一门语言良好的语法就蜂拥而至的。良好的生态系统为他们提供可靠而丰富的工具链,库包,最佳实践。而位于生态系统核心的正式管理依赖性关系的包管理器。本人杂乱地讲述了对各种包管理器一些思考,希望能“抛砖引砖拍”!

火星程序员带人指南

本来我是想写一本JavaScript方面的书,介绍一些这个领域内关于编程方法学和整体生态环境进展的书。但是去年与图灵的编辑们探讨过后,他们一致认为我应该先写出来一点,看看市场的反应。虽然建议不怎么好听,但毕竟只有真心说实话的人才会赢得我的尊敬。他们的担心体现在了两点,第一就是我作为一个在JavaScript领域并没有什么影响的人写出来的东西到底能不能卖,第二考虑到我妻子临产,我是否有充足的时间完成所规划的内容。至于内容方面我也是有些担心的,主要是貌似国人关心语言生态圈的并不多,他们把语言简单地当做一门工具,无论是赚钱的工具还是娱乐的工具,所以几乎看不到人谈论一门编程语言的流派,演进,思潮,展望。这些字眼儿也许过于风花雪月,但我觉得其实并没有那么地不切实际。在大家都在谈论某一具体的库,某一个具体的网站,某一种具体的新技术时,我总是感觉缺少些什么。似乎在这些疯狂逐利的群氓中,我更希望看到的是一个能沉静下来,多问几个为什么的人。

我最近带了两个新人,他们不是初学编程,基础也比较好。带的过程中我一直在想如何才能不误人子弟,如何能让他们获得内心的平静与强大。考虑再三,我决定让他们通过阅读一些经典代码,然后我提问题和演示的方式展开一开始的学习。理由如下:

第一,阅读源码是绝对必要的。虽然编程是创造性工作,但实际所有创造性工作的绝大部分都不怎么有创造性。这和艺术创作是类似的,大部分艺术家要数十年如一日地修炼自己的各种基本技巧,而这类基本技巧的训练经常是极度乏味,毫无创造性可言的。但是程序员往往以为自己跟别人不一样,想当然地认为大部分工作都是创造性的。说句实在话,我看到的大部分程序员都是缺少基本技巧的训练的,有的甚至说极度缺乏也不为过。最令人不解的是,很多人不愿承认这一点,或者即便承认也对此丝毫不以为意。其中我觉得代码阅读就是基础中的基础,一个看不懂别人写的代码的人,自己的写代码水平也必定有限。这个道理很好证明,一个人可以读懂自己写的任何代码,所以说他对代码的理解力一定大于自身的创造力,反过来说一个人的创造力的上限也就是他的理解力了。写代码和写文章非常类似,我以前也说过,就不罗嗦了。这里只是再一次重申代码阅读能力的重要性非常之高。所以我看程序员好坏,除了让他写一段程序,还可以让他读一段程序,甚至我更倾向于后者。读这个基础打好了,才能为写做一个良好的基础。

第二,要读经典才能学得更多。这简直就是废话。听音乐的要听经典的,读书也要名家名作,临摹字帖得是千古流传的……但程序员大部分时间都在读质量并不怎么高的代码。就好比我们读到的和我们息息相关的文字多数也没有什么美感一样。一定要刻意地找寻经典,话又说回来了,这就需要对一门语言的生态圈十分了解才可以。不但要知道那些产品非常有名,而且要知道为什么有名,谁在用这个产品,怎么用的。经典的代码和经典的音乐有点不一样,经典的代码一般还都处于活跃的维护期,不像音乐好多已经上百年没人更新了(呵呵,有点大不敬啊)。所以经典代码是活的范例,解决的是具体问题,不但可以学到编程的各种规范和技巧,也能学习到比人是如何思考改进代码的。好的代码更易于读懂,更清晰,有利于学习清晰的设计思想。这些都是普通教科书或者一般技术书籍所无法比拟的。学会跟踪趋势,知道流行也是程序员基本技能,况且额外的还可以通过读代码知道很多圈内八卦,这个是一般人不知道的乐趣。

第三,问题可以查看细节的理解是否到位。首先要说明的是无论是提问还是回答问题都是非常鼓励的。我一般会事先布置一些问题,然后让他们一起去研究,然后回答也可以问我新的问题。这种方式经过实践证明是非常有效的。学徒能够更集中精力,对问题的理解也会更加深入。透过他们的回答,我还能更清楚地判断哪些细节掌握的欠佳,我会毫不留情地抛出更多的问题。回答出所有问题只能得到及格,要提出问题才能获得高分。鼓励他们在提问的同时设计实验来检验自己的命题。这种苏格拉底式的修炼,一开始着实让新同学吃不消。因为我的问题无处不在,他们似乎第一次面对一个如此不会掩饰自己无知的家伙。这种方式使得他们渐渐抛弃了那些我们习以为常,却丝毫经不起验证的各种假设和误解。他们渐渐试着怀疑权威的观点,他们也会主动去验证自己的观点。编程是门实用艺术,一定要经得起别人问。

第四,演示促进理解和沟通。我发现大部分人对于把问题说明白这件事儿看得并不是很重要,尤其是工作经验比较少的同学。作为训练的一个科目,我要求不能只讲给我听,要演示给我看,要让我不经意间就能相信你说的都是对的。一开始有的同学觉得我比较扯,什么都演示多浪费时间啊。但如果你看过《完美软件》或者《人月神话》就会明白,就留沟通不行,问题都说不清楚,项目的失败只是时间问题,并没有回天的余地。程序员都觉得以“宅”为美,这就是狗屁好莱坞大片看多了的结果。我们不能相信好莱坞大片中的技术宅男,就好比我们不能相信国产电视剧中的八路军一样。我接触过很多大牛程序员,没见过哪个宅的。在一个团队,就是不能有信息的孤岛。在这个过程中我也发现了新手的一些常见问题,列举一些:

  • 倾向于说服,而不是证明。如果你要说明别人是错的,最好的办法就是举一个反例。如果你要说明你是对的,请回忆一下中学老师关于说明文的各种技巧。其中包括举例子,作类比,打比方等等。记住重复阐述自己的观点对理解几乎没有任何帮助。
  • 证明过程跳跃不完整。你说这两个对象是同一个的时候,就要演示一下是否全等,长得一样是远远不行的。
  • 思路不清晰,经常把自己绕进去了。课下的功夫做得不够。
  • 不cool。很多人说什么?!这也算是缺点!?当然,记得大学里上过的那些死气沉沉政治课吧。很多人上学的时候都对乏味的课程大放厥词,但是轮到自己演示的时候却是一个模样。我为什么要听你讲?你得有趣,人要有趣,讲的东西要有趣,要酷才行。
  • 不能即兴演示。对于观众提出的突发问题,没有即刻的反应。互动效果差。

好了,这些就是我对带人的一些实践。今后我会写一个专题,把我和他们之间讨论的问题记录下来(对,有可能是那种《论语》风格的),名字就暂定为《火星人JavaScript问题集锦》。起初几期讨论一下underscore和backbone的源码,之后会讨论jquery,coffeescript,less,欢迎大家参与讨论。

我们做了一个操蛋的网站

昨天公司内部发了一个邮件让做一个调查。考虑到这个调查系统是我们自己开发
的,而且我还没有使用过,便兴致勃勃地开始一段特别苦恼的旅程。

我不断地问自己问题:一个在线调查系统的目的是什么。在我备受煎熬,不得不
依靠自己强大的内心才完成了这次调查之后。我极其郁闷地将开发同学和产品同
学召集起来,将问题抛给了他们:“请用一句话回答:在一个被调查者眼中怎样才
算是一个好的调查网站呢?”

“需要有其他选项,不想被限定在某几个选项中。”

“易于学习,便于掌握,好操作。”

“引导用户说出自己真实的想法。”

“⋯⋯”

我深深地叹了口气,摇了摇头。我对这些一点儿都不着边际的话并不感到意外,
但我依然抑制不住自己失望。我提示大家:“你们猜我在做调查的时候是一种什么
样心情和想法?”所有人都有点愣住了,似乎从来没考虑过这个问题。

“做这个调查时,我唯一的想法就是:怎么TMD还没做完?!”

很多人笑了,看来这种经历并不是专属于我个人的。还有的人提示我说:“哦,这
个还算简单的呢!”

我继续问道:

“谁会来我们的网站接受调查?他们的目的是什么?我们的产品给他

们带来了怎样的价值?”

所有的人都静下来了。我一点一点的展开:

要知道我们其实做了一个非常操蛋的网站。因为所有来我们这里的用户都非常讨
厌我们的产品,没有,绝对没有任何一个被调查者会喜欢我们网站。因为他们不
是调查公司施以利诱骗来的,就是受人所托,或者是被要求(被逼也说不定)必
须完成调查。没有人是自愿的。他们从我们的产品不能获得一丁点儿价值。他们
想要的是什么?无非是尽早结束,这样调查公司骗来的用户就能获得那些虚无缥
缈的积分,受人所托的就能对别人有个交代,强迫完成的也总算能交差了事。

“一个用户无法获得价值,一分钟也不想多呆的网站肯定是个非常操蛋的网站了吧。
我们唯一能做的就是让其少操蛋一点,配合用户最快速地完成调查。好吧,这就
是用户眼中好得调查网站的标准:最快速地配合用户完成调查。”

所以,交互上要实行最简原则:

一个狗屁单选题绝对不要让用户再确认一次,对于单选题来说“下一题”的这个按
钮也完全没有必要。少一次点击对于程序员来说似乎是一个“死不了人”的问题,
但对于单选效率则会提高100%,这是别的优化望尘莫及的。有反对意见的同学可
以参考google首页,这是一个跳出率极高,粘滞时间超短的页面,难道我们的页
面不应该这样么。

扩大点击范围,整个选项都应该是可以点击的,而不仅仅只是有个选项框可以点
击,极力减少用户在操作过程中的鼠标滑动。邀请选择的暗示要足够强烈。

根本不需要后退(或者“上一题”)按钮,用户一心想往下进行,根本没有心思后退。
如果需要后退的话,那一定是某处逻辑设计失误(比如互斥条件)。如果是这样的
话,一定要立即解决逻辑设计的问题。后退这个按钮掩盖的都是肮脏的浪费。

支持键盘操作。要知道,虽然答题的人不想答题,但经常答题的人群确是非常稳
定的,一旦他发现键盘可用,则会兴奋起来,对于职业答题者非常必要的。

尽量避免让用户录入文字。“其他”就足够了。

尽量将问卷一次加载到前台,由相应的javascript来完成前台逻辑校验
(backbone.js就是不错的技术方案)。
后记

我听说了很多关于调查问卷的奇闻轶事。

有的客户要求做的调查有100多道题目。我不知道制作题目的人是不是仅仅是为了
完成任务。100多道题目太多了。人类的注意力集中时间大概只有20分钟左右,所
以必须在这之前完成所有调查。否则用户会倾向于敷衍,或者欺骗调查系统。

有的客户要求题目的逻辑异常复杂。你做到最后几个题目时不让你继续,除非你
把之前的20道题目都改成他们认为合理的取值范围内。我也是玩过有偿点差的人,
后来放弃了。全因为这些调查不仅是对你智商的侮辱,也是对你耐心和体力的双
重考验。这就是特别典型的逻辑互斥设计缺陷。

有的客户要求当用户对某个题目分数比较异常时给出理由。理个屁啊?会有人看
么??既然然人家选,就不要问人家为什么。所有选项间的继续进行难度应该是
一样的。人为造成的交互难度不一致会使得用户倾向于选择交互容易的选项。所
以客户看到了他们想要看到的结果,问题是那TMD还做什么市场调查啊?

有的客户设计了特别变态的逻辑题目,让用户完成一张我们都认为连阿汤哥都无
法完成的表格。拜托,用户要是都能做完,阿汤哥不就失业了。调查表格的设计
前提就是填写者没有义务填写。一个直接推论就是填写调查表格时,用户不需要
借助辅助思考或者计算h。我真的不知道,调查表的设计者学没学过《市场调查》
之类的课程。有没有老师认真地告诉他们,其实填表的都是大爷。

好了,就权当娱乐了。

MongoDB 2.0的亮点

亮点一 数据压缩

跑过MongoDB一段时间的管理员都会奇怪,这个家伙怎么这么吃硬盘。大家在各自 的实践中总结了各种最佳实践来应对这种永无止境的硬盘吞噬。比如手工的导入 导出,或者利用复制组的自动恢复特性,定期人为制造故障,来强迫系统进行故 障恢复,来达到导入导出的目的。MongoDB对于硬盘的利用率的确不高,这也是广 泛遭到诟病的一点。新的MongoDB 2.0有了campact命令,用来解决这一问题。看 上去有点像做磁盘碎片整理的程序。会不会也很慢呢?很不幸,还是会很慢,不过 好在不需要导入导出所要求的那么多的空间。所以还是要在备份节点执行,还得 选择负载不高的时刻执行。不过后来想想,叫做压缩不如叫做碎片整理更加准确。

 

亮点二 索引

索引原来就有,而且数据量少的话,根本感觉不到这东西需要提高性能。呵呵, 开玩笑了,线上的业务哪个数据量能少呢。新版的索引据称效率提高25%,体积减 少25%。这是个相当不错的消息,管理员尽管用就是了,没什么好犹豫的。只是从 原有的系统升级到2.0并不能自动利用新版索引。需要强制重建索引才行。不过, 管理员要是执行了上面的campact命令的话,会附带重建指定的索引。

 

亮点三 复制组节点的优先级

原来很多人都问我,复制组中的某台机器恢复过来了,怎么继续让它成为活跃节 点(primary)。很不幸,以前没啥好办法。优先级的设定非常重要,尤其是对大型 集群,能够避免负载传递这种连锁反应。优先级高的节点一旦与最新的数据同步, 则会触发选举,并在选举中胜出。很实用吧。

 

其他

增加了对多边形区域的支持,以及多个地点的支持。LBS相关的应用会觉得这个功 能非常贴心。

MapReduce性能有大幅提升,去掉了一些不必要中间转换过程。

大红大紫的JavaScript

现在说JavaScript大红大紫估计大家不会有什么反对意见吧。如今学习
JavaScript不但是一种非常保险的策略,甚至是必要的生存之道。不过这门语言
就和他的难兄难弟HTML一样承载了太多本不应该它们来做的事情。发展速度的过
快造成了原有设计上的缺陷被极不合理地放大了,以至于业界大牛Douglas
Crockford出手教人如何正确地利用那些还不错的特性,避免陷入令人恼火的陷阱。

问题的关键是人都是不靠谱的,再怎么教,再怎么强调,再怎么小心,
JavaScript那些罪恶的灵魂依然会渗入你项目的骨髓当中去。似乎是有
JavaScirpt的地方就有那种挥之不去的阴魂,即便使用了JSLint,也是疲于奔命。
CoffeeScript也许是这种噩梦的终结者,它继承了JavaScript好得部分,但也限
制了一些过于随意的地方。看似CoffeeScript是一门全新风格的JavaScript语言,
或者说是Ruby风格的JavaScript,但也没有必要大惊小怪。还是SICP中的那句
话:"解释器(编译器)也是一个程序"。与其为一门语言做些修修补补的操作,不如
另立门户。貌似C++走的就是这样一条路,历史总是很相似啊。CoffeeScript的一
个比较有意思的地方在于编译生成的正是JavaScript,这样就非常好地解决了与
现有系统兼容和集成的问题。OK,你可以放心大胆地用这个新技术,他对你的老板
是透明的,因为他只能看见工作的JavaScript,并不能看见你的源码。当计算机
技术发展到了今天,有趣的事情终于发生了,你以为看见的是源代码,其实不是。

无独有偶,CSS方面也有类似的方案SCSS(SASS),来解决CSS不支持变量,继承等
问题。巧合的是这两个方案都将作为Ruby on Rails近期即将发布的3.1版本的默
认方案。世界变了,你拿的武器变了么?

翻墙备忘 从bluehost的虚拟主机上打洞访问twitter及facebook

从前从bluehost上面打洞的时候总是不稳定,有时候能成功,有时候不能成功,后来因为有其他的工具,也就一直没深究。
不过隐隐觉得,是否是访问twitter及facebook的流量太高以至于被bluehost封了?

今天发现在 bluehost 上面 curl twitter.com 能抓会twitter 的首页,也就是说,从bluehost访问twitter是没问题的。
那么为什么打洞之后无法访问呢?
问题一定出在本地的DNS上。

好吧,让我绕过DNS,直接把正确的地址填进hosts文件中好了。

获得某地址对应ip:
bluehost上没给发icmp包的权限,所以ping是不成的,用python的socket模块获取。

?View Code PYTHON
import socket
print socket.gethostbyname('twitter.com')

后来发现直接用shell命令

gethostip twitter.com

就行了

将下面的地址加入/etc/hosts

#twitter
128.242.245.84  twitter.com
128.242.245.125 api.twitter.com
128.242.245.116 www.twitter.com
 
#facebook
66.220.149.25   www.facebook.com
66.220.147.42   login.facebook.com

然后再试试用 bluehost 打的洞,灰常顺畅。