依照惯例,我每年在元旦时候都会写一篇回顾,总结过去,展望未来。不过很少跟上一年指定的计划真正去比较,一般都是列举一下这一年做的事情。
大致分下来,可以分为上半年和下半年两部分,这当然不是废话。因为上半年和下半年分别在两个完全不同的项目上工作。
技术咨询项目 上半年在一个国内咨询项目上,主要做的事情有(其实我是作为前端专家加入的,不过后来工作重心发生了改变):
GIS平台 大数据平台 关于GIS最后的产出是一系列博客,而且还在InfoQ上发表了一篇。
而后来我又根据我iPhone上照片的经纬度信息,汇总出了一个热力图(使用QGis):
大数据相关的所有东西都在我的gist上,还没有时间整理。
硬件 回到办公室之后,发现了硬件小组提供的一大堆有意思的工具和器件,包括3D打印机,Arduino的一些芯片等,为了纪念我的GIS项目,我还打印了一个瓦片:
不断将我拖延了4年的机器小车组装了起来,而且还使用舵机,蓝牙,超声波等模块制作了一个实际的雷达:
Sessions & Workshop 5月底回到办公室后,我发现Office的气氛其实比我来的时候低落了很多,ThoughtWorks的感觉非常淡了。
一方面是新人太多,而来新的项目所在的11楼由于客户的关系(我自以为),同事们的积极性极低。一个最容易看到的信号就是Session变得很少,我尝试做一些改变。
分别做了一些关于自动化测试,JavaScript方面的Session和Workshop,下面是《可测试的JavaScript》的Workshop。这是我第一次组织比较大的,而且时间比较长的Workshop。
有了上一次的Feedback,在年底的时候,我又组织了一次为期3周的Workshop,受众更是扩大到了各种角色,包括BA,UX,UIDev,QA等等。
写作 今年的博客数量减少了,一个原因是我在编写我的第二本书《轻量级Web应用开发》,经过几个月的坚持和努力,这本书已经编写完成,应该会在明年(2015年)年初与读者见面。
另外,在休年假的时候(3周3页面之后),我将Workshop的内容做了整理,并加入了一些设计相关的内容,形成了一本电子书,名为《3 web designs in 3 weeks》。
其他 我正在努力的向UX角色的转变,所谓千里之行,始于足下。我在休年假期间,买了一大堆UX相关的书籍。目前正在努力学习画画:
在今天的CST的创新课上,我们一起设想了几个场景,下面是我自己画的图:
最后是一张我自己设计的自己的名片:
希望来年可以在自己努力的路上看到一些成果吧。
示例的需求描述 今天我们需要完成的需求是这样的:
对于一个给定的字符串,如果其中元音字母数目在整个字符串中的比例超过了30%,则将该元音字母替换成字符串mommy,额外的,在替换时,如果有连续的元音出现,则仅替换一次。
如果用实例化需求(Specification by Example)的方式来描述的话,需求可以转换成这样几条实例:
hmm经过处理之后,应该保持原状 she经过处理之后,应该被替换为shmommy hear经过处理之后,应该被替换为hmommyr 当然,也可以加入一些边界值的检测,比如包含数字,大小写混杂的场景来验证,不过我们暂时可以将这些场景抛开,而仅仅关注与TDD本身。
为什么选择这个奇怪的例子 我记得在学校的时候,最害怕看到的就是书上举的各种离生活很远的例子,比如国外的书籍经常举汽车的例子,有引擎,有面板,但是作为一个只是能看到街上跑的车的穷学生,实际无法理解其中的关联关系。
其实,另外一种令人不那么舒服的例子是那种纯粹为了示例而编写的例子,现实世界中可能永远都不可能见到这样的代码,比如我们今天用到的例子。
当然,这种纯粹的例子也有其存在的价值:在脱离开复杂的细节之后,尽量的让读者专注于某个方面,从而达到对某方面练习的目的。因为跟现实完全相关的例子往往会变得复杂,很容易让读者转而去考虑复杂性本身,而忽略了对实践/练习的思考。
TDD步骤 通常的描述中,TDD有三个步骤:
先编写一个测试,由于此时没有任何实现,因此测试会失败 编写实现,以最快,最简单的方式,此时测试会通过 查看实现/测试,有没有改进的余地,如果有的话就用重构的方式来优化,并在重构之后保证测试通过 它的好处显而易见:
时时关注于实现功能,这样不会跑偏 每个功能都有测试覆盖,一旦改错,就会有测试失败 重构时更有信心,不用怕破坏掉已有的功能 测试即文档,而且是不会过期的文档,因为一旦实现变化,相关测试就会失败 使用TDD,一个重要的实践是测试先行。其实在编写任何测试之前,更重要的一个步骤是任务分解(Tasking)。只有当任务分解到恰当的粒度,整个过程才可能变得比较顺畅。
回到我们的例子,我们在知道整个需求的前提下,如何进行任务分解呢?作为实现优先的程序员,很可能会考虑诸如空字符串,元音比例是否到达30%等功能。这当然没有孰是孰非的问题,不过当需求本身就很复杂的情况下,这种直接面向实现的方式可能会导致越走越偏,考虑的越来越复杂,而耗费了几个小时的设计之后发现没有任何的实际进度。
如果是采用TDD的方式,下面的方式是一种可能的任务分解:
输入一个非元音字符,并预期返回字符本身 输入一个元音,并预期返回mommy 输入一个元音超过30%的字符串,并预期元音被替换 输入一个元音超过30%,并且存在连续元音的字符串,并预期只被替换一次 当然,这个任务分解可能并不是最好的,但是是一个比较清晰的分解。
实践 第一个任务 在本文中,我们将使用JavaScript来完成该功能的编写,测试框架采用了Jasmine,这里有一个模板项目,使用它你可以快速的启动,并跟着本教程一起实践。
根据任务分解,我们编写的第一个测试是:
describe("mommify", function() { it("should return h when given h", function() { var expected = "h"; var result = mommify("h"); expect(result).toEqual(expected); }); }); 这个测试中有三行代码,这也是一般测试的标准写法,简称3A:
组织数据(Arrange) 执行需要被测的函数(Action) 验证结果(Assertion) 运行这个测试,此时由于还没有实现代码,因此Jasmine会报告失败。接下来我们用最快速的方法来编写实现,就目前来看,最简单的方式就是:...
ThoughtWorks好声音 ThoughtWorks好声音是一个聚合网站,内容来自众ThoughtWorker的博客,我们每周会汇聚一次,从众多的博客中挑选出一些P2(软件卓越)相关的主题,然后编为一辑,再分享出去。
但是从近100个博客中找P2相关的内容,这件事本身非常繁琐,如果每周都做这个重复劳动的话,那么软件卓越从何谈起呢?作为以解放人类为己任的程序员,我们绝对不能忍受纯体力的劳动。
获取博客地址列表 之前郑晔做了一个金数据的统计,请各位同事把自己的名字和博客地址登记在一个金数据的表单上:
接下来第一步就是把网页上的所有地址取下来,这一步很容易,从金数据的页面上用jQuery找到表格的第二列,然后将其中的文字取出来:
$("table tr td:nth-child(2)").map(function(key, item) { return $(item).text().trim(); }); 写到这里突发奇想,能不能用phantomjs去把这个动作自动化?
page.open(url, function (status) { if (status !== 'success') { console.log('Unable to access network'); } else { page.injectJs('jquery.js'); var links = page.evaluate(function() { return $("table tr td:nth-child(2)").map(function(key, value) { return $(value).text().trim(); }); }); var results = underscore(links).filter(function(item) { return item.length > 0; }).map(function(item) { if(!new RegExp('^(https|http)').test(item)) { return "http://" + item; } return item; }); } phantom....
总的来说,2013年收获颇丰,感谢同事们(特别鸣谢胡凯,张凯峰,以及RCA的各位同事)的帮助,我的第一本技术书籍JavaScript核心概念及实践在今年5月出版了。8月到10月,我和王磊,张久坤两位同事,和ThoughtWorks其他office的同事一起,在印度为来自世界各地的毕业生上了近两个月的课。12月从第一个项目上roll off下来,然后加入自己的第一个咨询项目。
在期间还去西电给学生讲过一次session,接受了CSDN的一次采访,本来打算赶10月份的校园招聘去学校讲点东西,后来由于出差耽搁了。但是感谢王欢给了我一个在郑大晔校上课的机会,我们每周六会对准ThoughtWorker们讲一些软件开发得session(TDD, Refactor, Pair Programming等)。
总之,2013过的充实而紧张,希望来年能更加的充实,也希望可以跟大家分享更多的有意思的session和博客。
在TWU(ThoughtWorks University) 当老师 2013年,最大的收获,应该是自己对于压力的新的认识。有一回和胡凯聊压力这个事儿,我说我自己是认可平时带着些压力去学习、工作的,胡凯的看法则是不应该是“带着些”,而是带着最大的压力。他给我举了个游泳的例子,说你在岸边是学不会的,只有被被人踢到水里,才有可能学会。
我觉得挺有道理,8月去印度参加TWU,当然有很多困难了,比如语言问题本身;和其他国家来的trainer一起交流的问题;给一群来自世界各地的学生用英文上课的问题;我周五从项目上下来,周六飞去印度普内,周日早上到达休息了半天,然后周三就要给其他国家的trainer用英文讲一个关于社会公正的演讲,而且形式限定在pecha kucha上,在这种压力下,我不止一次的后悔为什么把自己逼的这么紧?我的真实想法是把胡凯踢到水里学游泳,我自己回西安的项目继续每天做story。
但是周三过去了,我的演讲虽然也不至于震惊四座,但是不论是英文,还是主题,还是演讲技巧本身,都得到了比较正常的feedback。我存活了下来!
如果说这个小范围的,面向trainer的,带有彩排性质的演讲的压力值为100的话,那么下一周,面对着二十多个来自世界各地的毕业生,给他们讲一个关于如何给别人feedback的session,压力值至少为500+。即使是来自墨尔本、伦敦、巴西的trainer都开始表情凝重的备课,我自己的心情就更不用说了。还有人开导我说,不论你有多紧张,坐在底下的那些家伙都比你紧张100倍。
我清楚的记得,第一天结束后,我们互相击掌,还去酒吧喝了一杯来庆祝,当然,8点就赶紧撤回住处,准备第二天的session了,但是不管怎样,我又一次的存活下来了!
压力,必须压到自己要放弃,要退缩的那种程度,才能收获最多。一咬牙过去了,就海阔天空,进入一个新境界了。很多时候,自己总会给自己找很多借口,然后自己就把自己荒废了。李仲轩老人讲,练拳也一样,有人一听说有捷径,有了贼心,就不会出功夫了。
练拳 我虽然不能算是“自幼喜欢舞刀弄枪”,但是也一直对武术比较感兴趣,只是没有耐心去吃苦练而已。小时候只是跟父亲学过一点小擒拿之类,后来从家中找到一本《少林罗汉十八手》,自学未果,倒是记得一些招式的名字,如巧纫针,披身捶,僧推门,僧伏虎之类。2006年,看到了《逝去的武林》后,对内家拳产生了浓厚的兴趣,但是苦于没有老师,倒是我的兄长在石家庄,近水楼台先得月,找到一位教授他练习形意拳的老师,我跟着站了几天三体式,学了个劈拳和崩拳。
但是我自己也知道,那跟没练是一样的,练外行都骗不了。
2007年暑假,我跟李林京老师在石家庄学过一段时间的意拳。但是开学之后回到昆明,就开始三天打鱼两天撒网,后来干脆练网也撤了,借口是内家拳练习得有老师,不然十分危险,一旦受伤则后患无穷。武林盛传“练拳容易改拳难”,一旦练错,再来纠正就非常困难,不如不练。
毕业之后,就再也没有练过,但是见过高山,也知道其中的一些窍要,就是不困下功夫练,今年年初开始感觉颈椎不舒服,上班也感觉挺累的,就又开始站站桩休息脊椎。结果一周之内,隐疾全消,而且渐渐觉得精神比以前好一些了,然后就一直坚持站桩,技击桩怕练偏,就站平步桩。
截止今天为止,除了7月份去伦敦的飞机上没站以外(下了飞机赶到酒店赶紧补上),每天都在站。夏天有一次和同事分享任忠信先生的形意拳,有人怀疑是假的,我给他们试了下,虽然没有搭手即飞,发人丈外那么神奇,但是吓吓外行的效果已经有了。
明年一定要抽时间去石家庄找李老师好好学习一段时间。练拳不但在身体上可以让人强健,而且在精神上也有很多的好处。
其实传统武术,最重要的是锻炼脊椎,腰杆挺直之后,内力渐生,丹田气满之后自然中气充足,精神也会变好,再加上老是有一种别人打不过你的优势,自然容易产生自信(大不了打一架嘛,咱不怯)。蔡元培当年说过,要文明其精神,野蛮其体魄,就是这个意思。
项目 今年的12月中旬,我从RCA项目上正式Roll off,从2012年4月加入ThoughtWorks之后,就一直在这个项目上。在这个项目上主要关注在软件交付上,和所有的BAU项目一样,在RCA,能学到一个成熟的框架是怎么实实在在运行的,从开发,测试,仿真,生产环境都是通的,如果有心的话,可以接触到自动部署,负载均衡,数据库的主备配置,各级缓存等生产上才会遇到的问题,但是很多时候又会比较无聊,因为可能更多的是在做老代码的维护,bug的修复,新功能的开发可能较少。
RCA总的来说,有经验的人居多,所以交付压力来说要小一些,而且带新人方面也没有太大压力。所以时间长了,大家都会觉得有点疲。我们会定期举行CBS(Come Build Something),或者CSS(Come Share Something)这样的活动来刺激一下。我们团队上一般有8个人,每次CBS都是有3-4个ideas,然后结对去做,虽然不会产出什么划时代/跨世纪的产品,但是每次也都会有一些产出。可惜在坚持方面做的并不好。从项目上Roll off的当天,团队送我了一本书《人与神话》(据说排在程序员谎称读过的经典书籍排行榜的榜首,不过实话实说,当时非常感动,谢谢我们team和我并肩作战近两年的同事+朋友):
从项目上roll off之后,加入了西安本地的一个咨询项目,以前端工程师的身份加入,新项目的人对前端开发的经验相对来说都比较少,但是有很强烈的学习愿望,而且动力也很足。新项目本身做起来也比较有意思,各种前端的比较现代的技术(测试,本地构建,CI),框架(AngularJS, Jasmine)都可以很好的进行实践。
刚开始的时候,也是压力巨大,但是咬牙挺过前三天之后,就容易多了。单元在新的一年,可以和新的团队一起将这个项目做好。
旅游 年初和老婆去了次厦门,纯粹度假的方式,无计划,无目的,在鼓浪屿上住了两天:
7月份,我和学海兄参加了欧洲的AwayDay,本来准备讲一个关于轻量级web应用开发的session,但是后来由于session太多,我的就被cancel了。
在印度正好赶上印度的AwayDay:
在普内周边的一个古堡上: