白巧克力融化
September 28th, 2008
他年轻的时候没有人能防住他,除了他自己没有人能看清楚他的运球,除了他自己没有人知道下一秒他会做什么;当球在他手上时,你要做的就是睁大双眼,然后尖叫。
现在已经不太有人知道了…大学时候我的床头一直贴他的海报,我一直穿国王的球衣,还会在半夜时戴着手套练胯下运球,而且至今还会偶尔做一个突破中的脑后传球。
最后一个把背后传球、不看人传球和长距离击地传球当常规武器用的NBA球员。最后一个像本能一样做脑后传球的NBA球员。最后一个以华丽、匪夷所思和玩弄对手为至高目标的NBA球员。
向曾经的白巧克力,以及那些曾经或者仍然固执着不被职业篮球改变的伟大球员们,致敬。
[LINK]敏捷与精益: 中国软件的发展之路
September 26th, 2008
最近在计算机世界发表了 一篇文章
中国应该追求并效仿印度的软件公司吗,比如把它们的组织结构和做事方式都照搬过来?这里的建议是”不”。印度的软件业建立在外包业务的基础上,而中国软件企业有一个更为广大的内需市场。相比用完全可预测的提前计划来保护自己的既得利益,中国更为重要的应该是为快速发展的中国经济提供适应变化的IT支持,从而创造更大的价值。正在日益发展壮大的中国软件公司应该拥抱敏捷的开发方法和精益管理的行事方式以及一种不同于以往的软件开发者能力模型。笔者相信,通过采用敏捷与精益,这些公司将有能力更快速地交付低成本、高客户满意度的软件产品,并在市场上凸显出中国公司的与众不同。这也是一条可以同印度软件公司竞争的发展之路。
重构模式:用异步计算替代长计算
September 23rd, 2008
问题
当一个JavaScript计算进程耗时太长,浏览器会弹出警告框,不仅烦人而且一不小心就会点错导致后面的程序不被执行。
很多这类长计算是由于操作大数组造成的。虽然每个元素的处理耗时很少,当数组有几百上千个元素时整个计算时间就会长到超时。由于数组元素数不确定,对单一元素操作调优仍然不能根本解决问题。
办法
把长计算拆解成多个异步的短计算。
即使计算所需的总时间并不缩短,将阻塞的长计算拆解成异步的短计算至少带来响应性的提升:在计算进行的同时用户还可以做其他操作,而不是眼看着整个浏览器失去响应。
在拆解的基础上可以改进任务分发机制以提升整体计算时间。
步骤
- 重构原来的长计算
- 把整个长计算抽取到一个方法中
- 重构该方法使之呈现以下结构:
function longCalculation() {
before();
var items = getItems();
items.each(handleSingleItem);
after();
}
- 把循环重构为递归
- 把“操作数组中所有元素”的逻辑抽取到一个递归调用的方法,使之呈现以下结构:
function handleItems(items, cur) {
if(cur == items.length - 1) {
after();
return;
}
var item = items[cur];
handleSingleItem(item);
handleItems(items, cur + 1);
}
function longCalculation() {
before();
var items = getItems();
handleItems(items, 0);
}
- 把针对每个元素的操作变成一个异步的计算进程──这一步很简单,只要在调用handleItems方法时始终加上delay就行。
以上。应该很容易写出一个类似于library的玩意来封装这个模式。太容易了以至于我不想写。
Starwood Footprint
September 19th, 2008
受到Andy的鼓励,也来贴footprint
Revision: 4203 +----------------------+-------+-------+---------+---------+-----+-------+ | Name | Lines | LOC | Classes | Methods | M/C | LOC/M | +----------------------+-------+-------+---------+---------+-----+-------+ | Controllers | 1922 | 1600 | 35 | 232 | 6 | 4 | | Helpers | 1451 | 1210 | 8 | 206 | 25 | 3 | | Models | 4337 | 3555 | 63 | 567 | 9 | 4 | | Libraries | 2786 | 2317 | 37 | 233 | 6 | 7 | | Model specs | 6689 | 5536 | 1 | 3 | 3 | 1843 | | Controller specs | 5216 | 4355 | 0 | 7 | 0 | 620 | | Helper specs | 939 | 765 | 0 | 1 | 0 | 763 | | Library specs | 2744 | 2262 | 1 | 7 | 7 | 321 | +----------------------+-------+-------+---------+---------+-----+-------+ | Total | 26084 | 21600 | 145 | 1256 | 8 | 15 | +----------------------+-------+-------+---------+---------+-----+-------+ Code LOC: 8682 Test LOC: 12918 Code to Test Ratio: 1:1.5
正如Andy说的,4月到9月,trunk上共计约2400次commit。按照平均4个pair来算,每个pair每天提交6次。
除去统计失准的rspec部分,功能代码共计8682行,1238个方法,平均每个方法7行。测试代码是功能代码的1.5倍。
考虑到 Ruby on Rails 作为特别擅长开发web应用的框架所具备的强大表现力,以及对重复代码的低容忍,再加上stats所统计的只是Ruby代码(不包括HTML、JavaScript等代码),我毫不怀疑这个系统的复杂度能够等量于很多十万行代码级别的系统。
而重要的是,这个团队里的每个developer了解系统的每个角落──至少是能够在相当短的时间内通过阅读功能代码和测试来了解。每天6次的提交频率就是明证。
所以,作为总结,是一个值得骄傲的项目。
从持续集成开始,你怕啥呢?
September 19th, 2008
鼠标说,很多人认为 敏捷从持续集成开始 ,于是就 有人害怕了 。
人家说,你们搞这贸贸然的就持续集成,不行的。
1、认清真正的敏捷通过学习和调研,认清什么是真正的敏捷。如果一些基本初始概念就错了,那么在后续的推行中必然会差之毫厘、谬之千里,真正的敏捷实施也就无从谈起。
2、预估推行敏捷的收益
在确认知道什么是真正敏捷的前提下,对自己团队、组织的现状、问题和薄弱环节进行评估,设定改进目标,并预估敏捷能否解决这些问题,带来潜在的改进。如果成功的把握小于 50% 或者现状已经足够好,就不要推行敏捷,何必劳民伤财呢。
有意思啊。弄不清什么是“真正的敏捷”,“现状已经足够好”,就不需要改进了?就不要解决问题了?
怕啥呢?怕的就是这持续集成它是实打实的东西吧。怕的就是持续集成一上,所有的问题都以测试是红是绿这么截然的方式暴露出来,逼着不得不解决吧。怕的就是持续集成它没有放之四海而皆准的套话可以讲,build脚本得一点点写出来吧。怕的就是没人跟您玩“学习和调研”了吧。怕的就是“真正的敏捷实施”卖不掉了吧。
作为一个专门帮人解决问题的,我越来越频繁的说,我不在乎敏捷不敏捷。你告诉我,你有什么问题,咱们一起来看看怎么解决。可能一个项目做到最后你还是不搞敏捷,没关系,我解决你的问题提高你的效率就行。
ThoughtWorks 是一个做实事的公司,所以我们认为每个项目应该做的第一件事就是让真正的软件开口说话,说出它有什么问题,然后我们来解决问题。难怪有人要怕呢。光顾着解决问题,那学习和调研基本初始概念的事可扔到哪儿去了呢?
怕是又动了谁的奶酪了吧。
南戴河,中秋
September 18th, 2008
唯一值得重复的
September 11th, 2008
重复是软件开发中最大的阻力,没有之一。
重复是邪恶的。我是说,邪恶的!
永远不要为同一份信息保存两份拷贝。
DRY 是写出良好代码的根本原则。
(如果这个世界上有一些信息值得被重复的话,就是这些。)
螺狮壳里做道场
September 7th, 2008
以前闲得没事的时候想过在MSN上做插件,结论是那玩意它就不是正常人能玩的。
Spark 是一个开源的IM客户端,并且据说特别适合企事业单位办公用…其实就是对插件支持比较好的意思吧。插件都是用Swing来写的,API也很简单。做一个JFrame往里一扔就搞定了。
(还有 Openfire 也是他们家做的。配置简单使用方便,不错不错的说…)
自己跟自己聊天几分钟以后决定做一个浏览器嵌在Spark里面这样就可以一边聊天一边看网页(唔唔,很有追求)。JDIC 它对Mac OS X支持就有问题,搞了两小时还是不行,于是换方向。Lobo 是纯Java的浏览器然则对JavaScript的支持只有这种程度的浏览器它是没办法实用的。JRex 貌似从05年以后就没有更新鸟。至于Gecko Embedding …这个,未免太高科技了吧…
于是最终来到了 MozSwing 。稍微花了一点时间配置,它还是效果粉不错的亚~~这里有个 WebStart 可以试用一下,还有 一篇blog 介绍怎么玩,来自 LimeWire 的作者,显然他们也借用了一把,呵呵。
其实粉简单,总共就三句话:
MozillaPanel mozilla = new MozillaPanel();
someSwingContainer.add(mozilla);
mozilla.load("http://limewire.com");
下一个目标,把Groovy给搞进来玩玩。
原来,好照片都是P出来的
September 6th, 2008
享受代码之美
September 4th, 2008
(本文系 《代码之美》 的推荐序)
“希望写出漂亮代码的开发者可以向艺术家们学习一些东西。画家常常放下手中的画笔,然后远离画布一段距离,围着它转一转,翘起脑袋,斜着看看,再从不同的角度看看,在不同的光线下看看。在寻求美的过程中,他们需要设计这样一些视角并使它们融为一体。如果你的画布是个集成开发环境(IDE)而你的媒介就是代码,想一想,你如何做到离开画布一段距离,用挑剔的眼光从不同的视角来审视你的作品?──这将使你成为一个更优秀的程序员,并帮你写出美丽的代码。”
写这段话的Alberto Savoia在他的文章里真的没有讲什么令人敬畏的高技术或是大架构,他讲的是每个计算机系的大二学生都熟悉的二分查找。所以Savoia真的是在讲如何写出漂亮的代码,所以才选择了这么一个所有人都清楚得不能再清楚的例子。你会觉得这种事情都是些不谙世事的小程序员才会热衷于干的吧?可这位Savoia却是从Google离职以后开创了Agitar Software公司(http://www.agitar.com/)的不折不扣的创业者。有意思吗?一个胡须花白、在这个行业里厮混了数十年、拥有自己公司的老家伙,还在乐此不疲地谈论“漂亮的代码”。
这本《代码之美》就是由三十多篇像这样有意思的文章组成的。像Brian Kernighan、Tim Bray、Charles Petzold、Douglas Schmidt、Yukihiro Matsumoto这样的名字,你甚至很难想象他们同时出现在同一本书上。或许也只有“漂亮的代码”这样的话题才能激起他们共同的兴趣。于是就有了这本了不起的书:从正则表达式匹配器到图像处理,从通信到基因排序,这些可能是世界上最优秀的程序员毫不吝啬地向读者展示:不论面对什么问题、使用什么语言,代码的美感都是始终存在的,而且这种美感应该是程序员毕其一生不懈追寻的。
作为《重构》的译者,不时有人会问我一些关于重构的问题,其中一个问题让我最感为难:为什么要这样做?真的,如果不是要修改代码,也不是要添加功能,为什么要把这段代码抽取出来呢?让每个方法都保持5行以内的长度到底有什么好处呢?这种时候与其说是有什么利弊权衡,毋宁说就是为了让代码“更漂亮”。当然了,在大部分时间里,软件开发是一项集合了科学、工程和服务的工作,但──至少在我们的内心深处──它多少还有那么一点艺术的成分。除了完成任务以外让自己手上的代码更具美感,也算是对自己作为程序员的梦想的小小坚持吧。
所以,既然你已经拿起了这本书,就暂时放开那些功利的目标吧──别误会,这可不是一本没用的书,通过阅读这些“高手”们的编程心得,对自己的能力提升就算不能立竿见影至少也有潜移默化之功。但那也只是装珍珠的盒子而已。在一个安静的周末,给自己泡上一杯清茶,跟着三十三位顶尖高手畅游在代码世界,在他们的指引下遍赏代码之美,这才是作为一个程序员最大的享受呢。



