29

去游之前,杨MM的广告词:

早9:00乘车赴密云司马台长城景区,沿途可欣赏密云卫星城以及秀丽的京郊山水,中餐后登司马台长城,此处是中国长城唯一一段偏离原北齐长城基础的明长 城,也是唯一一段保留明长城原貌的古长城,在京城众多长城游览区中尤为险峻,晚餐享用农家宴,前往酒店参加盛大篝火晚会。酒店赠送娱乐项目:乒乓球、台球、健身、棋牌、麻将、卡拉 ok、游泳等。

第2天:密云—北京市区(车程约3.5小时)
早餐后乘车前往雾灵山森林公园(游览约4小时),园内山势雄奇、云雾缭绕、峰峦叠翠,溪水潺潺,景色之美,犹如置身人间仙境,让人流连忘返(含小交通10 元/人往返);园内山势雄奇、

云雾缭绕、峰峦叠翠,溪水潺潺,景色之美,犹如置身人间仙境,让人流连忘返。午餐后返回北京,结束愉快行程。

其实累个半死,还被太阳暴晒。

27

Restful + javascriptMVC是不是绝配呢?

Rest抛弃了传统mvc的web开发架构,服务器端变得简单,形成胖客户端的结构,不过浏览器端开发始终是一个瓶颈,不是谁都有勇气徒手写javascript做网站。对javascriptMVC不是太了解,不知道它是把事情搞复杂了,还是把事情简单化了。

Tagged with:
26

刚刚看了sony发布了日常版阅读器,不过没看到具体的细节,如果能有boox那样让人大开眼界倒是可以考虑买一部,boox不太争气,创意无穷,只可惜要胎死腹中,浪费了大半年也不见出来占领市场,在电子市场上虚掷光阴等于自杀啊。

我要的阅读器功能其实比较简单,我主要用来阅读一些英文小说,少壮不努力,只好现在恶补了。

那电子书免不了要有即时翻译了,这是其一。然后,我喜欢在书上一些句子和单词下划横线,以备重温的时候重点记忆,这是其二,其实这个我看汉王,翰林他们都做到了,只是细节做得不太好,比如只能在txt格式划线,放大字体的时候划线消失等。

其三是书本格式支持和文件导入方面,这个除了kindle,其他做得都不错了,而我也就看看txt和pdf文件多点。

boox让我看到了阅读器上网的潜力,那就多出来个需求,用wifi联网上google reader看文章。

不过,其实现在的boox已经让我很满意了。

http://www.onyx-international.com/en/ 这里的视频介绍如果不是假的,那也可以出手买了。只是丫就是不上市!

26

转自左岸读书。

最近以裁判的身份参加了公司举办的编程大赛,发现高手云集,对公司内部的程序员能力也有了更深入的了解。我觉得编程能力对程序员而言,虽然很重要, 但并不是 全部。那么作为一个程序员,到底应该具备什么样的能力呢?这个话题显然太大。不过我觉得可以看看其它国家的程序员,也许可以得到一些借鉴。我有幸和中国, 美国,印度和日本四国程序员有比较深入的合作过。虽然他们不一定有代表性,但我觉得他们的共性还是比较明显的。以下的比较纯属个人见解,欢迎指正。

首先是日本程序员。他们的特点是非常仔细。我认为很主要的一个原因是日本公司的需求非常细致。细致到在网页上, 连一个像素都不能偏差的地步。另外, 日本人的执行力非常强,对老板的承诺比命还重要。一个项目可以做到连续3个月天天加班,每天只睡4个小时。然而,高执行力背后的代价是低创造力。在日新月 异的互联网今天,很少听说日本工程师发明了哪些重要的技术。与其说这些特点是日本程序员的,不如说是大部分日本人的。因为在日本文化中,追求品质和遵守等 级制度是根深蒂固的。另外,技术领域中的很多专业词汇是外来语,以英语(论坛)为主。这些专业词汇往往会被翻译成片假名。而片假名的发言有时候和英语大相 径庭,导致沟通的困难。比如病毒一词在英语中是Virus,发音为歪儒斯,而日语的发音是味鲁斯。再例如服务器(Server)一词在日语中的发音是萨 巴,和英文发言简直风牛马不相及。因此与日本程序员沟通是比较痛苦的,除非你懂日语。

其次来看看印度程序员。我所接触的印度工程师都是在美国工作的。虽然他们和印度本地的工程师肯定有区别,不过相似的地方应该更多一些吧。我觉得他们 的普遍优点就一个:流程做得好,文档写得好。但 是他们写代码的能力,我个人的观点是一般般。我想这里面有两层原因。一是有相当一部分在美国工作的印度程序 员是半路出家。转行做程序员是为了生存而已。二是印度程序员在算法,数据机构等基本功方面的水平明显低于中国程序员的。这就导致他们写的很多代码逻辑性不 强和性能不优(以我的标准来看)。不过这两个问题在一定程度上被大量的文档和高性能的硬件设备弥补和掩盖了。在沟通方面,印度人的英语发音对西方人而言几 乎没有问题,但很难被中国人听懂,甚至往往被国人怀疑他们是不是在说英文。

从某种意义上讲,日本程序员和印度程序员十分相似。他们都很敬业,都能让领导比较满意,但不要过多地期望他们能做得更好,因为他们的目标就是完成领 导指派的任务。日本程序员让领导满意的方法是不折不扣的执行和狂热的加班。而印度程序员让领导满意的方法是通过大量的文档来告诉领导他们的工作意义重大, 流程严谨,资料齐全,而且成本很低。夸张一点地讲:日本程序员善于做领导想做的事,印度程序员善于说领导想听的话。

接下来说说美国程序员。美国程序员千奇百怪,好像很难只用几个词来定义他们。可能是因为美国是一个移民国家吧,本来就千奇百怪。但大部分程序员有一 个共同的特点:喜欢技术,甚至崇尚技术。这 点在硅谷尤为突出。这就导致每个技术领域中都有一些人会废寝忘食地钻研。其实这和打游戏一样,如果你着了迷,自 然会忘了吃,忘了喝,拼命地玩。我所认识的美国程序员还有一个特点,才艺能力都不错。以前在波士顿工作的一家公司中,几十位工程师居然可以组成一个交响乐 团。有小提琴,大提琴,小号,竖琴,打击乐等各种各样的西洋乐器手。而且这些哥们姐们还不是一般地玩玩,周末都有自己的固定乐队,经常参加社区的表演。更 有甚者,在硅谷工作时的一位同事,白天写程序,晚上在自家的车库里练习乒乓球,竟然代表美国参加了悉尼和雅典的两届奥运会。说起写文档的能力,美国程序员 绝对不亚于印度人。但是美国人写文档不是为了老板,而是为了自己,为了分享。因此他们的文档往往读起来很有趣,很实用。当然,这会让老板有时候很头疼,因 为程序员不那么“听话”。他们不是给老板交差,而是要实现自己的想法,自己的设计,自己的完美。说白了,就是美国程序员有时候想法多了点。

最后是我们中国的程序员。和其他国家的程序员相比,我觉得他们的特点还是比较明显的。他们的算法能力普遍高于其它几个国家的。这可能是我们的教育体 制导致的,比较注重理论知识。反过来,实践能力就相对差些。我 们的程序员执行能力并不差,但在解决问题的能力上明显不足。往往需要把任务分解得很细以后才 能完成,独立解决问题的能力不够。另外在表达能力上也相对差些。相信大家一定见过技术水平很高,但表达能力很差的工程师。最好笑的是,我见过不少工程师拿 着一支写不出字的白板笔(我们的白板笔质量也确实不咋样),有模有样地在白板上写字。仿佛听众可以看得到他/她写得是什么。因为他/她完全沉浸在自己的逻 辑中,完全不去体会听众的感受。不过我认为这些缺点并不严重。

因为这些是属于技能和经验方面的东西,是可以通过实际工作或者培训来提升的。我认为国内程序员最大的问题还是所处的环境不利,导致相当一部分人比较 浮躁和急功近利。真正能够沉下心来钻研技术,热爱技术的是凤毛麟角。我在面试的时候,常常发现工程师知识面还挺广,但深度几乎没有。这样的人很难在技术领 域有所作为。我希望找到的人是,敢于承认自己不会的地方,但是只要会的东西,哪怕就一样,就要一定比别人理解得透,钻研得深。我相信一个人如果在某一个问 题上比别人做得好,在其它问题上也一定有能力超越别人。

虽然比较下来,看到中国程序员不少的问题。但作为群体,中国的程序员可能是全世界最聪明的工程师群体。因为环境的原因,使得他们不得不想法很多,顾 虑很多,无法最大程度地将聪明才智发挥在技术上。改变这种状况首先要从公司的管理层开始。只有技术负责人热爱技术,追求卓越,才可能为技术人员创造环境, 激励他们钻研和创新。技术负责人需要深入项目,和工程师们一起讨论技术设计,从而通过具体问题来提升工程师的能力,同时也防止自己的技术能力滑坡。在技术 管理上,很多国内的公司把工程师简单地作为资源,过于强调流程管理和资源管理。我的观点是:工程师不是高级蓝领,不能以管理生产线的方式来进行管理。优良 的环境只有靠大家一起来创造。中国工程师一定可以成为世界上最优秀的工程师群体。

25

折腾了两三天,把他们原来的dvbbs数据导出到discuz里面,问题当然还是碰到了一些,比如开始是linux下XConvert程序不起作用,便想在本机安装个环境跑,那是比较麻烦,装了apache,php,mysql还得装ucenter,discuz7,最后才能运行XConvert,后来有个简单的解决办法,就是使用ComsenzEXP一体化的软件包,一个东东把以上软件全部包了。

导数据也碰到了麻烦,原dvbbs里面有几条重复id的帖子,真不知道是怎么设计的数据库,反正导入mysql中间程序就卡壳了,我只好找人要了个office装access,打开access文件删掉重复帖子再重新导入数据。

昨晚有个巨后悔的操作,我把discuz验证码改为中文,为了测试效果退出了后台,结果在linux系统下显示不了中文,管理员又无法再登录了,真是巨操蛋,可是又别无办法了,网上的解决方法不外是上传个ttf中文字体文件到images/fonts/ch/目录,不过在我这个系统却不起作用,我几乎要重装整个论坛了。花了几个小时研究php代码,不得其解,最后还好,找到个办法是修改forumdata\cache\cache_settings.php中修改下 ‘seccodestatus’ => ’0′ 然后登录后台。

最后贴出地址

http://gzhsa.org.cn/

Tagged with:
22
司马台长城
Tagged with:
21

谷歌adsense出现的二手汽车广告越来越多,这种东西一眼就知道是骗人的,然而谷歌并不知道,它也不想知道,虽然我几年前就写过投诉邮件,却是如石沉大海杳无音讯。未命名这说明在贵国,不作恶是不可能生存的,无论你是百度,还是谷歌。

只是谷歌也实在是太过份了点,我屏蔽了chengyi2c.com吧,又冒出个新域名出来,不断翻新,不厌其烦,幸好搜到了一片帖子:http://bbs.qdit.com/dispbbs.asp?BoardID=30&replyID=533644&ID=407731&skin=1

截至到2009年8月8日 11点
我们共计屏蔽 201个 骗子网址,这些都是google 广告代码展现给网友的。请大家留意!!!

我们会见一个封一个!!!

020858.com
022qiche.com
0779ok.com
588qc.cn
598a5.com
912car.com
aabb6776.com
ao2car.com
aojitongqiche.com
baichengqimao.com
baideli2sqcgs.com
bailianlianhe.com
baodi88.com
baojia8988.com
blj2che.com
bsj2car.com
by2car.com
byby999.com
cb2che.com
cd2car888.com
cdqc88.com
cdzy2car.com
ch2shouche.cn
che2yx.com
chengxinsh.com.cn
chengyi2c.com
chiccar.cn
cjs7che.cn
cxqiche.cn
cxqm8.cn
cy2sc.com
dali2che.com
dr2auto.com
ds2sc.com
dsgm2car.com
dy7che.com
dy818.com
dz7che.cn
f5588.com
feichi88.com
futong2car.com
gc3366.com
gkkj66.cn
gkkj88.cn
gs2qc.com
gzyl2sc.com
haosheng5858.com
haosheng5898.com
haotong588.com
hc2188.cn
hc586.com
hengcheng8899.com
hengda66.com
hesheng818.com
hg2shouche.com
hh2cars.cn
hhcar668.com
hhqm8.cn
hl2cars.com
hn178.com.cn
hongsheng5858.com
hongyuan188.cn
hongyuan188.com
hq3788.cn
hs2sche.com
hsqc88.com
hstqm.cn
huaaoqimao.com
huachang88.com
huacheng168.com
huachengqimao.com
huafa2car.com
huamao688.com
huaruiyuanqimao.com
huxin2car.com
hw2qc.com
hy11.cn
hycar158.cn
jc1996.com
jc2shouche.com
jdqc88.com
jfqimao.com
jg2c.com
jiacheng88999.com
jiadeqcxsgs.com
jiahao6688.com
jiahe2che.com
jiangbin2c.com
jianghuai2c.com
jiasheng8889.com
jinhuiqiche.com
jinjiaoqm.com
jinxin6688.com
junhaoqm.com
jx7che.cn
kr2scar.com
la2sche.com
ldqiche.com
lianhehuapeng.com
lj2scar.com
longfengqimao58.com
longshunqm.com
longzecar.com
ls2car888.com
lx2c.com
ly2scar.com
mingchengqimao.com
mingdanet.com
moto186.com
my8668.com
nan5566.com
newsun120.com
qingdaoxinli.com
qj2che.com
rongshengqimao.com
rq163.com
rs2sc.com
runhuajituan.com
runtongqimao.com
runxiangqimao.com
ry2car.com
ryqiche.com
sd2sc88.com
sf2che.cn
sf2sche.com
sh120.com
shiji21.cn
shunchangercar.com
shuncheng2.cn
shunda2sche.com
shundasche.com
shunfa998.com
skd2c.com
stx889.com
swqiche.com
sxin2car.com
szglsw.com
tc2scar.com
tengfei2qm.com
tengsheng6688.com
tengshengqimao.com
tengshengqm.com
tengyi2che.com
tianchengesc.com
tjyj2sc.com
tl2che.cn
tyhqm.com
uk2car.com
wanbiao66.com
wanyuan88.com
waosheng5588.com
weida2car.com
wff66.com
wj2sc.com
wx7che.cn
wz2auto.cn
xd2che.com
xdl567.com
xiangtaiqimao.com
xietongqimao.com
xinda369.com
xinjing2car.com
xinli668.com
xinlianqimao.com
xinmeiqimao.com
xinsheng868.com
xinsheng888.com
xinwang56.com
xinyuan518.com
xm2che.com
xssh2008.cn
xuriqimao.com
xw2sc.com
yazhijieqiche.com
yd365.cn
yf518.com
yichengqiche.com
yideqimao.com
yidong123.com
yidu2car.com
yinhe2c.com
yiyuan2sqm.com
yongfa2che.com
yongfa2sche.com
yonghao168.com
yongsheng5588.com
ys2sche.cn
yuandong588.com
yuanhua188.cn
yuehui2che.com
yxin2sc.com
yz2qc.com
yzzhijieqiche.com
zg2shouche.cn
zhongming888.com
zhqm66.com
zm2scgs.com
zunrcar.com
zunrong2che.cn
zx2car.com
zy7che.com
chengyi2c.com

最后一个域名,正是我刚才颇为震怒的发现的新域名,昨天才封了,今天又出新的,还不把我给气死啊。

Tagged with:
19

有些音乐会让你忽然换了一个人一般,又好像不是,还是自己啊,只是回到了人生的某个阶段,哎,是那年轻的时候吧,只是个错觉,有时候会想知道年轻的时候,我在做什么,我在想什么? 几乎都给忘记了,而现在居然漂泊在北京了,成了一个中年大肚腩的异乡人。

今晚的茶不错,上次在家买的,香味一般,扔了一包给强叔鉴定,他还以为要200多,其实只是80而已。《twiligth》只看了70多页,磨磨蹭蹭,每个晚上看几页,不知何年可以完成,哎,还有《Marley and me》,《the future of FREEDOM》,《reader》,以及特意上次回广州带来的《西班牙旅游笔记》,这些还没看,心痒痒又在网上订了四本,我也只是买书的时候痛快,看书很磨蹭,然而我几乎又迷上了电子书阅读器,比如kindle,比如sony reader,当然最让人着迷的是boox,价格不菲,我担心买来我也读不了多少书,又被我扔到一边,成为另一件电子垃圾。

刚听说基地想找我帮忙搞网站,其实都无无所谓了,我还可以给他们提供服务器,他们的流量估计不会大到啥地方去,一个慈善机构,也不要再自己购买带宽服务器吧,也感谢他们照顾了joey(熊猫眼)半年多,虽然joey出事了,很可惜,然而在这个世界上,我怀疑joey在基地的时候是它一生最幸福的吧,它主人抛弃了它,估计也不曾在那里享受多少温暖,而我家它也只是呆了一个晚上,然后就一直在医院了。后来它便被送进了基地,再后来见了我也不再认得了,那时它也是刚理了毛发,光秃秃的,居然怕生得很,飞一般跑了上楼藏起来,然后使劲朝我吠,一吠就是不肯停了,中气十足。我跟raymond都很高兴,心里都冒出童话里最常说的那句话:从此joey在基地过上了幸福的日子。。。

那是四月份吧,来北京之前,跟raymond最后一次去见joey,回来在水库旁边吃饭,点了一条不知名的鱼,貌似很贵,说啥淡水三文鱼,几种煮法,两个人吃趴下了。吃饱了撑着想申请个twitter账号,@163news,结果失败了,现在有了个叫@news163的,我们咋不会变通呢。

Tagged with:
17

Today’s bad news, Joey is dead, she was killed by another mean dog.

http://bbs.pclady.com.cn/topic.jsp?tid=246769&pageNo=1

1247665233607_m2

(2009-08-17 10:46:21)
基地新来一只大狗叫威威,喺比较凶猛嘅罗威那,基地得华叔可以搞得掂佢,joey又喺成日跟住华叔嘅,华叔行到边,佢就跟到边,琴日华叔去关返威威时,joey跟住华叔过去,joey睇到威威度有未食晒嘅狗粮就过去食,威威睇到后就一口咬住佢,罗扫把点打都唔放,等放落来,joey未到2分钟就走咗了

Tagged with:
16

作者 Stefan Tilkov 译者 徐涵 发布于 2008年8月4日 上午7时25分

人们在试验REST时,通常会四处寻找样例——而他们往往不仅能找到一大堆自称“符合REST”或标榜为“REST API”的样例,还会发现许多关于某个自称符合REST的特定服务名不副实的讨论。

为什么会这样?HTTP虽不是什么新事物,但人们使用它的方式却五花八门。其中有些做法符合Web设计者的初衷,但许多并非如此。要为你的HTTP 应用(无论是面向人类、还是计算机、或同时面向这两者使用的)应用REST原则,意味着你要恰好反过来:尽量“正确地”使用Web,或者说按符合REST 的方式使用Web(倘若你不喜欢用对或错来评判的话)。对许多人来说,这的确是一种崭新的方式方法。

我经常在文章里作同样的声明:REST、Web和HTTP是不同的事物;REST可以用多种不同技术来实现,而HTTP只是一种恰好符合REST架 构风格的具体架构。所以,其实我应该小心区分“REST”与“REST式HTTP”这两个概念的。但我没有这么做,在本文剩余部分,我们姑且认为它们是相 同的事物。

跟任何新的方式方法一样,发掘一些共同的模式是有益的。在本系列的第一第二篇 文章中,我已经讲述了一些基础——比如集合资源的概念、将计算结果转换为资源本身、以及用聚合(syndication)来模仿事件。后续文章将进一步讲 述这些及其他模式。不过在本文中,我想主要说说反模式(anti-patterns)——即那些力求符合REST式HTTP、但未能成功而造成问题的典型 做法。

首先我们来看看我发掘了哪些反模式:

  1. 全部采用GET
  2. 全部采用POST
  3. 忽视缓存
  4. 忽视响应代码
  5. 误用cookies
  6. 忘记超媒体
  7. 忽视MIME类型
  8. 破坏自描述性

下面我们来逐个详细说明。

全部采用GET

在许多人看来,REST仅仅意味着用HTTP暴露一些应用功能。HTTP GET是最重要的基本操作(operation )(严格地讲,用“动词(verb)”或“方法(method)”这样的术语比较好)。GET方法应当用于获取由URI标识的资源的一个表示 (representation),而许多(即便谈不上所有)现有的HTTP库和服务器编程API不是将URI视为一种资源标识符(resource identifier),而是将之视为一种传递参数的便利手段。这导致了以下这种URIs的出现:

http://example.com/some-api?method=deleteCustomer&id=1234

实际上,你无法根据构成URI的字符获知关于给定系统的“REST性(RESTfulness)”的任何信息,不过对于上面那个URI,我们可以判 断该 GET操作不是“安全的(safe)”——也就是说,调用者很可能要为结果(删除一个客户)负责,尽管规范里说在这种情况下使用GET方法是错误的。

这种做法唯一有利的方面在于它编程起来容易,而且在浏览器中调试也简单——你只要把URI粘贴到浏览器地址栏里、然后调整一些“参数”就行了。这种反模式主要存在以下问题:

  1. URI没有被用作资源标识符,而是被用于传递操作及其参数了。
  2. HTTP方法(HTTP method)不一定跟语义相符。
  3. 这种链接一般不可加入书签。
  4. 有“爬虫”造成非预期副作用的风险。

注意:符合这一反模式的APIs没准最终碰巧符合REST原则。这里有个例子:

http://example.com/some-api?method=findCustomer&id=1234

这个URI是标识操作及其参数呢,还是标识一个资源呢?两种情况都有可能:它可以是一个完全合法的、可加入书签的URI;对它做GET操作也许是 “安全的 ”;它也许会根据Accept报头返回不同的格式,并支持复杂的缓存机制。在很多情况下,这将是偶然的。API经常在刚开始时采用这种方式来暴露一个“读 ”接口,但当开发者要增添“写”功能时就有问题了(因为你无法通过对上述URI做PUT操作来更新一个客户——开发者得构造另一个URI)。

全部采用POST

这一反模式跟前一个颇为相似,只不过这里用的是POST方法而已。POST除了携带一个URI,还携带一个实体主体(entity body)。一个典型的场景是:将单个URI作为POST请求的目标、通过发送不同的消息来表达不同的意图。实际上,SOAP 1.1 Web服务就是这样做的,它把HTTP当作一种“传输协议”来用。服务器根据SOAP消息(可能还包括一些WS-Addressing SOAP报头)决定做什么。

可能有人认为“全部采用POST”跟“全部采用GET”存在的问题完全一样,只是它更难用一些,而且不能利用缓存(甚至连偶尔的机会都没有),且无法支持书签。事实上,它并不是违反了哪条REST原则,而是根本忽视了REST原则。

忽视缓存

即使你按各个动词的原本意图来使用它们,你仍可以轻易禁止缓存机制。最简单的做法就是在你的HTTP响应里增加这样一个报头:

Cache-control: no-cache

这样可以禁止缓存机制发挥作用。当然,这也许正是你想要做的,然而通常这只是你的Web框架规定的一个缺省设置。不过,对高效的缓存与再验证 (caching and re-validation)的支持,是采用REST式HTTP的诸多关键优点之一。Sam Ruby表示,在判断是否符合REST原则时的一个关键问题就是“你支持ETag吗”? (ETag是HTTP 1.1里引入的一种机制,它允许客户端通过加密的校验和来验证一个被缓存的表示是否仍然有效)。要生成正确的报头,最简单的做法就是把这个任务交给一个“ 知道”怎样做的基础设施——例如通过在Web服务器(比如Apache HTTPD)的目录里生成一个文件。

当然,这也要涉及到客户端一方:你在为一个REST式服务实现程序客户端时,你应充分利用现有的缓存机制,以免每次都重新获取表示。例如,服务器也 许已经发出信息:初次返回的表示在600秒内都可被认为是“新的”(比方说因为后端系统每30分钟才轮询一次)。这样的话,短时间内重复请求同一信息就完 全没必要了。在客户端设置一个代理缓存(比如Squid)也许比自行构建相应逻辑更好。

HTTP的缓存机制强大而复杂;Mark Nottingham的《缓存指南(Cache Tutorial)》是一个很好的指南。

忽视响应代码

HTTP提供了一组丰富的应用级状态代码, 它们可用于应付不同场合,不过许多Web开发者对此并不知晓。大部分人对200(“OK”)、404(“Not found”)和500(“Internal server error”)这些状态代码是比较熟悉的。但除此以外还有很多其他状态代码,正确使用这些状态代码意味着客户端与服务器可以在一个具备较丰富语义的层次上 进行沟通。

例如,201(“Created”)响应代码表明已经创建了一个新的资源,其URI在Location响应报头里。409(“Conflict”) 告诉客户端存在冲突,比如随PUT请求发送的是基于老版本资源的数据。再如,412(“Precondition Failed”)表明服务器不能满足客户端的预期。

正确使用状态代码的另一方面涉及客户端:应该根据一种统一的总体方法对不同类别的状态代码(例如所有2xx段代码、所有5xx段代码)作不同处理——例如,即便客户端不具备处理特定代码的逻辑,但至少应把所有2xx段代码视为成功信号。

许多声称符合REST的应用仅仅返回200或500,甚至只返回200(并在响应实体主体里给出错误文本——SOAP就是这样的)。你要是愿意,可 以称之为“通过状态代码200传达错误”,但无论你觉得采用哪个术语好,假如你不利用HTTP状态代码丰富的应用语义,那么你将错失提高重用性、增强互操 作性和提升松耦合性的机会。

误用cookies

利用cookies来传播某个服务端会话状态的键(key)是另一种REST反模式。

Cookies表明肯定哪个地方不符合REST了。是这样吗?不;不一定。REST的关键思想之一是无状态性(statelessness)——不 是说一个服务器不能保存任何数据:倘若是资源状态(resource state)或客户端状态(client state),那是可以的。服务器不能保存的是会话状态(session state),因为那会造成可伸缩性、可靠性及耦合方面的问题。Cookies的最典型的用法是:保存一个跟“某个保存在服务端内存里的数据结构”相关联 的键(key)。这意味着,浏览器随各次请求发出去的cookie是被用于构建会话状态的。

如果一个cookie被用于保存一些“服务器不依赖于会话状态即可验证”的信息(比如认证令牌),那么这样的cookies是完全符合REST原则 的—— 不过有一点需要注意:如果有其他更为标准的方式来传递一则信息(比如放在URI里、放在某个标准报头里、或较少见地放在消息主体里),那就不应将之放在 cookie里。例如,按REST式HTTP的观点来使用HTTP认证就比较好。

忘记超媒体

最不易接受的REST思想就是标准的方法集合。REST理论并没有规定标准集合由哪些方法组成,它只是规定必须有一组适用于所有资源的方法集合。对 于 HTTP来说,这组集合是GET、PUT、POST和DELETE(至少起初是这样),你需要一定适应时间才能掌握如何将所有应用语义投射到这四个动词 上。但你一旦适应了,就可以开始运用这个REST的子集——一种基于Web的CRUD(Create、Read、Update、 Delete)架构——了。暴露这种反模式的应用不是真正的“非REST式”应用(假如存在这种事物的话),它们只是未能利用一个REST核心概念——“ 超媒体即应用状态引擎(hypermedia as the engine of application state)”。

超媒体(hypermedia)是一个把事物链接起来的概念,正是它造就了Web这个网——一个互联的资源集合,应用通过跟随链接从一个状态进入另一个状态。这听上去也许有点深奥,不过其实遵从这一原则是有正当理由的。

“忘记超媒体”反模式的首要表现就是:表示(representation)里缺少链接。尽管通常客户端可以根据一定的规则来构造URI,但是因为 服务器没有发送任何链接,所以客户端将无法跟随链接。一种较好的做法是:即支持构造URI,又支持跟随链接——这里的链接通常反映了下层数据模型中的关 系。但最好的情况是:客户端应该只需知道一个URI;其他URI(各个URI及其构造模式,如:各种查询字符串)应该通过超媒体(作为资源表示里的链接) 来传达。 Atom发布协议(Atom Publishing Protocol)就是一个好例子,它有一个服务文档(service documents)的概念,服务文档为它所描述的域内的各个集合提供具名元素(named elements)。最后,应用可能经历的状态迁移应该是动态传播的,客户端应该可以不用掌握多少知识就可以跟随它们。HTML就是一个好榜样,它包含足 够的信息,以便浏览器可以向用户提供一个完全动态的接口。

我本想增加一个“人类可读的URI”反模式的。但我没那么做,因为我跟其他人一样也喜欢可读的、好“篡改”的URI。但是当人们采用REST时,他 们经常浪费许多时间来讨论“正确的”URI设计,而忘记了超媒体方面。所以,我建议你不要花太多时间来寻找正确的URI设计(毕竟,它们只是字符串而 已),而是多花一些精力在表示里寻找提供链接的正确地方。

忽视MIME类型

HTTP有个内容协商(content negotiation)的概念,它允许客户端根据需要获取资源的不同表示(representations)。例如,一个资源也许有不同格式的表示(如 XML、JSON或YAML等)以便于用各种不同语言(如Java、JavaScript及Ruby)实现的消费者所使用。再如,一个资源可能即有面向人 类的PDF或JPEG版表示,又有“机器可读的”XML版表示。还有,一个资源可能同时支持v1.1版和v1.2版的自定义表示格式。不管怎样,也许可以 为“只有一个表示格式”找到理由,但这常常意味着丢掉某种机会。

显然,若一个服务能为更多未预见到的客户端所用(或重用)那更好。因此,依靠现有、预定义、广为人知的格式,要好过发明私有格式——这会导致本文讲述的最后一个反模式。

破坏自描述性

这种反模式是如此普遍,以至于几乎在每个、甚至那些由所谓的“REST狂热者们”(包括我在内)创建的REST应用里都可以看到:违反自描述性约束 (这一努力目标并不像人们最初想象的那样跟人工智能科幻小说有多大牵连)。理想情况下,一个消息(HTTP 请求或HTTP响应,包括报头与主体)应该包含足够信息,以便任何通用客户端、服务器或媒介(intermediary)能够处理它。例如,当你的浏览器 获取某个受保护资源的PDF表示(representation)时,你可以看到由标准达成的协定是如何起作用的:有些HTTP认证交换发生,可能会发生 一些缓存(caching)和/或再验证(revalidation),服务器发送的content-type报头(application/pdf)触发了你系统里注册的PDF阅读器,最后你得以在自己的屏幕上阅读该PDF。所有用户都可以用他们自己的基础设施来执行同样的请求。若服务器开发者另外增加一种内容类型,那么服务器的客户端(或服务的消费者)只需确保他们安装了正确的阅读器即可。

你要是发明自己的报头、格式或协议,那就一定程度上破坏了自描述性约束。极端地讲,所有没有被某个标准化组织官方标准化的东西都违反此约束,因而可 被认为符合本反模式。在实践中,你应努力做到尽可能遵循标准,并懂得“某些协定可能只在一个较小的领域(比方说,你的服务和客户端是专门针对它开发的)中 适用” 的道理。

总结

自从“四人组(Gang of Four)”出版了书籍、 掀起模式运动的开端以来,许多人误解了它,并试图在尽可能多的场合下应用模式——这已被其他人所取笑。模式应当仅在符合上下文时才被应用。同样地,可能有 人会不遗余力地在所有场合下虔诚地努力避免所有反模式。许多时候,你有充分理由违反某一规则,或者按REST的术语放松某一约束。这么做是没问题的——但 了解实际情况、作出知情决策是有益的。

但愿本文能有助于你在开始首个REST项目时避免落入这些常见的陷阱。

非常感谢Javier Botana和Burkhard Neppert对本文初稿的反馈。

Stefan Tilkov是InfoQ SOA社区的首席编辑,以及位于德国/瑞士的innoQ公司的合伙人、首席顾问和主要的REST狂热主义者。

查看英文原文:REST Anti-Patterns

Tagged with:
preload preload preload