Code 2011

成功人士是不写总结的,所以我来写个总结。

今年的coding从ABAP开始,这个很多人现在不知道以后也不用知道最好永远也不要知道的语言和他的平台,是一个脱胎于Pascal,在发展过程里又杂糅了SQL和C++的怪物,最后几乎变成了满屏幕关键字。再加上缺乏文档,实在是一段不堪回首的记忆。

3月份开始,我又重新开始了一个python项目叫做jip,他兼容maven,可以与virtualenv和setuptools集成,帮助你解决jython项目的java依赖,简化jython项目的发布,提高工作效率。这个小工具倾注了我不少时间,如果你某一天要和jython打交道的话,可以试试看。

今年还尝试了coffeescript,它恰到好处地消除了javascript里一些ugly的部分,大大提高了编码速度。我用它改写了网站首页的js

6月份我又重拾起1年前的javascript库heatcanvas,和lbt05协作完善了程序。通过HTML5的Web worker API改善了渲染canvas时的用户体验,增加了对Google Maps,OpenLayers,Baidu Map以及Leaflet的支持。这个项目的介绍被顶到hackernews的首页,这是一种前所未有的感觉。

7月份开始迎来了一个重大的转折。断断续续学习了一年半的clojure,终于开始写第一个库,reddit.clj,用clojure封装reddit网站的API。通过这个入口算是真正走进了clojure的世界,七月底reddit.clj基本完成之后我开始写他的第一个应用,rageviewer。这是个clojure的web项目,借着这个契机又接触了compojure和ring。而且写rageviewer的时候恰逢clojurescript公开,一不做二不休,于是这个项目就成了一个full stack的clojure项目:前后端都是clojure。最后rageviewer部署在当时刚刚开始邀请测试的cloudfoundry上。

8月参加了在上海的cn-clojure列表第一次聚会后,我开始用clojure克隆一个已有的并不复杂的程序,当时选择了beanstalkd,一个轻量级的task queue。这个项目取名为clojalk。最后它成功地支持了beanstalkd协议的所有命令,支持了通过Write-ahead log做持久化和恢复。这个项目用到了aleph,见识了一把clojure思维下的网络编程。

另外我还帮clojure-control写了一个leiningen的插件,现在这个插件已经合并到clojure-control项目里了。clojure能有这么快的发展,leiningen作为构建工具也有很大的帮助。就好比上半年做jip时,感受到jython的小世界里就没有一个好的方案来同时解决java和python的项目管理问题,而且人们也不重视这个问题。

年底还有一个clojure RPC框架的诞生,这个项目叫做slacker。项目还没有到总结的时候,我的org file列表上还有一长串的TODO。

总得来说,我觉得今年学习clojure的这个过程很有借鉴价值。对于一个新语言新平台新生态系统,如何入门并且getting real。你可以从一个功能简单的库开始,比如包装一个网站的API,或者(对于clojure来说),包装一个已有的java的库。在完成之后,利用这个库,写一个web应用,进而去了解这个平台上的web开发。再下一步,可以去克隆一个其他平台上的项目,规模不要太大。如此循序渐进,学习的效果很不错。另外,无论做了什么,只要是有用的,就应该说出来,这不仅是自我鼓励,有时候也能找到志同道合的朋友一起参与。

最后除了clojure之外,今年还接着gnome-shell的发布和更新,接触了gnome-shell的gjs扩展开发。又是一个不堪回首的平台,也许是还没有finalize吧,没有任何文档,而且一个平台上的库连变量拼写的风格都不一样!我是不会再浪费时间了,当然,以后的这个豆瓣电台的control还是会继续跟着gnome-shell的发布一直维护的。

除了上面提到的,今年还尝了一些groovy,common-lisp,甚至octave,不管怎么说都算是一个big year了。但愿明年能把这种状态保持下去,享受这种愉悦。

再见2011赛季

虽然还有两个月才能结束这个2011年,但是舜天队的赛季已经结束了。经过大半年的鏖战,大起大落之后,最终球队取得了史无前例的第四名,这让我们看了十多年次级联赛的球迷一时间几乎无法接受。今年赶在联赛开始前我换工作回到南京,去主场的机会也比以前上学或是在外地时多了很多,最终今年一共看了6个主场,是看球16年以来最多的一年。当然不出意外明年还要刷新这个纪录!

周三下午请假去球场目送了一下球队。距离明年开赛还有5个月,有一些球员可能转会,有的退役,所以每到最后一轮都是伤离别的时候。只是往年,这个时候都是夕阳西下,三三两两的观众看完无关紧要的比赛鸟兽散去;而今年的最后一轮,我们还为了理论上的一个亚冠机会争取。

2009年加入球队,2011年学习回来后,杨晨是舜天队的领队兼助理教练。在比赛开始前,作为助理教练要带领队员作热身活动。
resized-DSC_0017

队员训练。
resized-DSC_0011
前面两位是去年从降级的长沙金德转投而来的刘建业和任航,刘建业现在也是队里唯一的国脚。两人转会过来以后一直是球队的主力。刘建业负责中场的拦截防守;任航是边后卫,可以胜任左右两边,攻防俱佳。
跟在后面的时候杜文辉和李炽。杜文辉上赛季结束后被国安队清洗,自由转会来到舜天本来希望通过更多的出场机会能获得国家队的席位,结果不料第四轮就重伤缺席了后面的比赛。复出后球队已经更换了教练,不过杜文辉还是舜天队里技术顶尖的球员,经历了一番周折到了赛季末他还是占据了主力的位置。后面李炽是队龄最大的队员之一,2005年从广东来到江苏,伴随球队度过了最艰难的05、06、07年。升级之后,李炽一直在主力和替补之间徘徊,不过最后总能通过努力获得首发的机会。今年李炽合同到期,据说一条微博还让很多球迷以为下赛季他会回到广东,为此,有了这么一条横幅:
resized-DSC_0057

resized-DSC_0035
中间的9号陆博飞是球队的队长,在球场上的角色有点类似皮尔洛。今年陆队已经32岁了,不过据他昨天在广播里说他的状态还可以再踢两年。20号孙可是队里唯一一个能打上主力的由舜天梯队培养出来的队员,今年孙可也经历了最重要的一个赛季,基本上完成了从替补到主力的转换,在比赛中的作用也越来越重要。

罗马尼亚人达纳拉赫,这位仁兄上半赛季经历了漫长的进球荒,如果不是在场上特别积极,恐怕早就收拾东西走人了。好在从对陕西开和之后,状态越来越好,最终打进13球,在射手榜上排到了第三。
resized-DSC_0002

达纳拉赫的诡异爆发得益于身边空降了一名优秀的同伴,塞尔维亚红星队的耶夫迪奇夏季转会来到球队,是球队历史上身价最高的球员(140万美元)。身价在总体上当然还是和能力成正比的,耶夫迪奇半个赛季就打进11个球,是球队在场上最重要的球员。
resized-DSC_0005

后防线上,两个外援塔基耶夫(左)和埃雷尔森(右)。前者是乌兹别克国脚,他的哥哥和弟弟都曾经在天津泰达踢球。后者是球队的老面孔,埃雷尔森从09年就加入球队,一直是后防线上的定海神针,今年也是联赛中的最佳后卫。
resized-DSC_0097

守门员邓小飞也是09年加入球队,前半赛季一直是替补,后来成为主力之后发挥一直很出色,也是球队后半赛季辉煌的功臣。
resized-DSC_0013

resized-DSC_0050
替补席上的秘鲁外援略显落寞,因为在球队没有位置明年他将是唯一一名离队的外援,所以也有球迷专门给他感谢
resized-DSC_0054

resized-DSC_0066
resized-DSC_0071
resized-DSC_0067
resized-DSC_0086
resized-DSC_0099
resized-DSC_0079
比赛最终没有什么悬念地结束,虽然球队没有获得亚冠的名额,不过今年的成绩已经是18年历史上最佳排名。
resized-DSC_0105
球迷聚在场外放完烟火,约定明年再战!
resized-DSC_0127

Clojure Chinese User Group第一次线下聚会

今天下午赶到上海参加了clojure中文用户的第一次线下聚会,见到了国内clojure的的主要用户。感谢一直在努力组织这次活动的朋友,还有提供场地的朋友。

这是我关于clojure构建工具、生命周期管理的slides

欢迎对clojure感兴趣的朋友加入中文用户邮件列表,希望这样的聚会活动可以长期的办下去。

工作第二年

这个周末就是我正式工作两年的日子了,第二年过得稍微有些起伏,晚上写了一点总结。但是刚才读了一下觉得不太满意,也不太合适发出来。这样,即将跨入三年级的时候,我就改改风格谈谈愿望吧。

1. 把日常工作做好,积累技术,流程,项目管理的经验
2. 业余时间拓展周边领域的知识:数据挖掘,数据分析,可视化方面
3. 希望能主导去做成一点有始有终的事情
4. 希望不久的将来能参与一个志同道合齐心协力(self-motivated)的团队一起做好一个产品

最近的一些想法

最近有机会带着两个弟兄做一个老产品的技术改造。起因是测试发现产品的并发性很差,反馈回开发部门作下一个版本的改进。一查代码发现在网络通信时,原本异步的NIO,发送线程居然被强行加了wait同步等待远程返回。线程不能被释放,前端的请求被排队,吞吐量根本上不去。

这是root cause,其实进了代码里面的问题更多。于是产生了对这种feature driven development的怀疑。我曾经觉得列出 feature,做好代价估计,然后大家各自去实现的方式很理性很可控。如果宏观地看,黑盒地看,这种方式对项目管理很友好。但是最近看这种方式下开发出来的产品,问题还是很多的。当开发人员面对一个feature却缺少对产品整体架构的足够了解,他很容易倾向于用quick and dirty的方式\打补丁的方式解决问题,而忽略新feature对架构整体的挑战。长期下来,软件的功能不断演进,架构却停留在早期,维护成本越来越高,神秘的陷阱越来越多。这时,每次发布都要通过测试部门的蛮力测试,这个过程中除了修bug还要克服无数的invalid的bug。What the hell!!!

另一方面,从开发人员的角度,我认为Don’t repeat yourself是每个程序员必须牢记在心的编程行为准则。无论技术好坏,经验是否丰富,只要坚持这个原则,程序员总会趋向于做一些抽象做一些设计,我想是不会写出太让人发指的代码的。最近查看遗留代码,里面实在是太多copy/paste了。对新增的功能,甚至通过重载加copy/paste来实现。如果不能怀疑同事能力的话,只好认为这是工作态度问题了。管理者往往是不会看到这么细节的问题(其实是严重的问题)。

面对这样的系统,我最初的想法是通通推倒然后模块化。虽然考虑了工作量,可是尝试了一周还是发现老的基础根本无法剥离开,多年前的设计者根本就没有考虑模块化/解耦合的问题。有句话说得好: if you cannot split it, you cannot scale it. (对数据显而易见,对程序其实也一样)然而放弃这么大规模的久经考验的代码又不现实。这周开始又只好改变策略小步快跑,虽然不治本,但是就这个阶段来说,看到改造的效果对我们这个小组意义更大。这是在内心的洁癖和现实的局面间做的不难的取舍。

尽管困难重重,还是争取抓住这个机会能对自己有个提升。需要驱动弟兄们接受和实现自己的想法,和自个一个人闷头干是完全不同的。