Archive for December, 2004

当微操作遇上刺蛇海

Thursday, December 30th, 2004

StarCraft游戏初期,神族高级玩家一般喜欢在出了一两个狂热者就带上一个农民出发,利用优秀的微操作能力很可能推倒一些心理素质不太好的Player,尤其是对付虫族的小狗,如果操作得当,两个狂热者往往可以消灭掉6~8个小狗。然而这一战略如果用过了头,比如,在刺蛇海面前,再优秀的微操作马上变得可笑。在一次国内的比赛中,我曾经看到过这样一场悲壮的比赛。

有一句话说得很对:先做正确的事,然后正确地做事。如果把大型项目比喻为刺蛇海,那么我们无论如何都不能在这样庞大的攻势面前傻乎乎的用某一两个“设计模式”、“PoEAA”或者“Core J2EE Patterns”这样的微操作。原因很简单,在业务架构尚不清晰的情况下,盲目的用小规模的技术组件来套用是愚蠢的做法。我经常听到不成熟的程序员这么在说:晤,这里可以用状态模式,嗯,那里可以用解释器模式。问问他是否真正明白业务的需求,他一脸茫然。当目标从一开始就错误的时候,再优雅的设计得到的顶多是一堆优雅的垃圾。

那么,正确的事是什么?是正确评估分析你的业务。业务架构是技术架构的基础,业务语义是技术语义存在的前提。这个问题之所以没有被得到重视,是因为我们现在做的大多数系统都还比较简单,我以前做过的项目基本上用事务脚本便可以解决,通过数据库的增删改查从而完成特定功能;在此基础之上建立了一系列技术组件,比如OA, 工作流,CMS。在分析项目的时候,将功能需求往已有的技术组件上套,然后用不太先进的技术完成了一个又一个的项目。因此我说,项目成功的保证一定不是所采用的技术,而是对业务的理解程度。

我们比较不幸。客户越来越成熟,对信息系统所能带来的生产力期望值越来越高(政府项目除外)。大量的旧的系统如电力,金融等,开始被迁移到J2EE平台。J2EE平台技术的成熟并不等同于业务的成熟,当一个系统膨胀到刺蛇海的规模时,当功能需求书堆起来一米多厚、功能错落有致、交叉相连时、就是这样也不足以描述需求时,那么技术方面的某些小小的微操作、模式就像是刺蛇海面前可怜的狂热者,潇洒却凄凉;又如同印尼海啸面前“坚固”的漂亮的海边别墅,不堪一击。在对这样大的项目进行分析的时候,业务是最重要的。将业务分析清楚才是正确的事,而不是上来就往J2EE N层模式上套。放之四海皆准的方案,往往可行性、操作性成问题。只有当业务分析清楚了,业务功能之间的联系也分析清楚了,怎么做就变成了很简单的事情:无论你怎么做,代码写的多么难看,只要完成功能,你做的事情都决不是Dirty work.

然而,业务分析也太艰难:当你面对一个具有十几个子系统、几千种交易、数百种工作流、子系统功能之间纵横交错的时候,没有业务知识和技术知识的双重修炼,这件事情无异于mission impossible. 这方面,我想才是自己需要修炼的一个方向。Raimundo同志正在进行这方面的研究,希望能够有所建树。

稍微有点高兴的是,目前我们接触到的项目大部分并不庞大,大部分都能够进行归类,比如简单的业务逻辑普通的增删改查就能完成,复杂一些的加上工作流支持;大一些的公司有能力对这些操作进行积累,称之为“技术组件”,因此某些以构件为核心的解决方案(公司)抢到了许多订单。从一段时间趋势来看,这种方式也是目前最可行的一种方式。

控制发散思维

Wednesday, December 22nd, 2004

深入开源世界的程序员的思维大多发散严重,这种发散在很多情况下是有害的。在制作一个新的产品/项目之前,很多人都会说,唔,你应该参考好的开源东西,把他直接使用。殊不知这样拿来就用伤害最大:因为自己根本没有机会仔细思考自己要做的东西是什么样子的。这就是Hibernate之所以创建EHCache的原因。在EHCache之前,已经有不少Cache实现,为什么没有直接使用?因为Hibernate自己都不知道Cache接口应该是什么样的。因此有了小小的简陋的EHCache, 正是有了这个小小的东西,其他Cache机制的集成才成为可能。因为Hibernate知道与外界集成要遵循的接口是什么。如果当初直接采用某一种Cache实现,恐怕就没有了现在灵活的Cache机制了。

(这种思维的方式同样可以推广,为什么小公司不愿意接受数额较大的融资,因为这样很容易将小公司原本不太清晰的发展观念冲垮,最后什么也不是。)

现在设计平台,发现陷入了这样一个怪圈:我总想将最新最好的开源产品集成到平台中,却忽略了Roadmap Feature的定义,也就是说,没有一个清晰的标尺来定义平台某一个版本应该包含那些特征,应该达到什么效果。这样做的后果是我陷入在一个又一个优秀的产品中,像上瘾的烟鬼拔不出来。在深邃的开源世界里,一切的一切都太又诱惑了:为了选定一种O/R映射方案,我比较了JDO的各种实现以及Hibernate,阅读了大量文档(广告?),最后还是回归到Hibernate; 为了选定一种Mock测试方案,我比较了EasyMock, jMock, 之前我从未用过Mock测试,现在我对EasyMock的机制已经相当清楚了;为了选定一种代码覆盖率工具,我比较了Clover, Jcoverage和Emma,最后选定了Jcoverage, 为了选择一种IoC容器,我比较了Spring和 HiveMind,最后选定Spring, 为了选定一种Web开发框架,我重新审视并比较了SpringMVC, WebWork, Struts, Tapestry.,最后选定了Tapestry。这个过程充满了感叹,也充满了诱惑性:很多具有相关性设计精美的项目会时不时招摇的在你眼前晃来晃去,让你忍不住看下去,然后你一个下午的光阴就耗费在从Google或者TSS或者JavaLobby一个链接开始而引入的一个深渊,留下你无法弥补的4个小时的时间。看着越来越近的Release Date, 心情越来越不爽。

因此,一旦前期调研结束,程序员应当果断的将与开源的联系一举切断,专心致志的投入到实现中去,一旦发现有可能抠出新的设计的地方,不要马上就找开源的产品,请先用自己的智慧设计一个能用哪怕是破败不堪的(好的设计是重构出来的,不是吗?)东西,先将框架搭建出来,一个迭代过后,开始重构,等到这个设计基本成型了,能够运行了,然后重新获得与OS的联系,参考同类产品,进行重构或者集成。这么做的目标是控制住发散的思维,在有限的时间内拿出一个在当前状态下最好的方案与实现,没有底线的项目/产品是个毫无意义的泡泡,脆弱,除了作为夸夸的谈资,经不起明眼人的一锥子。