豪翔天下

Change My World by Program

0%

其实最先写这篇读后感我是拒绝的,因为关于健康的书看多了,感觉都差不多,但当我回过头来翻看的时候,发现这本书有很多的观点都是需要深深体会的。

作者Joe Kutner本就是一位运动员和健身教练出身的程序员,所以对程序员的健康问题有深入的了解,也在这方面进行了大量的实践和研究,最后以程序员的思维来写作这本书。所以在图灵教育上,这本书也是挺火的。

饮食

书中引用马克吐温的话:“保持身体健康的唯一办法,就是吃点你不想吃的,喝点你不想喝的,以及做点你不愿做的事情。”

相信很多人都和我一样,小时候很多东西不愿意吃就坚决不吃,挑食,只吃自己爱吃的,由于我父母在教育方式上存在一些瑕疵,只要我说不想吃的,基本上一次过后就再也不会做那些菜了,以致现在全家人的口味都差不多了,而且菜的种类都比较少。长大后偶尔会吃到以前讨厌的菜,虽然仍然有点儿难以下咽,但都知道了,那些东西吃了确实对自己身体比较好,然后妈妈就会问:你不是不喜欢吃这个吗,怎么现在要吃了。始终,父母是爱我们的,只是,在饮食上,前20年我们几乎不能自己做主,之后的生活一定要注意,我也喜欢尝尝不同的东西。

能让我们有饱腹感又不会产生多余能量的食物:蛋白质、全谷类食品。

运动

我的运动比较单调,我喜欢散步,喜欢慢跑,基本上每周会跑三四次,所以现在在运动上我到没有什么了,只是可能动作上有一些不符合规范,长期以往,对身体可能会造成伤害,所以需要研究一下这个。

硬件

办公桌、健身器材,我应该马上就能过上自己想要的生活(独立、经济自由),所以马上我就得为这些东西考虑了。

关于眼睛的保护,对于每天面对几个小时电脑的程序员来说,隐形眼睛完全不合适,防辐射眼睛,可能会有作用,购买没有过度炫光的显示器和减少显示屏色温(减少蓝色光)。

通过我上个月一下减10斤的经验,只有持之以恒,饮食规律,才是最好的减肥方式。

此书和刘同两年前的《谁的青春不迷茫》的风格不同,此书通过几十个身边的小人物来展现人生各个时期的孤独,以独有的价值观去从普通人不一样的角度看问题。或许是我刚开始谈恋爱,所以感觉突然忘了以前的那种孤独感,即使是有朋友也会有一个人的孤独。以前我一直想,要看自己是不是一个孤独的人,就要看自己一个人行走在安静或嘈杂的环境下能否进入自己的内心而不被外界干扰。

现在玩儿的最好的一堆朋友就是初中的那群朋友,大概有十个左右,我们每年过年都会聚餐,不只一次,如果可以,寒假每天都会一起上街吃烧烤,这样的日子每年都会有,我到不担心会失去,因为家乡那个小镇,逛过去逛过来都是这几个朋友。初识孤独的感觉大概是从高中开始,和初中朋友分开过后,我独自一人跑到隔壁县去上学,每个月只能和他们见一次,我高中的时候最喜欢一个人跑到公园的池边看往来的人群,那时候的孤独,不是没朋友,而是,能说心里话的人都不在身边。那时候很流行一句话:“越长大越孤单”。是啊,我们渐渐长大,很多朋友都因为空间的隔离而渐行渐远,曾经的朋友会因为各自新的朋友的不同而渐渐产生隔阂,虽然朋友一生一起走,那些日子不再有,但一声朋友,就绝对是一辈子的事。

今年大三,暑假就开始实习了,这是迈向未来生活重要的一步,也是以后生活的开端。一直都很憧憬,以后所有朋友都在身边的场景,正如本书所说:“在一个毫无生机的城市里,有一群朋友最大的好处就是,随时随地能够为任何一个理由团聚庆功、畅想未来。”那样的感觉肯定很好,和他们在夜市里唱歌,遥想未来,每个月拿着微薄的工资也能每天开开心心快快乐乐的,那绝对是人生最美好的时光。

其实我现在还处于“为赋新词强说愁”的状态,呵呵,人生,很精彩,未来很美好,尽力成为我能成为的人吧。很庆幸,二十几岁了,我还在为梦想奋斗。

经典语录:

也许能力不够,所以至今不能真正满足自己内心的愿望。也许足够幼稚,所以至今仍会用这一招骗骗自己。

还记得十年前那个期待见识这个世界的少年吗?你还认得出这是你十年后想成为的那个风尘仆仆的大叔吗?

当初你不愿听的歌,总有一天会为一个人而听。当初你不愿品尝的食物,总有一天会为一个人去品尝。对于你,也一定会有一个人愿意陪你看你想看的电影,去所有你想去的地方,看所有你写过的日记。你不爱人,人不爱你,不是报应,只是时间问题。

我们没有成为我们曾以为的,我们成为了我们能成为的。

在一个毫无生机的城市里,有一群朋友最大的好处就是,随时随地能够为任何一个理由团聚庆功、畅想未来。

所有因为某人而让自己生气的事情,一定要说出来。不说的话,自己越想就越生气。说出来之后,自己踏实了,对方就会变得不踏实。如果心里因人不爽,最好的办法就是说出来告诉对方。一来自己不会再纠结,二来可以让对方纠结,三来如果对方并不因此纠结,就证明对方压根儿不在意你,那你又何必要为不在意你的人影响自己的心情。有话就说的人不是直肠子,而是不会让自己辛苦的透明人。

一个男人的帅来自于他的性格,一个男人的魅力来自于他的自知,一个男人的强大来自于他对自己的苟刻。

你的过去我来不及参与,你的未来我奉陪到底。

你以为做的一切都是为了身边最亲近的人,后来你才知道最亲近的人最需要你做的只是你在身边。

大多数人不会在同一个地方工作一辈子,大多数人也不会在同一个岗位做一辈子,我们所有的累积都是为了给人生最后的那个位置打一个稳定的根基,所以每个获取经验的机会都显得尤为重要。如果所有人工作时间都一样,工作质量拼的就是纯粹的智商和情商,你看了看自己在镜子中的样子——完全没有任何一点男一号的气质啊,不在后天努力,就只能成为这出人生剧中的路人甲乙丙丁了。

这本书是我最好的一个朋友给我推荐的,在我们眼里他一直是哲学家。

之前以为,像这种书名顶多就会像某些心灵鸡汤一样,叫我们该怎么做,不该怎么做。但刚看到第一章“没有任何向导”的时候,我就震惊了,当时就意识到,这绝对是一本不可多得的好书。绝对只有到达某种境界的人才能看懂。当完全拜读完此书后我真的懵了,我不知道该怎么形容他了,好多好多,我根本看不懂,不是像看技术书籍那种看不懂,而是你一想书中蕴涵的哲理的时候你就感觉头脑发热,完全是一种“懵”的状态。

此书原名叫“Freedom From the Known”,当时看到这种翻译也是想了很久,后来发现,结合书中的内容,确实,翻译为“重新认识你自己”或许能更让人理解。它一步一步地让你从你的世界观中挣脱,获得自由,获得新生。对于我这样一个还在象牙塔里的少年郎来说,连世界都没有观过,哪儿来的世界观呢。我知道的还太少,我的人生经历还太少,所以我认为,这本书我还不适合看。

人生有三种境界,看山是山,看山不是山,看山还是山。我肯定还属于第一种。

再看王国维的人生三境界:

昨夜西风凋碧树。独上高楼,望尽天涯路。
衣带渐宽终不悔,为伊消得人憔悴。
众里寻他千百度,蓦然回首,那人却在,灯火阑珊处。
这样看来,我还是在第一境界里游走。

总之,等等吧,等我有足够阅历了再回头看这本书,到那时,肯定会有不一样的理解。那时的我肯定是一个不一样的我。当然,我首先得认识我自己,当然不是一点一点累积与自己有关的知识,去学习那些能够让我更深刻认识自己的工具。

语录:

多少世纪以来,我们被我们的老师、尊长、书本和圣人用汤匙喂大。我们总是说:“请告诉我,那高原、深山及大地的背后是什么?”我们总是满足于他人的描绘,这表示我们其实是活在别人的言论中,活得既肤浅又空虚,因此我们充其量只是“二手货”人类。我们活在别人口中的世界,不是受制于自己的个性和倾向,便是受制于外在的情况和环境,因此我们只是环境的产物,我们不再新鲜,我们从没有为自己发现过什么东西,我们的心中没有什么东西是原创的、清新的和明澈的。

认识自己便是智慧的开端

如果你说你要慢慢地学习认识自己,一点一滴地累积,这表示你并不在认识目前的你,你只是在累积有关自己的知识罢了。

你必须由衷地想去了解一件事物,才会付出全部的心力去觉察它。

所谓“活在当下”,就是在刹那间领会其中的美及喜悦,而不是眷恋它所带来的快感。

凡是不断追逐快感的心,无可避免终将面对它的阴影及痛苦。

该为恐惧负责的就是念头,道理就是这么简单呐,你不妨亲自观察一下。当你正在专心应付某种危机时,你并没有恐惧,等到念头一起,恐惧才由心生。

你一旦认清自己就是恐惧,和恐惧无二无别,自然会停止所有的斗争,然后恐惧就会完全止息下来。

只有停止比较,才能使自性呈现,能够活在自性中,才能有真正的平安。

自由乃是一种心智状态,它不是从某种东西挣脱的自由,而是一种自由的意识,一种可以怀疑和追问一切的自由,它强烈、活跃而富有生气,因此能清除各式各样的依赖、奴役、臣服及逆来顺受的阴影。

随心所欲而不逾矩

如果你只裴阳你的孩子适应社会,那就是在训练他们如何斗争,那么他们就会被社会摘个。如果你真的爱你的孩子,怎么还会鼓励他们加入这场人间的苦战?

真正好好看过日出、日落或湖面月色的人寥寥无几

观念永远属于过去,而行动却属于现在,生活也是属于现在的。

念头跑来跑去并不是问题,让自己觉察每个念头的动向,才是关键所在。

说说本书

这本书可以说是每一个互联网爱好者的必读书籍,尤其是那些想在互联网界大显身手的人。这不是单纯的心灵鸡汤,而是一本史书,一本不仅仅陈述基本事实,还道出几十年来腥风血雨中的不变规律。它给了你一个直观的感受,让你仿佛身临其境,短短几天就体会到互联网诞生至今的那些潮起潮落,而是否能踏上下一波浪潮,还得看你自己的造化。

《浪潮之巅》点燃了很多人创业的灵感,也点燃了我奋斗的激情,每次看到这种关于互联网的鸿篇巨著,我就庆幸自己当初选择了这个行业,并热爱上这个行业。在互联网,要踏上浪潮之巅,很容易,也很不容易,这本书同样也削减了一些人的锐气,互联网的路上,一不小心,便会永世不得超生,它每天都在千变万化,我们要更加脚踏实地。

或许,正如书中所说,不是时势造英雄,恰好是英雄创造了时势。

据作者吴军介绍,这本书很多都是当年发表在谷歌黑板报上的文章,我之前没看过,但我知道,也只有吴军这样的经历才能站在那样的高度审时度势,酿造这本史诗。(另外,有不少读者说此书存在许多细节错误,这些东西我觉得没必要去计较,毕竟,我们不是学历史…)

说说互联网公司

这本书有上下两册,上册主要讲互联网大公司的兴衰,下册则主要讲互联网的本质。从AT&T、IBM、摩托罗拉、Google、Apple这些大牌公司中发现,一个企业能有发展,基因是决定性作用。我也曾一直在观察着,比如Google,我也一直找不到一个准确的词语来形容我的发现,后来发现了“基因”这个词,我才恍然顿悟,这不就是企业基因吗?它伴随着企业诞生,也是企业能否踏上浪潮之巅的关键所在。

我想,我以后所在的公司,不看它有多壮大,而更看它是否适合我,是否是我想要的公司。(这句话并不代表我有多大的选择的余地,只是,这种公司肯定会有很多的)

说说我最喜欢的Google

我接触互联网比较晚,没有见证谷歌飞速发展的年代,我刚开始使用谷歌的时候,就正好碰上它离开某国的时候,作为一个愤青,自然对它多了一份喜爱。

我看互联网公司,主要是看该公司的所作所为。Don’t be evil!这是谷歌的格言,我想,谷歌或许还是做过一些对不起用户的事的,但是它依然在做着很多好事,这才是真正以用户为中心的公司,踏上浪潮之巅也是自然而然的事情了。国内的一些公司也一样,七牛、Segmentfault等新兴的互联网公司也是深受大众的喜爱。

自由、开放、分享,永远都是互联网的代名词

语录

任何梦想家都不足以成事,因为所有的成功者都是实干家

虽然说条条道路通罗马,但是成为罗马帝国的路只有一条,就看谁能找对了。

原文地址:http://movie.douban.com/review/2877890/

奈良鹿丸那段很经典的独白,恐怕是每个鹿丸迷都能背下来的:

“我本来想过着随便当个忍者,随便赚点钱……然后和不美又不丑的女人结婚,生两个小孩,第一个是女孩,第二个是男孩……等长女儿结婚,儿子也能够独当一面的时候,就从
忍者的工作退休……之后,每天过着下将棋或围棋的悠闲隐居生活……然后比自己的老婆还要早老死……我就是想过这种生活……”

鹿丸在《火影忍者》中本应是个不起眼的人物。模样不算帅,也不算丑;气质不算酷,也不算俗;武力不算强,也不算弱;出场不算少,也不算多。总之,不管从哪边算起,都不
是一个出头椽子。在木叶忍者的合影中,是一个拿放大镜才能找到的人。就是这样一个人物,在很多人气调查中,都排进了前五名。

鹿丸在《火影忍者》里有一个很特别的地方,就是他的人生观,也就是我们在上边引用的那一段。这个人生观既不高尚,也不低俗,却是鹿丸向往的,也是很多鹿丸迷喜欢他的重
要原因。

《火影忍者》这部动画片,一个重要课题就是,人生意义的追寻。几乎每场较大的战斗,敌我双方都会回顾生命的历程,探讨人生的意义。就像古雅典城里,哲学家们的论战一样
,人生观论战中输了的人,最终战斗也会输。《火影忍者》表面上看,是一场场忍者之间的对决;实际上,是一场场人生哲学的较量。就像TVB的时装剧一样,经常通过警察、
律师、厨师等特定职业,来探讨人生观;在《火影忍者》中,一个个忍者,就是一个个人生观的载体。很多忍者都背负着这个沉重的课题,甚至包括,以“食为天”的秋道丁次,
也曾经为生活的意义烦恼过。

鹿丸则不然,几乎没有和别人探讨过人生观的问题。因为他已经有了一个,不需要太大努力,就能实现的人生目标。在这个问题上,鹿丸并不困惑。

不像漩涡鸣人那样整天风风火火的,也不像宇智波佐助那样整天装帅耍酷,鹿丸始终给人一种从容的感觉。这种从容,来自于他对自己人生观的深信不疑。像鸣人、佐助、大蛇丸
那样,整天把人生观挂在嘴边的人,实际上,对自己的人生观并无十分把握;否则,就不会逢人便宣讲、证明自己的人生观。当然,也正是因为这样,他们才能成为主角人物,观
众在他们的矛盾和成长中,得到共鸣。

鹿丸另一个受欢迎之处,就是他给人的安全感。我们设想一下,一个由鹿丸带队的小组,和一个由鸣人带队的小组,显然前者更能给人安全感。这种安全感来自于鹿丸强烈的责任
感。在追回佐助的任务中,临出发的时候,鹿丸给队员们说了一段话:

“佐助跟我没有很深的交情,我也不喜欢这个人。但佐助也是木叶的忍者,是我们的同伴。所以我们要拼命把他救出来,这是我们木叶的风格。并且,虽然我的性格这样,但也不
会在这件事上怕麻烦。因为我的行为关系到你们的性命。”

说到责任感,就要说到鹿丸的另一个经典口头禅:

“真麻烦……”

对于责任,鹿丸是能躲就躲,即使是中忍考试这样“催人奋发”的大事,也是被鸣人一把推下看台,强行参加考试。从这一集的标题《云彩真是好啊……干劲zero的男人》,
即可以看出鹿丸的避世心态。

不过,避世不等于逃避责任。就像在追回佐助的任务中,临出发时,鹿丸给队员们说的那段话一样。鹿丸的嫌麻烦心态,意味着不愿意在没把握的情况下,轻率地承担责任;而一
旦承担了责任,就要信守承诺。

我们更常见的是,因为一时的激情,盲目承担下了工作、婚姻、朋友的责任。当激情过后,遇到困难时,便开始推三阻四,这才是俗人逃避责任的心态。

《世说新语》里有一个华歆和王朗的故事:

“华歆、王朗俱乘船避难,有一人欲依附,歆辄难之。朗曰:“幸尚宽,何为不可?”后贼追至,王欲舍所携人。歆曰:“本所以疑,正为此耳。
既已纳其自托,宁可以急相弃邪?”遂携拯如初。世以此定华、王之优劣。”

《谱叙》中也记载了华歆另外一件类似的事:

“歆少以高行显名。避西京之乱,与同志郑泰等六七人,间步出武关。道遇一丈夫独行,原得俱,皆哀欲许之。歆独曰:“不可。今已在危险之中,祸福患害,义犹一也。无故受
人,不知其义。既以受之,若有进退,可中弃乎!”众不忍,卒与俱行。此丈夫中道堕井,皆欲弃之。歆曰:“已与俱矣,弃之不义。”相率共还出之,而后别去。众乃大义之。

华歆能够在评估自己的实际情况后,作出正确决定,即这个责任承担不起。之后,这两个责任被王朗和郑泰等人强加在头上。既然承担了责任,就要承担到底,这是君子所为;而
王朗、郑泰之流,在这两件事上,只不过是“拍脑袋决策,拍胸脯保证,拍屁股就走”的俗人。

当第一天坐在新办公室的时候,当爱人偎依在自己胸膛的时候,当在酒桌上拍着胸脯对朋友说:“这事儿交给我”的时候,用《火影忍者》中的人生观来说,许下承诺的一刻,总
有一种“被认可”的快感。但不要忘了,这也意味着背负上了新的责任,很多时候,我们没有能力承担这个责任,或不愿意为此去努力,我们只想享受那一刻“被认可”的快感。

想想看,如果鹿丸像大蛇丸那样,完全没有责任感,只靠那不高尚,也不低俗的人生理想,很难产生如此强烈的人格魅力。

因此,鹿丸淡泊的人生观不是理想主义的写照,而是一个基于现实主义的理想。

喜欢鹿丸,就要像他那样,找到自己深信不疑的人生理想,并为自己所承担的责任而努力。

原文地址:阮一峰的网络日志

网络应用程序,分为前端和后端两个部分。当前的发展趋势,就是前端设备层出不穷(手机、平板、桌面电脑、其他专用设备……)。

因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信。这导致API构架的流行,甚至出现”API First“的设计思想。RESTful API是目前比较成熟的一套互联网应用程序的API设计理论。我以前写过一篇《理解RESTful架构》,探讨如何理解这个概念。

今天,我将介绍RESTfulAPI的设计细节,探讨如何设计一套合理、好用的API。我的主要参考了两篇文章(12)。

一、协议

API与用户的通信协议,总是使用HTTPs协议

二、域名

应该尽量将API部署在专用域名之下。

1
https://api.example.com

如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下。

1
https://example.org/api/

三、版本(Versioning)

应该将API的版本号放入URL。

1
https://api.example.com/v1/

另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。Github采用这种做法。

四、路径(Endpoint)

路径又称”终点”(endpoint),表示API的具体网址。

在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的”集合”(collection),所以API中的名词也应该使用复数。

举例来说,有一个API提供动物园(zoo)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样。

五、HTTP动词

对于资源的具体操作类型,由HTTP动词表示。

常用的HTTP动词有下面五个(括号里是对应的SQL命令)。

  • GET(SELECT):从服务器取出资源(一项或多项)。

  • POST(CREATE):在服务器新建一个资源。

    • PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。

    • PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。

    • DELETE(DELETE):从服务器删除资源。
      还有两个不常用的HTTP动词。

    • HEAD:获取资源的元数据。

    • OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。
      下面是一些例子。

    • GET /zoos:列出所有动物园

    • POST /zoos:新建一个动物园

    • GET /zoos/ID:获取某个指定动物园的信息

    • PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)

    • PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)

    • DELETE /zoos/ID:删除某个动物园

    • GET /zoos/ID/animals:列出某个指定动物园的所有动物

    • DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物

六、过滤信息(Filltering)

如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。

下面是一些常见的参数。

  • ?limit=10:指定返回记录的数量
  • ?offset=10:指定返回记录的开始位置。
    • ?page=2&per_page=100:指定第几页,以及每页的记录数。
    • ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
    • ?animal_type_id=1:指定筛选条件
      参数的设计允许存在冗余,即允许API路径和URL参数偶尔有重复。比如,GET /zoo/ID/animals 与 GET
      /animals?zoo_id=ID 的含义是相同的。

七、状态码(Status Codes)

服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的HTTP动词)。

  • 200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
  • 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
  • 202 Accepted - [_]:表示一个请求已经进入后台排队(异步任务)
  • 204 NO CONTENT - [DELETE]:用户删除数据成功。
  • 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
  • 401 Unauthorized - [_]:表示用户没有权限(令牌、用户名、密码错误)。
  • 403 Forbidden - [_] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
  • 404 NOT FOUND - [_]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
  • 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
  • 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
  • 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
  • 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
    状态码的完全列表参见这里

八、错误处理(Error handling)

如果状态码是4xx,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可。

1
2
3
{
error: "Invalid API key"
}

九、返回结果

针对不同操作,服务器向用户返回的结果应该符合以下规范。

  • GET /collection:返回资源对象的列表(数组)
  • GET /collection/resource:返回单个资源对象
    • POST /collection:返回新生成的资源对象
    • PUT /collection/resource:返回完整的资源对象
    • PATCH /collection/resource:返回完整的资源对象
    • DELETE /collection/resource:返回一个空文档

十、Hypermedia API

RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。

比如,当用户向api.example.com的根目录发出请求,会得到这样一个文档。

1
2
3
4
5
6
7
8
{
"link": {
"rel": "collection https://www.example.com/zoos",
"href": "https://api.example.com/zoos",
"title": "List of zoos",
"type": "application/vnd.yourformat+json"
}
}

上面代码表示,文档中有一个link属性,用户读取这个属性就知道下一步该调用什么API了。rel表示这个API与当前网址的关系(collection关系,并给出该collection的网址),href表示API的路径,title表示API的标题,type表示返回类型。

Hypermedia API的设计被称为HATEOAS。Github的API就是这种设计,访问api.github.com会得到一个所有可用API的网址列表。

1
2
3
4
5
{
"current_user_url": "https://api.github.com/user",
"authorizations_url": "https://api.github.com/authorizations",
// ...
}

从上面可以看到,如果想获取当前用户的信息,应该去访问api.github.com/user,然后就得到了下面结果。

1
2
3
4
{
"message": "Requires authentication",
"documentation_url": "https://developer.github.com/v3"
}

上面代码表示,服务器给出了提示信息,以及文档的网址。

十一、其他

(1)API的身份认证应该使用OAuth 2.0框架。

(2)服务器返回的数据格式,应该尽量使用JSON,避免使用XML。

(完)

扩展阅读

RESETful API 设计规范

微软的Rest API设计指南

个人总结

  • RESTful设计风格是仅仅针对API的设计,其他的,比如新建功能页面的url还是需要自己另外定义的,当然可以在后面直接加参数,比如GET /zoos?add=1

  • 对于文件的上传,无法使用application/json,而只能使用Multipart/form-data的方式

  • 如果我们要是用名称而不是ID来作为url的关键字,那么可能出现关键字与url重复的问题,例如/users/:username/cars/users/cars,这个例子不是很恰当,但是已经可以看出问题了,前者表示某个用户所拥有的车,后者表示属于所有人的车,但是如果有个人的名字就叫cars呢,就会出现设计上的错误。为了规避这种情况,最好的办法就是提取出几个关键字,应该尽量少,例如github就不能注册名为teams的账号,注册时就会提示这是一个保留字。这只是大多数情况,少数情况,资源并不完全属于我们,我们无法确定资源是否会占用保留字,那么这时候就只能添加特殊字符了,例如$,另外一个做法是使用下划线,例如/users/_regist

  • 有些人喜欢所有的接口的http状态码全部返回200,然后从返回的Json数据里面判断请求是否正常,理由却是统一管理返回数据格式,前端更好判断。我的理解是,这样完全不符合restful的设计规范。首先,无法保证请求永远返回200,所以,前端反而会多写一些判断;另外,如果按照请求错误的不同返回不同的http状态码,也是一种规范,因为http状态码对应的错误原因本身就是统一的;还有一点,对于日志监控来说,比如ELK这种自动分析日志的工具,当然是返回http状态码更好一点。

    这里还有另外一种将错误信息具体化的方法,就是在HTTP_CODE外,添加一个错误码头进行返回,例如HTTP_CODE=403X-status=4031可以表示用户密码错误等具体错误信息。另外HTTP_CODE其实是支持用小数进行扩展的,例如403表示禁止访问,那么403.1可以表示禁止可执行访问,403.2表示禁止读访问

  • 返回数据结构可以这样定义

    1
    2
    3
    4
    5
    {
    "code": "业务状态码",
    "message": "业务状态信息",
    "data": {} 或者 []
    }

其实Python3的字符串默认是unicode格式了,但utf-8并不能解决所有问题。首先,我们得在所有的文件前加上这样一句:

# -_- coding:utf-8 -_-
或者




# coding: utf-8

其次,就是注意一般的常见的编码格式,爬去某些奇葩的网页时可能会遇到的,这时候只需要使用对应的转换进行了,如果不知道网页的格式就只能一个一个猜了,常见的有

ASCII
GB18030
GB2312
GBK
UTF-8

直到上个月,我都还一直以为能使用个第三方库,想要什么功能去Google一下肯定能搜索到,这样就算是高手了。可是,最
,我还一直想,为什么即使是BAT这样的大公司也都问那些在实际开发中根本就用不到的网上一搜就一大片的东西,感觉他
事却让我意识到自己犯了一个多大的错。

在这里,我想把只会堆砌代码的程序员称呼为码农,当然不是贬低,而是确实这个词比较直观,比如当年给进城务工的人士
在我看来,内功包括三个方面:

熟练程度

这绝对不是一朝一夕就能简单掌握的,必须日复一日年复一年的写代码,才能达到所谓“熟练”的程度。不然,每次就像我之
甚至是很基础的语法问题都得去搜一下,然后,每次遇到问题都重复地去寻找答案,完全没有技术含量,可却从另一方面说明,你仅仅只是一个码农。

创造能力

我不鼓励重复造轮子,但你得保证,在没有轮子的时候能自己造一个出来。前阵子因为业务的需要,得破解一下某系统的验证码。结果去Google一下才让我大吃一惊,只发现了一个很古老的东西,pytesseract,是对Google Tesseract的一个简单的封装。可是使用起来却极其麻烦。没办法,只能计划着自己造,我以前跟着一位导师研究过一点AI方面的知识,知道这种验证码是可以实现很高识别就只能呵呵了。

系统架构

天地万物为我所用。程序员,垒砌代码,总得知道在哪儿垒吧。如果,能够自己设计系统架构,能够清楚明白每一种技术选型的利与弊,那样,一个完整的工程才真正属于你,否则,你永远只属于你那一方没人愿意去碰的基础的代码,而且,我总感觉,像这种重复性的劳动,总有一天会被更智能的东西取代。

当年,小米刚出来的时候,所有硬件都是出自别人之手,当时我很仰慕,能够集中所有最好的东西做出来一个产品,这样,应该很牛了吧。可后来发现,小米牛的不是这点,它也在造轮子,至少我认为小米系统,是国内最好的一个改装版android,很难想像,小米没有MIUI会是多么的脆弱。

内功这种东西,有没有最重要,用不用才是另一回事儿。不过,是有一些工作是只需要码农的,那就是外包,而且是低质量项目的外包。

转自:http://www.admin10000.com/document/5744.html

许很多人还不知道,知乎在规模上是仅次于百度贴吧和豆瓣的中文互联网最大的UGC(用户生成内容)社区。知乎创业三年来,从0开始,到现在已经有了100多台服务器。
目前知乎的注册用户超过了1100万,每个月有超过8000万人使用;网站每个月的PV超过2.2亿,差不多每秒钟的动态请求超过2500。

在ArchSummit北京2014大会上,知乎联合创始人兼 CTO
李申申带来了知乎创业三年多来的首次全面技术分享(幻灯片下载)。本文系根据演讲内容整理而成。

初期架构选型

在2010年10月真正开始动手做知乎这个产品时,包含李申申在内,最初只有两位工程师;到2010年12月份上线时,工程师是四个。

知乎的主力开发语言是Python。因为Python简单且强大,能够快速上手,开发效率高,而且社区活跃,团队成员也比较喜欢。

知乎使用的是Tornado框架。因为它支持异步,很适合做实时Comet应用,而且简单轻量,学习成本低,再就是有FriendFeed
的成熟案例,Facebook 的社区支持。知乎的产品有个特性,就是希望跟浏览器端建立一个长连接,便于实时推送Feed和通知,所以Tornado比较合适。

最初整个团队的精力全部放在产品功能的开发上,而其他方面,基本上能节约时间、能省的都用最简单的方法来解决,当然这在后期也带来了一些问题。

最初的想法是用云主机,节省成本。知乎的第一台服务器是512MB内存的Linode主机。但是网站上线后,内测受欢迎程度超出预期,很多用户反馈网站很慢。跨国网络
延迟比想象的要大,特别是国内的网络不均衡,全国各地用户访问的情况都不太一样。这个问题,再加上当时要做域名备案,知乎又回到了自己买机器找机房的老路上。

买了机器、找了机房之后又遇到了新的问题,服务经常宕掉。当时服务商的机器内存总是出问题,动不动就重启。终于有一次机器宕掉起不来了,这时知乎就做了Web和数据库
的高可用。创业就是这样一个情况,永远不知道明早醒来的时候会面临什么样的问题。

这是当时那个阶段的架构图,Web和数据库都做了主从。当时的图片服务托管在又拍云上。除了主从,为了性能更好还做了读写分离。为解决同步问题,又添加了一个
服务器来跑离线脚本,避免对线上服务造成响应延迟。另外,为改进内网的吞吐量延迟,还更换了设备,使整个内网的吞吐量翻了20倍。

在2011年上半年时,知乎对Redis已经很依赖。除了最开始的队列、搜索在用,后来像Cache也开始使用,单机存储成为瓶颈,所以引入了分片
同时做了一致性

知乎团队是一个很相信工具的团队,相信工具可以提升效率。工具其实是一个过程,工具并没有所谓的最好的工具,只有最适合的工具。而且它是在整个过程中,随着整
个状态的变化、环境的变化在不断发生变化的。知乎自己开发或使用过的工具包括Profiling(函数级追踪请求,分析调优)、Werkzeug(方便调试的工具)、
Puppet(配置管理)和Shipit(一键上线或回滚)等。

日志系统

知乎最初是邀请制的,2011年下半年,知乎上线了申请注册,没有邀请码的用户也可以通过填写一些资料申请注册知乎。用户量又上了一个台阶,这时就有了一些发
广告的账户,需要扫除广告。日志系统的需求提上日程。

这个日志系统必须支持分布式收集、集中存储、实时、可订阅和简单等特性。当时调研了一些开源系统,比如Scribe总体不错,但是不支持订阅。Kafka是Scala
开发的,但是团队在Scala方面积累较少,Flume也是类似,而且比较重。所以开发团队选择了自己开发一个日志系统——Kids(Kids Is Data
Stream)。顾名思义,Kids是用来汇集各种数据流的。

Kids参考了Scribe的思路。Kdis在每台服务器上可以配置成Agent或Server。Agent直接接受来自应用的消息,把消息汇集之后,可以打给下一个
Agent或者直接打给中心Server。订阅日志时,可以从Server上获取,也可以从中心节点的一些Agent上获取。

具体细节如下图所示:

知乎还基于Kids做了一个Web小工具(Kids Explorer),支持实时看线上日志,现在已经成为调试线上问题最主要的工具。

Kids已经开源,放到了Github上。

事件驱动的架构

知乎这个产品有一个特点,最早在添加一个答案后,后续的操作其实只有更新通知、更新动态。但是随着整个功能的增加,又多出了一些更新索引、更新计数、内容审查等操作,
后续操作五花八门。如果按照传统方式,维护逻辑会越来越庞大,维护性也会非常差。这种场景很适合事件驱动方式,所以开发团队对整个架构做了调整,做了事件驱动的架构。

这时首先需要的是一个消息队列,它应该可以获取到各种各样的事件,而且对一致性有很高的要求。针对这个需求,知乎开发了一个叫Sink的小工具。它拿到消息后,先做本
地的保存、持久化,然后再把消息分发出去。如果那台机器挂掉了,重启时可以完整恢复,确保消息不会丢失。然后它通过Miller开发框架,把消息放到任务队列。Sin
k更像是串行消息订阅服务,但任务需要并行化处理, Beanstalkd就派上了用场,由其对任务进行全周期管理。架构如下图所示:

举例而言,如果现在有用户回答了问题,首先系统会把问题写到MySQL里面,把消息塞到Sink,然后把问题返回给用户。Sink通过Miller把任务发给
Beanstalkd,Worker自己可以找到任务并处理。

最开始上线时,每秒钟有10个消息,然后有70个任务产生。现在每秒钟有100个事件,有1500个任务产生,就是通过现在的事件驱动架构支撑的。

页面渲染优化

知乎在2013年时每天有上百万的PV,页面渲染其实是计算密集型的,另外因为要获取数据,所以也有IO密集型的特点。这时开发团队就对页面进行了组件化,还升级了数
据获取机制。知乎按照整个页面组件树的结构,自上而下分层地获取数据,当上层的数据已经获取了,下层的数据就不需要再下去了,有几层基本上就有几次数据获取。

结合这个思路,知乎自己做了一套模板渲染开发框架——ZhihuNode。

经历了一系列改进之后,页面的性能大幅度提升。问题页面从500ms 减少到150ms,Feed页面从1s减少到600ms。

面向服务的架构(SOA)

随着知乎的功能越来越庞杂,整个系统也越来越大。知乎是怎么做的服务化呢?

首先需要一个最基本的RPC框架,RPC框架也经历了好几版演进。

第一版是Wish,它是一个严格定义序列化的模型。传输层用到了STP,这是自己写的很简单的传输协议,跑在TCP上。一开始用的还不错,因为一开始只写了一两个服务
。但是随着服务增多,一些问题开始出现,首先是ProtocolBuffer会 生成一些描述代码,很冗长,放到整个库里显得很丑陋。另外严格的定义使其不便使用。这
时有位工程师开发了新的RPC框架——Snow。它使用简单的JSON做数据序列化。但是松散的数据定义面对的问题是,比如说服务要去升级,要改写数据结构,很难知道
有哪几个服务在使用,也很难通知它们,往往错误就发生了。于是又出了第三个RPC框架,写RPC框架的工程师,希望结合前面两个框架的特点,首先保持Snow简单,其
次需要相对严格的序列化协议。这一版本引入了 Apache
Avro。同时加入了特别的机制,在传输层和序列化协议这一层都做成了可插拔的方式,既可以用JSON,也可以用Avro,传输层可以用STP,也可以用二进制协议。

再就是搭了一个服务注册发现,只需要简单的定义服务的名字就可以找到服务在哪台机器上。同时,知乎也有相应的调优的工具,基于Zipkin开发了自己的
Tracing系统。

按照调用关系,知乎的服务分成了3层:聚合层、内容层和基础层。按属性又可以分成3类:数据服务、逻辑服务和通道服务。数据服务主要是一些要做特殊数据类型的存储,比
如图片服务。逻辑服务更多的是CPU密集、计算密集的操作,比如答案格式的定义、解析等。通道服务的特点是没有存储,更多是做一个转发,比如说Sink。

这是引入服务化之后整体的架构。

Python,我最喜欢的语言。但是,在其强大的功能以及强制的编码格式背后,也会引来一大波的编码方面的困扰,所以依然得需要进行一些规范化。

注释

函数或者文档的注释使用三引号,结尾空一行

函数注释需要注明三个参数:Args(参数)、Return(返回值)和Raises(抛出的错误),例如:

def exampleFunc(one, two):
    """
    这里是函数的功能





Args:
    one: 参数一的注释
    two: 参数二的注释

Return:返回值的解释,如果返回值比较复杂,比如是一个json数据,那么还需要将返回的格式卸载这儿

Raises: 非必须
"""</pre>

** 类的注释**,依然得有一行文档字符串,若有共有属性,需要在注释处表名,例如:

class exampleClass(基类):
    """
    类的注释





Attributes:
    公有属性1: 解释
"""</pre>

** 文件注释:**一般包括了编码信息、版权、许可声明、模块头等信息,例如:

# coding = utf-8




# Copyright 2015 ........




"""
这里是模块头,用一行文字概括文件或模块或脚本的作用
"""

命名

module_name:模块
package_name:包
ClassName:类
method_name:方法
ExceptionName:错误
function_name:函数
GLOBAL_VAR_NAME:全局变量
function_parameter_name:函数参数
local_var_name:局部变量
has_或is_:定义布尔类型元素

空行

两个函数的定义之间空两行,而方法或者语句模块之间则只空一行

空格

二元操作符之间添加空格

其它

对于常字符串,Python可以使用小括号将行隐式地连接在一起而不用在每行末尾加上加号,例如:

a = (
    'wang'
    'hao'
)
print(a)




# 打印出来就是wanghao