共有103篇文章被收藏推荐
鲜果标签:
java
收录于2007-04-05
认领
报错
推荐
当读书成为一种常态,有一段时间不读书,自己就会觉得空虚。之前,空虚了一段时间,突然觉得对不起自己,于是,又开始新一轮的读书。老妈给了我一个还算好用的脑子,当我扔下书本,隔一段时间再捡起来,思维居然还有连续性。所以,我可以并行读几本书。
《费马大定理》,这是一本数学八卦,非常好看。数学,是一种美,非常严谨的美。当时报考大学的时侯,如果没有计算机专业的话,我很可能会去学数学,我喜欢数学的那种美,也喜欢问题成功解决那一瞬间的快感,就如同程序顺利运行的那一瞬给我的感觉。《费马大定理》讲述了费马大定理的证明过程,作者非常八卦的把证明前前后后涉及的种种人和事谈了一遍,完全就是一个数学发展史,远到毕达哥拉斯定理,近到椭圆方程。好书好译,让这书读起来异常流畅。读这本书时,有一种力量,牵引着我,让我不忍放下。上一本给我这种感觉的书是《达芬奇密码》。当然,由于这是一本跟数学相关的书,所以,其中会一些定理的简单推导过程,即便是作者解释得非常清晰,仍会有一丝障碍,“好读书,不求甚解”或许是最好的解决方案。
之所以会读《费马大定理》,主要是最近又对数学有了兴趣,而这个兴趣来自《什么是数学》。
如果一个数的各位数字之和能够被3(或9)整除,则这个数可以被3(或9)整除。
怎么样,勾起童年回忆了吧!《什么是数学》给出一个非常清晰的证明,让人一看便知。《什么是数学》算是一本科普读物,问题讲得行云流水一般,数学的严谨之美在这本书体现得非常明显。在我看来,当年学的数学知识只是一个个零散的点,而这本书把这些点串了起来,所以,很多原来不那么清楚的地方,似乎变得再清楚不过了。不过,这必竟不是小说,不可能那么一下子就完全理解,所以,慢慢来,好好读。
只有当认识问题到一定深度之后,才可能用浅显的方式讲出来,《什么是数学》如此,《万历十五年》也如此。
记得很小的时侯,老妈送给我一本像新华字典一样的小册子,里面有各种各样的知识,我对它爱不释手。其中,这本书的后半部份讲的是中国历史,这也形成了我对中国历史最初的认识。想来,对历史的兴趣和现在停留在脑子里面的历史知识,大多是来自那本小册子。
《万历十五年》,一本关于明朝历史的书。那些面孔严肃的教科书太不受人喜欢,于是,有了《明朝那些事儿》之类的文字出现。相比之下,《万历十五年》是一本居于二者之间的书,不似教材般刻板,不似明月般调侃。一位深刻洞察力的历史学家像讲故事一样讲历史,历史变得生动起来。在这本书里面,你会看到做人臣难,当皇帝也不容易;会看到政治的阴阳;会看到冰冻三尺非一日之寒;会看到那些我们印象中的那些忠臣,也符合“人非完人”的规律……
其实,这段时间并行读的书还有一些,但大多是一些技术书籍,这里已经聊了太多和技术相关的内容,所以,才会有了《闲杂书等》。
心急火燎的结果呢?下面的情景是否会让你有种似曾相识的感觉:
* 费了半天努力修改的bug,仔细想来,其实已经在需求明明白白写好了,只是开发时未曾注意到。
* 好容易写好的一段代码,还没来得及向别人炫耀,却发现原来一个好好的功能出了问题,更糟糕的是,根本看不出这两段代码有什么联系。
* 这个bug让你想骂人,因为它居然是其他人修改另一个bug引入的。
* 这个地方有人改过,不过,修改的代码解决的根本不是真正的问题。
* 客户要的是一个小功能,但是对我们来说,加入它无异于重写整个系统。
……
已经有无数人用无数的事实告诉我们,在软件开发中,要付出就趁早,越晚代价越大。当然,我们能看到的大多数例子是在开发的不同阶段,比如需求比开发便宜,开发比测试便宜,测试比维护便宜等等。其实,在开发之中,也是如此,新鲜出炉的代码绝对比那些陈年旧帐更容易修改,不信的话,找一段自己几个月前写的代码理解一下试试。
前面那些似曾相识的场景,多半都是“急”出来的。可现实是,我们需要在后期用更大的精力为前面的“急”买单,所以,为了不给未来的自己挖坑,我们不妨慢一些:
* 仔细了解一下需求,分析需求是不是合理,而不要低着头就开始堆代码。
* 给出一个解决方案时,考虑一下会对已有的代码造成怎样的影响,打破窗户容易,修补难。
* 多花点时间重构,代码上的臭味越到后期显得越刺激。
* 修改bug时,停下来想想什么才是真正的问题,治标不治本的方案只会让人重回梦境。
* 写测试吧!貌似的浪费会让你在后期遇到bug时感激涕零。
……
软件开发其实是一个跟复杂度做斗争的过程,从某种程度来说,复杂度会一直在增长,我们所能做的就是尽可能降低复杂度增长的速度。我曾经和一些朋友说过,前期所做的一切是让我们在后面有更大空间挥霍。慢下来,让我们有时间思考自己的每一步是否迈得是否稳当,稳当的行进,心里才踏实。
这里的慢,实际上,还是为了快,殊途同归。
我正在写的一个库,摆在我面前的是这样一段代码:
class CONSTANT_Utf8 < MyModule::String
size :type => :u2
define_type :constant_utf8
end
这里定义了一个类型,它定义了字符串类型,size的类型是u2,类型的名字叫constant_utf8。我翻遍了所有的代码,这个类型的名字(CONSTANT_Utf8)除了定义这里,根本没有人会用到。没有用的东西是否还有存在的价值,这是我面对它思考的问题,尽管这是我想当初费劲心力想出的名字。经过一番痛苦的思索,我打算把这段代码改成这样:
MyModule.Type.string(:constant_utf8, :size => {:type => :u2})
如此一来,那个完全没有必要存在的类名字便也烟消云散了。想清楚之后写代码还是容易的。
module MyModule
class << Type
...
def string(name, options)
type(name, MyModule::String, options)
end
def type(name, super_type, options)
klass = Class.new(super_type)
options.each {|key, value| klass.send(key, *value) }
define_type(name, klass)
end
end
end
于是,我兴致高昂把后面类似的代码用同样方法处理。突然,一个测试失败了,真正的问题在这段代码:
MyModule::Type.struct(:constant_long, :u4 => :high_bytes, :u4 => :low_bytes)
经过分析,让这段代码失败的理由是,后面两项居然都用:u4做键值,于是原本是两项,传进hash之后,就只有一项了。于是,我的思路开始发散,加上括号,改hash为array……
结论是,没有哪个让我满意,不是实现不了,而是着实没有美感可言。不知道大脑中的哪个弦跳动了一下,既然在这个思路下,问题没法解决,我不妨换一个方式,于是,代码被改成了这样:
MyModule::Type.struct(:constant_long) do
u4 :high_bytes
u4 :low_bytes
end
如此一来,hash可能带来的冲突便不再存在了,而且,这和最初的用类定义形式上也更加接近,还有,这里也不用再为symbol点那个冒号了。当然实现也是要相应调整。
module MyModule
class << Type
...
def string(name, &block)
type(name, MyModule::String, &block)
end
def type(name, super_type, &block)
klass = Class.new(super_type)
klass.instance_eval(&block) if block_given?
define_type(name, klass)
end
end
end
前两天和胡凯聊天,我们发现公司里有一些更资深的技术人员,他们解决问题并不是通过操起兵器直接上阵,而是通过分析,提出另一种解决方案,从而原本的那个问题也就不是问题了。这里,我跳了两次,躲过命名和hash的烦恼。
Implementation Patterns
按照惯例,空闲的状态下,负责招聘的同事就会找上门来。在这个校园招聘如火如荼进行的时段,他们更是要充分利用“beach”上的每一个人。去年,我荣膺了公司的“Code Review Machine”,所以,当之无愧就成了他们找人的首选。这不,今天一口气做了14个Code Review。
我们的招聘环节中,有一个环节,就是让应聘开发角色的人去写代码,然后,我们会根据内部的标准对代码进行评审,这就是Code Review的由来。有兴趣的人,不妨搜搜,我知道,我们公司最近用的这几道题在网上都是可以找到的。其实,仔细一读便不难发现,这几道题并不是那种难到让人摸不到头脑的题。按照我当初应聘时,冰云给我的说法,两个小时就可以完全搞定。
或许你会疑问,如果试题不难,那如何区分应聘者的编码能力呢?事实上,仅仅完成功能是不够的。我们更多的是在看代码中展现出来的内容。
当然,我无意在这里讨论公司Code Review的标准。
之所以会想起写这个话题,完全是今天的代码看多了,好吧,找一些精采的部份分享在这里:
* 一个类的名字叫做A(我不记得我们的题里面有这样的概念……)
* 一个C#/Java程序只有一个文件(我们的题没有简单到只有一个概念吧?)
* 所有的方法都是static的(确定用的是OO语言?)
* 长长的方法(虽然鼠标有滚轮,看着也麻烦)
* 太多的switch..case(很勤劳,写那么多一样的switch都不嫌烦)
* 嵌套许多层(看来是用有自动格式化的工具了,要不然,打tab或是空格,自己就会觉得麻烦)
……
我曾经和同事开玩笑,我应该写一篇《ThoughtWorks应聘代码过关指南》,争取让自己在今后的Code Review过程中稍为舒服一些。
其实,ThoughtWorks所遵循的评审标准完全是业界公认的一些标准。所以,真正的《过关指南》已经有了,比如Martin Fowler用《重构》告诉我们什么是不好的代码,比如这篇blog开头列着的那两本书告诉你怎么写好代码。
如果这算泄密的话,那么就让我去评审更多的好代码,累累自己。
听着张惠妹的《解脱》,看着奥巴马当选美国总统的新闻。
对于政治,我不那么关心,对于奥巴马的当选,我看到的更多是一个美国梦的实现。和人说过,如果奥巴马当了总统,我就去买一本他的《无畏的希望》来读,看来要多读一本书了。当选的奥巴马经过了最初的喜悦,很快就会面对的更现实的问题:经济危机。经济危机,这个最初曾在初中政治课本上见识到的词,这一次迈着大步重回人间。
曾以为经济危机离自己很远,直到公司厨房里的零食开始减少,我才知道,原来,还是会有一些影响的。
今天下午,当我和几个同事正在热火朝天的讨论一个问题的时侯,忽然项目组召集开会。老大告诉我们一个坏消息,项目取消了!
原因很简单,在这个经济危机的冬日,客户准备扎紧腰带过苦日子了,所以,所有的项目都要取消了。比起厨房的零食,这次,经济危机的冲击更加直接。虽然老大说了很多,说我们这段时间的工作是有价值的,希望大家最后在把一些整理和收尾的工作做好。但散会后,大家的表现一目了然,刚还在为一个问题争论不已的我们,一下子失去了前进的动力。我们操起了放下好久的Wii,放肆的在“工作”时间打起了网球,甚至在其他人还在忙碌的时侯,一群人就奔向了KTV,准备引吭高歌一番。
对于我而言,听到“取消”的那一刻,我的思绪却飞回了六年前。
那时,我刚刚离开校门,还是一个干劲十足的毕业生。我放到了一个Java项目上,做的是一个彩信网关,那时侯,我们称之为多媒体短信(MMS)。这是我在职业路上真正意义的第一个项目,我不懂业务,不了解Java,不知道网关为何物。于是,我拼命的学着项目需要的各种各样的技术,写着尽可能有用的代码,也犯着初学者可能的各种各样的错误。还记得当时我是分配和一个在读研究生一起写协议,还有一个用于测试的客户端模拟器,他忙着写自己毕业论文,于是,我几乎一手包办了所有代码。当我的模拟器与我们的系统成功互通,我无比的满足。
在2003年新年到来之前,项目负责人宣布,项目取消了。当时的我,一下子就懵了,我拼命的回忆着自己到底做错了什么。现实是,这个彩信网关当时根本就没有需求,完全是部门领导拍脑门想出来的东西,当他们看到短时间之内不可能有真正的需求时,终止了这个项目。
那个飘雪的冬夜,项目负责人带着我们几个在一家朝鲜族饭店吃了散伙饭。
那之后,我知道,原来技术并不能决定一切。
时隔六年,现如今的我经历了很多,也能够更加坦然的面对同样的场景。项目死掉的直接原因通常与程序员无关,好程序员可以对一个项目的成功推波助澜,但却很难毁掉一个项目,放在大背静下更是如此。
冬天来了,春天还会远吗?


