2009年4月15日星期三

两个关于架构师的问题

《程序员》第100期(2009.04)最后一篇文章提到了两个关于架构师的问题:

1. 程序员如何成为好的架构师?
2.资浅架构师如何设计出好架构?

我也试着回答一下这两个问题。

1.通过大量的学习、思考、实践,才能成为好的架构师。你能叫出几个世界顶级架构师的名字?有没有听说过Parnas?你对他们的设计思想和作品有什么了解?你做了哪些思考?你进行了怎样的实践?

2.这个,基本上,很难。水平怎样看两点:一、坚持练了多久;二、练的方法对不对。好架构来自好的架构师,冰冻三尺,非一日之寒。

2009年4月14日星期二

“大”项目的关键是集成

一个朋友提到,他们的公司将clear case换成了git。而他的感觉是,由于git是分布式版本控制系统(DVCS),所以在几百人的分布式大项目中,如果弄不好,很快就会乱套。虽然有一个“主代码库”,但是可以想象,提交时的冲突会很多。

确实,Clear Case有很多先进的特征,我也很喜欢,除了它的价钱之外。但我认为,这里问题的关键是集成。

几百个人的分布式大项目,要让所有人的工作能够顺利集成在一起是一件不容易的事情。其中的难度早有定论:这些人需要沟通协作,而沟通时的不一致和冲突将耗费大量的时间和精力。所以,在大项目中,我们常常看到集成的工作量比编码的工作量要大,有时候甚至大得多。

开发人员多是一种类型的“大”项目,另一种类型的“大”项目是小团队,但复用了很多第三方的软件。这种类型的项目在开源软件中相当常见,比如Liferay就是一个例子。它使用了Velocity模板框架,提供与多种应用服务器的绑定,支持多种关系数据库后端,还支持第三方的CMS和用户管理。

这两种大项目,如何来实现集成?

据我所知,以前某些大公司的做法是,项目设置build manager或build team,专门负责集成构建。这样做的含义很清楚:集成工作量很大,我们要专派人手。

但现在业界的最佳实践是持续集成。

对于开发人员很多的项目,《持续集成》中介绍的一种集成方式或许可以解决他们的问题。设置两个Repositry,大家向第一个Repositry提交,如果提交后5分钟没有新的提交,就第一个Repositry上持续集成。如果集成失败,自动回退到上一次成功集成的状态;如果集成成功,将新提交的内容再提交到第二个Repositry。开发人员将在持续集成服务器上,看到自己的提交是否成功集成。也会在集成失败时收到通知。

(这个故事再次告诉我们:工具的价值小于过程的价值,过程的价值小于人的价值。人是改进过程和工具的决定因素。)

对于小团队大量复用的项目,持续集成仍是成败的关键。你可以在Liferay项目中看到大量使用Selenium自动化集成测试。

最近我独自一人开发程序时,也明显感到持续集成的重要性:我需要把一周、两周、一月、两月的工作集成在一起。也许,集成一直都比编码更重要吧。

日志设计

记日志是个技术活,需要经过认真的设计。

为什么要记日志?为了在某个时候以某种方式对日志进行分析。Tim Bray在《代码之美》的第4章中,用例子说明了如何分析他的Blog的访问日志,找出最受欢迎的10篇文章。

从本质上来说,日志记录了系统中发生的事件。我们应该将重要业务事件的处理记入日志,并通过记录事件ID,保持事件的可追踪性。

例如,在一个filter-pipe架构中,每一条信息都有一个ID,每一个filter对信息的处理(通过或过滤)都记入日志(What)。在需要时,还可以记下过滤的规则(Why)。由于日志会记录时间,我们就可以写一些分析程序/脚本,统计业务事件的发生情况和处理时间。又是5Ws and an H的思想。

在调试时,这种日志明显是有好处的。这是升级版的printf。在运营时,这为系统的审计追踪性提供了帮助。

如果日志输出能够转向,作为另一个应用的输入,那么我们就可以写一个实时日志分析程序了。你猜到了,这是SOA治理的思想。

唯一的担心是性能开销。设计师要根据具体情况做出折衷。

2009年4月12日星期日

Filter和Pipe是一种实用的架构

手上在写的程序需要不断抓取实时信息,然后根据既定的策略做出相应的反应。写着写着,我的程序就变成了经典的Filter-Pipe结构。

我设计了三个接口:InfoProvider,InfoConsumer,InfoFilter。InfoProvider有setInfoConsumer()方法,InfoConsumer有receiveInfo()方法,而InfoFilter是InfoConsumer和InfoProvider的结合。

另外,我还设计了一个InfoSource,它是InfoProvider,但它还有另外两个方法:start()和next()。start()方法的语义是源源不断地提供Info,直到最后提供null。next()则是单步提供Info。

然后,我利用Guice的实例绑定来组建这个处理管道。再用一些确定的数据来测试整个管道的功能是否正确。

根据SOA的思想,我为每个InfoProvider/InfoConsumer/InfoFilter组件设计了一些运行时监控功能。在开发时,可以利用这些功能来确定程序的正确性。在运行时,可以得知程序的实时运行信息。

如果某个Filter没有设置InfoConsumer,它可以在标准输出中输出Info。

很像Unix的管道吧?推荐一本书“Software Architecture: Perspectives On an Emerging Discipline” by Mary Shaw & David Garlan,其中提到了Filter-Pipe架构。

2009年4月11日星期六

7个习惯

上次在培训时,我的slide中出现了“以终为始”,主要是让学员能在培训之后继续与我保持联系,这样我就好知道他们是否“学到了知识,改变了行为,养成了习惯,改变了命运”。学员们对“以始为终”产生了共鸣,我一问,原来大家都集体培训过“高效能人士的7个习惯”了。

如果一个理论包含3点,那么它很好理解并记忆。例如:
训练动物的秘诀有3点:1、动物没有错;2、动物不愿做这个,你就让它做那个;3、动物做了你想让它做的,就给它奖励。(Tip:也适合“人”这种动物)
Sun的策略有3点:1、技术采用;2、商业跟进;3、处理好前二者的关系。

如果一个理论包含5点,努力一下也能记住。例如:
管理者的工作有5个方面:1、制定目标;2、分配资源;3、监督进度;4、执行奖惩;5、教育培训

如果一个理论有7点,就要采取分而治之的方法来记忆了。如Peter Coad的7项修练,可以分成(语数)(音体美)(情商)。又如高效能人士的7个习惯:(积极主动、以终为始、要事第一)(双赢思维、知已解彼、统合综效)(不断更新)

还有一种办法,就是记首字。如7层网络模型:物数网传会表应。围棋十诀:不入攻弃舍,逢慎动彼势。
不得贪胜。入界宜缓。攻彼顾我。弃子争先。舍小就大。
逢危须弃。慎勿轻速。动需相应。彼强自保。势孤取和。


2009年4月2日星期四

低配置机器上的开发环境

如果你有一个上网本,希望出差几天时也能偶尔写点程序。那么装点什么开发工具?
  • Mercurial HG:分布式版本控制系统。
  • JDK:写Java程序,没这个不行。可能还要装Java API doc。
  • vim:带行号显示、语法加亮的编辑器总要一个的。
  • Ant:经常要打ant clean test。
PS:编辑器还可以用Notepad++

怎样才能提高自己的能力?

一个朋友在MSN上问了我一个问题:怎样才能提高自己的建模能力?

子曰:“大哉问!”凡是练功升级的人,都在思考这个问题。一般来说,我们需要:学习,思考,实践。

  • 学习是摆在第一位的。“吾尝终日而思矣,不如不如须臾之所学也”。“三人行,必有我师焉。择其善者而从之,其不善者而改之。”要师从古人,师从外国人,师从周围的人。
  • 学习完了要自己思考。“学而不思则罔,思而不学则殆”。他人的观点纷繁复杂,有的甚至针锋相对。思考的目的就是在自己头脑中建立起一个自洽的知识体系,将新学到的知识与旧的知识融合,使之相互得到加强。如果一个人,以前对UML建模很有研究,后来又醉心于敏捷方法学,然而他不能将这二者很好地融合,那么他只能算是一个跟风者,就像那只过玉米地的猴子。我怀疑这些知识是否真正成为他的东西。
  • 接下来是实践,实践出真知。实践可以检验你的理解是否正确,即是否符合客观规律。“纸上得来终觉浅,绝知此事要躬行”。

以上是一般原则,是泛化。下面结合具体例子,讲一个特化。

学围棋的人,很关心怎样提高棋力的问题。我也请教过多人,总结下来有这样一些方法:

  • 做死活题。吴清源说:围棋最重要的是死活。然而下棋的目标却不是杀死对方的棋或自己做活。死活只是手段,赢棋是目标。不过你若“不知死活”,目标当然遥不可及。看高手下棋时,我觉得必死的棋,忽又活了;我觉得是一堵大厚势,不可能出事的棋,忽又变成了孤棋,最后大龙愤死。不由感叹:满盘尽是死活题。做死活题时,是学习,是思考,也是实践。
  • 打谱。在打谱中,你可以看到中国古棋凌厉的攻杀,秀策那看似平淡无奇却闪耀着万丈光芒的小尖,吴清源和木谷实对布局的新理解,武宫正树天马行空的宇宙流。打谱时,是学习和思考。再在实战中用出来,就是实践了。
  • 实战。没有实战不行的高手。高手是通过无数实战而长成的。实战有输有赢,但关键是要通过复盘,分析输赢的原因,从而提高棋艺。
  • 复盘。当你水平不行时,最好是请高水平的老师复盘,这样进步快。当你到达一定水平时,可以自己复盘或与对手一起复盘,摆出一些变化图,分析实战中决策的合理性。反思是最重要的一项实践。所有实践一律平等,但有些实践更平等。

坚持做到这几点,围棋水平一定蹭蹭地往上长。