Morning@Weblog

12/5/2005

出差后的恢复期

Filed under: — site admin @ 10:13 am

我的状态大概开始恢复了,对学习也开始重新焕发了热情。最近在看马大叔的PoEAA。老马不愧是个写作高手,这点不得不佩服。书将近看了一半,虽然是影印版,可前面的内容竟然也能让我看得津津有味,不时有感同身受的体会。

昨天终于把Michael同学的buffalo下载了下来,初步的看了一下,大致领会了精神,当然,对于我这个对JavaScript不甚精通的人而言,初读这样的JS代码还是有些别扭。不过之前粗粗的补过一点基本功,对于JS这个动态脚本语言的神奇之处也着实有了认识。我还找来了“JavaScript 2.0 Complete Reference”的电子版,打算过一阵有时间了翻上一翻。

前一阵在网上碰见孟岩,他问我现在是不是也也rubilized了,当时我纳闷于不知何意。后来他的解释才让我恍然大悟:现在搞Java,又做Web,还喜欢Agile的人,还有几个能置身Rails大潮之外?看来我是有些落伍了,虽然工作内容所限,不过还是打算将Rails纳入学习计划之列,触类旁通,好歹也能让我这个Agile fans不至于名不副实:D

出差两个月之后的状态恢复期

Filed under: — site admin @ 10:06 am

在外出差两个月,筋疲力尽,如今回到北京已将近一个月了,状态也逐渐开始恢复了。

最近在看马大叔的PoEAA。老马不愧是个写作高手,这点不得不佩服。书将近看了一半,虽然是影印版,可前面的内容竟然也能让我看得津津有味,不时有感同身受的体会。

昨天终于把Michael同学的buffalo下载了下来,初步的看了一下,大致领会了精神,当然,对于我这个对JavaScript不甚精通的人而言,初读这样的JS代码还是有些别扭。不过之前粗粗的补过一点基本功,对于JS这个动态脚本语言的神奇之处也着实有了新的认识。我还从网上找来了“JavaScript 2.0 Complete Reference”,打算过一阵有时间了翻上一翻。BTW:Michael兄对buffalo的宣传力度确实有些不足,今天在写blog时本想引用一下url,可baidu上怎么也搜不到了,真是奇怪我前几天怎么找到buffalo的下载地址的。并且,如果我没记错的话,好像buffalo的PageRank是2,还得加油啊。

前一阵在网上碰见孟岩,他问我现在是不是也rubilized了,当时我纳闷于不知何意。后来他的解释才让我恍然大悟:现在搞Java,又做Web,还喜欢Agile的人,还有几个能置身Rails大潮之外?看来我是有些落伍了,虽然工作内容所限,不过还是打算将Rails纳入学习计划之列,触类旁通,好歹也能让我这个Agile fans不至于名不副实:D

8/21/2005

一个task分配2-4个小时,可以吗?

Filed under: — site admin @ 12:56 pm

近日在BJUG的maillist里听到冰云在感慨“我们做agile的方法还不够细”。其实我感觉,要做到task的细粒度其实也不难,有时候只是大家的惯性思维在作怪。想想把一个任务划分到2小时内,那一定是相对单一而明确,且易于达成的。这也很符合控制理论:当自身控制力不够时,应该想办法通过任务分割的方式,将处理所需的控制成本降低。不过,我觉得这并不代表我们要将一个长周期的安排都细化到小时,原因有二:这本身也是要计入成本的,所谓“计划成本”;情况时常在变化,这么做反而落入了以往传统软工的“陷阱”了,与“over engineering”、“over design”如出一辙。

7/30/2005

Bad Smell,温故而知新

Filed under: — site admin @ 8:10 pm

前些天借着给新员工内培的机会向同事们推荐了老马的《重构》,今天顺便又重温了一下“Bad Smell”那一章,感觉依然还是很有收获的。重构的时机来源于“见识广博者的直觉”,比如:一个类中有多少实例变量才算太多,一个函数有多少行代码才算太长,而这种直觉是锻炼和培养出来的。想来偶尔在看同事代码时不免皱眉也是蛮有道理的,习惯成自然,看到Bad Smell就算没有“标明”,心里也会觉得不畅,总忍不住要把它改掉。老马《重构》一书的一大特色在于其技法的名称基本都可以“望文生义”,因此即使没有看过每个技法的详细说明,也已经基本能够猜个八九分了。从侯sir网站当下来的中文电子版开放了前六章,封底内页有一张Bad Smell与相应重构技法的对应表,准备将它打印出来贴到我的办公桌旁,作为时时提醒之用:)

[Bad Smell]
- Duplicated Code
- Long Method
- Large Class
- Long Parameter List
- Divergent Change
- Shortgun Surgery
- Feature Envy
- Data Clumps
- Primitive Obsession
- Switch Statements
- Parallel Inheritance Hierarchies
- Lazy Class
- Speculative Generality
- Temporary Field
- Message Chain
- Middle Man
- Inappropriate Intimacy
- Alternative Classes with Different Interfaces
- Incomplete Library Class
- Data Class
- Refused Bequest
- Comments

7/28/2005

重构、设计模式在团队协作中的作用

Filed under: — site admin @ 11:53 am

重构、好的编码习惯、设计模式的合理运用,作为开发者的基本功应该是一个持续修炼的过程,对于一个团队而言,在一定程度的掌握了这些技能之后,建立起了一定的语境,成员间的彼此技术交流就会变得更加畅快和有效率,一些分歧也会变少。大家不会因为争论一个设计或者一段代码是否合理而耗费很多无畏时间,也不会因为不合理的设计和代码而导致日后维护与更新的极度困难。并且,作为开发者来讲,个人也会从不断进步之中体会到工作的乐趣,而不是在重复单调乏味的Copy & Paste过程中逐渐消磨了自我。

6/27/2005

爱心拯救程序员王俊

Filed under: — site admin @ 10:09 am

祝福后山,早日康复。这里是本次活动的官方网站。

6/24/2005

Sitemesh Tutorial(2)

Filed under: — site admin @ 2:18 pm

sitemesh中decorate pattern的匹配规则

查看sitemesh的PathMapper代码可以知,在解析decorates.xml文件时,sitemesh对url pattern的匹配分为三类:精确匹配,模糊匹配,缺省匹配。

String result = findExactKey(path, mappings);
if (result == null) result = findComplexKey(path, mappings);
if (result == null) result = findDefaultKey(mappings);

所谓精确匹配是指严格相等,比如:url为/a/b/c.jsp,则与内容为/a/b/c.jsp的pattern匹配;而模糊匹配则是带有“*”、“?”之类的匹配串,比如:url为/a/b/c.jsp,则与内容为/a/b/*的pattern匹配;至于缺省匹配则是精确对应于“/”、“*”、“/*”的匹配项。

其中,精确匹配优先进行,模糊匹配次之,最后才是缺省匹配,如果前二者找到匹配项,则不进行缺省匹配。因此,对于内容为/a/b/c.jsp和/a/b/*的pattern同时出现时,/a/b/c.jsp首先匹配前者。

对于模糊匹配,sitemesh采用最长匹配原则,以下代码摘自PathMapper:

Iterator i = mappings.keySet().iterator();
String result = null, key = null;
while (i.hasNext()) {
 key = (String) i.next();
 if (key.length() > 1 && (key.indexOf(’?') != -1 || key.indexOf(’*') != -1) && match(key, path, false)) {
  if (result == null || key.length() > result.length()) {
   // longest key wins
   result = key;
  }
 }
}

因此,对于内容为/a/*、/a/b/*、/a/b/c.jsp的pattern,url为/a/b/c.jsp将匹配最后一项。

而对于decorates.xml中的excludes定义,由于是在最先判断的,因此具有最高优先级。只要满足excludes中定义的pattern,即可免去后续判断。

此外,由于sitemesh使用HashMap保存decorator pattern,因此如果存在多个decorator中定义了相同的pattern,则最后只有唯一的pattern存在

基于上述规则,我们可以在web.xml中只简单的声明sitemesh filter的url-pattern为“/*”,然后在decorate.xml中根据实际需要定义出复杂的pattern。

6/17/2005

BJUG周年庆

Filed under: — site admin @ 12:31 am

多亏nemo提醒,因着BJUG里好几个member都在自己的blog上记了一笔,我想也不能落下啊,所以也免不了落一下俗套了:)

今天看到maillist里最长的thread, 感觉其乐融融。很高兴看到BJUG走完1年历程,哦不,算起来是1年多了,如果按去年4月份的话,我应该是半年后来到BJUG的,当时还叫Java Party。在这里,我看到了老朋友银狐,还有小陶,同时还结识了很多新朋友。记得当初找到李默,是因为看到他在blog上号称要招收敏捷团队,于是带着敬仰之情想向他请教敏捷方法,后来也一直未果:( 不过到是颇有意外之喜,半年多来收获颇丰,眼界也开阔了不少,衷心希望BJUG能够越走越好,也希望自己可以尽一份绵薄之力:D

6/9/2005

process, from forground to background

Filed under: — site admin @ 11:07 pm

A well-defined and lightweight process. Team members apply them several times, make refinements, and commit the process to memory. It becomes second nature to them. It becomes a good habit. It allows the team to carry out the basic steps, focusing on the content and results rather than process steps. The process itself moves from foreground to background.

软件过程的实践,应该是:经过若干次重复实践,而后精化,并逐渐形成记忆以成习惯。最终,要使得团队成员能够将注意力集中于结果与内容上,而非过程步骤本身;要使得过程规则从台前转入幕后。从规则到习惯,这是必由之路。由此也可以看到,好习惯的积累与传承,需要多次重复实践与磨合,需要所有团队成员的协作,这是十分难能可贵的。顾而,一个好的团队的形成,也并不是一件容易的事情。

What’s develper’s good feeling

Filed under: — site admin @ 12:16 am

Developers love new things. They get something new to work on every two weeks. They get closure every two weeks. Closure is an important must-have element for job satisfaction. Getting to declare “I’m done” every two weeks is such a good thing.

从FDD有关迭代的描述中我们可以看到,现代软件过程方法中对人的重视,这是一种人性的回归,不能忽略人的因素,不能忽略团队的士气,这也是很多时候为什么普通程序员对过重的文档化与管理制度会有漠视与抵触,job satisfaction才是能够为软件开发中的多数人所接受的good feeling,也是团队士气的关键因素——morale of team。

5/31/2005

Basic Test Pattern

Filed under: — site admin @ 11:21 pm

这里列出的是出现于TDD一书中的两个有关于测试的基本模式:

When you begin writing tests, you will discover a common pattern (Bill Wake coined the phrase 3A for this):
1. Arrange—create some objects
2. Act—stimulate them
3. Assert—check the results

这个模式看起来很简单,以至于似乎不值一提。这里主要的问题在于,对一组测试来说,Arrange是否可以“共享”。而一般认为,这里的Performance是次要的,因为比起测试间依赖导致的严重后果,Performance的影响就显得弱了许多。

前阵子在BJUG的maillist里讨论过DbC(Design by Contract)的问题。如Raimundo所说,这里的Test Case其实是在检查postcondition和invarient。而至于precondition则需要有被测代码自己来保障了。不过适当结合DbC到或许是一个值得一试的事情,至少可以把对precondition的检验放到代码之外。

a common pattern—one test can be simple if and only if another test is in place and running correctly.

这条模式比较有意思,讲的是,当你想要简化一个test的时候,也就是要对原有test做出修改的时候,首先要有其他的测试对这一修改做出保障。

5/30/2005

软件开发成本的“守恒”规律

Filed under: — site admin @ 11:27 am

一方面,借助于某一系列的具体技术或者工具,软件开发的成本也许可以在某个局部领域里得到大幅度的降低。另一方面,总体而言,成本依然没有减少,无非是从一处转移到了另一处,从一种形式的消耗转化为另一种形式的消耗。这一点到是酷似物理学领域里的“能量守恒定律”。这里可以举出很多例子:

比如framework,它部分的将软件成本转移到了framework的开发上,从而使上层应用者得以轻松享用framework开发者的辛劳付出。但是不要忘记,任何framework都有其适用的领域,只有在其擅长的范围内,效用才能得以彰显。而一旦超越其能力所及,那么,越俎代庖只会事与愿违,古老的MFC便是一个例子。

再比如TDD,作为一种以个体经验为主导的敏捷方法实践,它在为XP团队带来编写高质量代码保障的同时,也为TDDer们学习和掌握其实践精要无形中设置了障碍。也就是说,这种效益的总体提升,是建立在TDD的正确实践基础之上的。因为TDD浓重的经验主义色彩,使得成功者的经验很难轻松把握和简单复制。因此,对于一个实际团队而言,TDD本身的掌握成本,以及对项目构成的风险,也该计入账上。此外,TDD的适用范围也是一个值得思考的问题。至少,对于许多并未采用TDD的现存系统的再工程(reengineering)而言,中途引入TDD在短期内并不会看到任何作用。而很多情况下,我们面对的多是遗留系统(至少从我个人经历而言是如此),而非白手起家,从零开始。最近市面上有一本书,叫做《Object-Oriented Reengineering Patterns》,讲的就是对遗留系统的再工程问题。

这里还有一个来自于.net的例子,这是最近从孟岩那里听来的,有关于DataGrid的抱怨。DataGrid作为RAD开发工具的一个必要组件,为基于数据库应用的快速搭建提供了便利,但是与数据源过于紧密的绑定,导致了许多基于.net技术的应用系统没有层次概念。而一般认为,一个分层系统所带来的松耦合,可以使系统更具延展性,以适应多变的需求。由此,为了使.net应用也变得层次分明,为了使domain model能够贯穿于从后到前的每一个层面,就不得不花费大量精力来做与DataGrid的适配。这个反面例子,到是让我更加相信RAD工具的局限性了。看起来,像do more with less这样的口号,也并非如听上去那么悦耳,搞不好就是一个hype。

5/26/2005

Refuse Duplication —— JavaScript

Filed under: — site admin @ 3:23 pm

既然对于Web层的诸多页面冗余,我们提出了重新整理的想法,那么这种思想也必然应该是贯彻始终的,换言之,在开发过程中应该“绷紧这根弦”,敏感的不要放过任何有可能改善重复的机会。对于JSP页面,我们可以在确定框架之后,采用include机制,而对于JSP页面以外的其他元素呢?比如JavaScritp,比如CSS。

一个典型的例子是用JavaScript实现的鼠标悬浮于文本输入框之上时控件风格的改变。以前的做法是,要在每一个页面的首部先定义一段JavaScript代码:

function mouseOverInput() {
  this.className = “focus";
}
function mouseOutInput() {
 this.className = “";
}

这里的focus定义于一个外部的css文件中。然后,在文本输入框出现的地方,我们需要加上这么一句:

<input type="text” onmouseover="mouseOverInput();” onmouseout="mouseOutInput();” />

随着时间的推移,duplication不断重现,最后就会发现,有的页面中只有function定义,而没有对function的引用。事实上,上述功能在“要求所有文本输入框都遵循该规则”的前提下,完全可以有更为优雅而不致错误的做法。我们可以将下列JavaScript代码作为公共部分独立于所有页面:

/// general.js
// set onload handler
if(document.all)
 window.onload=addEvent;
function addEvent(){
  aTags = document.getElementsByTagName("INPUT");
  for (var i=0; i<atags .length; i++)
  with(aTags[i]) {
   if (type!="text")
    continue;
   // set onmouseout handler for text box
   onmouseout = function() {
    className = ‘’;
   }
   // set onmouseover handler for text box
   onmouseover = function() {
    className = ‘focus’;
   }
  }
}

这样,引用该js文件的页面,其中包含的所有文本输入框无须额外设置,都将自动获得前述界面效果。

<input type="text">

因而也不用担心漏写onmouseover和onmouseout消息响应函数的调用了。除了需要在文件首部包含一行引入该js文件的JavaScript代码外,页面内部对其他事情一概不知。

上述解决方法还有一个缺陷,假如我们希望在页面加载时做一些自定义的初始化操作,我们也许会在页面里定义自己的myInit函数,然后将其设置为onload消息的处理函数。比如:

<script src="general.js"></script>
<script>
function myInit() {
 alert(’init’);
}
</script>
<body onload="myInit">
</body> >

此时,general.js中的addEvent函数将不起作用。为了解决这个问题,我们可以做一个简单的约定:在general.js中定义一个dummy myInit,它什么事情都不做,在addEvent中会将其作为callback函数进行调用。

function addEvent(){
 // …
 myInit();
}
function myInit() {}

如果我们需要在本页面内定义自己的初始化行为,则可以在引入general.js之后再行定制myInit。并且,我们不用在body标记中声明onload属性了。当然,如果你希望强行“注销”addEvent的功能,也可以这么做:

<body onload="">
</body>

5/17/2005

一次TDD实践经历

Filed under: — site admin @ 11:50 am

昨天在重构一位同事的代码时,小试了一下TDD的开发方式。在看过Kent的TDD之后,做这样的实践,感觉效果还是不错的。进行的时候颇有点像Money Example的味道。

因为要将原来散布于JSP页面中的部分代码逻辑移出,因此我引入了一个新类。在未及代码实现之前,先写了Test Case,然后一点点充实,Test Case与实现类的规模同步增长。

不过,过程中也再次体会到了一些问题:

我在某个Servlet类中加入了一段代码,而正是这段代码中的一个小疏忽,使我为此调试了4个小时之久,这期间包含了反复的部署和启停服务器。试想,如果将这段代码移入POJO进行单独的测试,相信很快就可以在我真正关注的范围之内通过assert来暴露问题,而不是一直等到UI表现上的异常反映,才促使我去通过debug的方式来逐步排查。实际上,我们的时间往往就是在这样不知不觉的过程中“浪费”掉的,虽然看起来从出现错误到排查错误的过程很自然很合理。

不过,当我调试完错误后,试图将这段代码从Servlet移出时,确发现了绊脚石:代码中存在对Singleton的调用,该Singleton又间接包含了对数据库的访问。这使我最终放弃了努力。当然,这么做还有另外两个理由:相信debug之后的代码不会再有问题;时间紧迫。

由此,也可以再次给我一个深刻的启示,即:如果要真正高效而方便的完成测试编写,一定记住两点:
Programme to Interface
Test Plain Object

培养起主观上使代码易于测试的意识并不容易,因为它涉及定势开发习惯的改变。如果问我为什么开始的时候要在Servlet类中加入那段代码,我也无法回答,只能归咎于惯常思维。

5/16/2005

一种工具、技术、方法论是否被广为接受的两个要点

Filed under: — site admin @ 10:21 pm

Write the tests you wish you had. If you don’t, you will eventually break something while refactoring. Then you’ll get bad feelings about refactoring and stop doing it so much.

一种工具、技术,甚或是方法论,能否被大家广为接纳与传布,有两点至关重要:其一是自身简洁直观便于掌握,其二是恰如其分的方式方法。如果达不到前者,那么工具、技术、方法论的实际价值就值得怀疑。反之,则是个人认识与修为的欠缺,而不能盲目的一概否定。比如上面的反面教材,正是由于没有适时的引入测试,才致于对重构产生怀疑与恐惧,并最终止步不前,重回老路。而导致这一结果的真正原因恰在于错误的实践方式,并非重构之过。

很多时候,失败的软件过程实践往往就是因为团队成员觉得难于施行,在遇到一系列挫折之后,最终选择了放弃,甚至产生了偏见,即使他原本很想尝试新鲜事物。应该从上述两点来考察失败的原因。是方法论本身的问题,还是自身理解的偏差。

一件最近发生的让我很沮丧的事情:在我充分认识沟通的重要之后,却无奈于我与另一位同事的相隔距离十分的远(他的办公地点在与我们部门相对的另一个部门,分属两个办公场所,中间一条过道相隔),于是,我希望借助于远程桌面,但是对方的Win XP(SP2)操作系统似乎很顽固,致使我最终选择放弃。由此带来的影响,我估计沟通起码减少一半。

3/18/2005

Case Study: The Spring Experience

Filed under: — site admin @ 9:21 am

来自Rod Jhonson的Spring经验,非常受用的一些关于unit test的实践指南:
- Accept that the test suite is more important than anything else but the deliverable code itself.
- Work in small steps.
- If you’re looking at a piece of code for which tests can be improved, add more tests.
- Write a unit test that fails because of a reported bug before attempting to fix the bug.
- Design code so that it’s easy to test.
- Ensure that the entire test suite runs in seconds.
- Use meaningful names for tests that show their purpose
- Minimize the number of configuration files that need to be loaded to run tests.
- Tests should have no side effects.
- Don’t depend on the ordering of test cases, and don’t create test suites programmatically.
- Unit tests should not depend on a database or external resources.(If your test suite takes minutes rather than seconds, you can’t practice test first development.)
- If a configuration file is used, load it from the class path
- Have Ant scripts that run all tests and run test coverage analysis.
- Run individual tests in an IDE.
- Look at test coverage reports regularly.
- Use mock objects to avoid dependence on external resources.
- Refactor test code when necessary.
- Refactor application code to eliminate duplication and improve quality.
- Configuring IDE to throw UnsupportedOperationException() instead of doing nothing or returning null in all generated method stubs.
- Writing each test (each JUnit test method) to test one thing.

1/28/2005

关于AllTests

Filed under: — site admin @ 9:18 am

一般情况下,在编写Test Case的时候,与Test Case位于相同路径下还应该有一个AllTests.java文件。该文件代表一个Test Suite,包含了当前所有可用的Test Case。在本地开发环境中,除了可以利用build脚本运行Test Case外,一般IDE还会提供具有良好图形界面的Unit Test功能,比如:Eclipse的JUnit插件。此时,如果要运行所有测试,就不用手工逐个执行了,只需要Run “AllTests” as JUnit Test就可以了。

AllTests.java的编写很简单:

public class AllTests extends TestCase {
 public static Test suite()
 {
  TestSuite suite = new TestSuite("All Tests");
  suite.addTest( SomeTest.suite() );
  suite.addTest( AnotherTest.suite() );
  return suite;
 }
}

同时,还需要在每个Test Case中加上一个suite静态方法,比如:

public static Test suite() {
 return new TestSuite(DBTest.class);
}

1/27/2005

关于代码阅读

Filed under: — site admin @ 9:43 am

近日,Java Party的maillist里有人在聊如何阅读与学习源码,当然,这里尤指开源源码。这个话题让我想起早先候捷先生的那篇“上穷碧落下黄泉”,对于这个问题的阐述可谓巨细无余。

在这里,我还想根据自己的切身体会,补充几点:

文档>>

为了做到有的放矢,了解源码之前最好先热热身,翻阅一下相关的文档和资源。在了解了足够背景之后,再行决定是否深入源代也不迟。文档的阅读解决的是“why to”的问题,而源码的阅读则解决的是“how to”的问题,不过实践中,好的文档往往难得一见。

方法>>
源码分析大抵可以分为两种类型:静态分析和动态分析。前者是从静态代码入手,从某个关键点/入口点开始,抽丝剥茧逐层分析;后者则是先将程序跑起来,再结合某个具体场景,采用调试手段,通过分析运行期对象间的协作交互来获得对代码的深层体认。如果自认为天资聪慧,或者是源码简单至极,静态分析也许已经足够。但若是对自己的IQ信心不大,或者源码甚为复杂,那么最好采用情景分析和动态调试。

笔记>>
俗语说“好记性不如烂笔头”,不论是静态分析还是动态调试,笔记是一定要做的,并且必要时候还要画图。在OO系统中,尤其是遇到对象间交互关系复杂的关键部位时,不妨画一下时序图。有UML工具相辅自然是好,不过没有也无妨,一个白板一支水笔足矣,只是这样的真迹要注意保存,辛苦得来的劳动成果也许以后还有用处。不过使用UML工具有一个明显的好处,在对类间的静态关系还不清楚的情况下,可以利用反向工程根据源代码快速生成类图。

工具>>
趁手的工具最好不要少,比如:候sir钟爱的grep。记得我在VC6风行的年代,使用最频繁的就是其IDE中的Find in files功能了,有了这个“简陋”的功能,已经完全可以游刃于MFC的源码之间了。当然,如果有更好用的工具自然好,比如Eclipse,除了强大的调试功能之外,对于源码的交叉索引和快速跳转,将会有助于更快更方便的定位到自己感兴趣的位置。此外,Source Insight也是我很喜欢的一款工具,虽然不能用它来调试程序,但是作为一个轻巧的代码编辑器,其语法高亮显示和交叉索引功能还是很不错的。

其他>>
阅读代码的动机/意图也很重要。不同的动机对阅读代码的效果和最终结果将会有不同的影响,这一点在候捷先生的文章中已经有所提及了。
此外,还有一本专门介绍源码阅读方法的书——《Code Reading》

12/31/2004

本年度的最后一篇blog

Filed under: — site admin @ 4:03 pm

这是本年度这里的最后一篇blog,似乎带有一点充数的成分。记得当初在这个blog的开篇中说过,这里是一个只谈技术的地方,不过由于最近工作繁忙,加之状态不好,实在没啥心情谈论技术问题。所以,就当是破个例,在2004年的最后一天里。

孟岩是一个让我不得不佩服的人,“双重压力”下依然还能够如愿的考上博士,在这里要恭喜他一下!我发觉每次听他说话,和交流,都会有一种莫名的感染力,可以让自己振奋的,找到方向的,而又是实实在在毫不浮华的感觉。我想,在他身上,还有很多很多东西都值得我学习。很幸运能够结识这样一位好长辈。

BTW:Happy new year to all my friends:-)

12/22/2004

办公桌与团队的氛围

Filed under: — site admin @ 7:28 pm

想了解team的氛围和凝聚力到底如何吗?想知道team member对自己所处集体的信心怎样吗?那就仔细观察一下他们的办公桌吧,这里也许会有如下三种可能:
- 干净的没有任何多余的东西,比如一些小摆设;
- 胡乱堆放着无数文案,以及其他杂物,脑袋被埋没其中;
- 经过精心布置,一走近就给人以格外温馨的气氛;

若是第一种情形,我要很遗憾的告诉你,结果是令人失望的。若是后两种情况,不论是生活习惯过于邋遢,还是过于讲究,最终都只证明了一点——这张桌子的所有人,已将这里当作了自己的“家”,否则他/她就无需这么随意,或者刻意了。

在一个如此温馨的氛围中,大家可以毫无保留的进行彼此间的交流,甚或争论,自然是颇能说明些问题的。这也是一个有战斗力的team,最为可贵的一点了。

12/12/2004

blog存在的意义

Filed under: — site admin @ 8:25 pm

光阴就这么在不经意见偷偷的溜走了,一点一点,并没有留下很深的印痕。不知道这算不算是一种虚度,也许很多人都有这样的感受。有时候想想真是有些可惜,甚至是可怜……,所以,blog也就有了它的特殊“意义”——记录下自己的一点一滴,好在将来回顾的时候“有据可依”。至少在我看来,这样会让自己觉得过去的时光不至白费,让自己觉得生活有了些许意义,让自己哪天回忆的时候不会是脑海里空白一片。

写blog也是一种习惯,习惯的建立总是不易,而一旦打破,便会一发而不可收拾,所以,该写的还是要写的,否则对自己的信心也是一种打击。这又让我想起前几天的那番牢骚:)

12/9/2004

有感于良好习惯的打破

Filed under: — site admin @ 9:25 pm

规则的打破是很容易的,有时候甚至是在team member的不经意间的“默许”下潜移默化的发生的。进而,交流归于不畅,目标可以变得模糊,行事可以变得随意,原则可以不成其为原则,一切都显得自然而然,因为已经有过一次了,再来一次又何妨?

合抱之木,生于毫末,九层之台,起于累土,持久的原则与良好的开发习惯的建立,绝非易事啊!

11/16/2004

计划的粒度

Filed under: — site admin @ 10:17 pm

一个计划的制订到底是以什么为单位才更合理呢?记得同事以前曾因计划粒度过细而有所抱怨。不习惯计划的人,会为难于周计划;习惯了周计划的人,会为难于日计划。好在我以前就已经有了写日志的习惯,因此对周计划并没有什么不习惯的地方。

不过今天到是翻然醒悟,绕了一个大圈子之后才发现,至少以我目前的能力而言,要将计划的粒度控制到小时为单位还是有些困难。其一是精力的不自主分散;其二是不确定因素的干扰。前者还需日后磨炼,而后者却是不可控的。

不过以天为单位的计划任务还是可取的,“多还少补”,保证大方向不变。持之以恒的小幅前进,也是一种成就感。

测试先行的合理性

Filed under: — site admin @ 10:22 am

如果你对自己把握OOD的能力还没有足够的信心,如果你对需求的理解还不甚明晰而无从下手;如果你更习惯于从代码中寻找问题的答案(这是许多程序员一贯的品质),那么就先从编写testcase开始吧,它可以有助于你抛开一些既有设计中华而不实的先验假设和过分设计,从而让你变得注重实际。一组testcase下来,OOD也就完成了一半了。

9/24/2004

Automate anything if possible

Filed under: — site admin @ 10:18 am

Automate anything if possible,我想这大概是《Java Development With Ant》一书所带给我的最大影响了。让机器自动处理,流程自动运转,事情变得尽可能简单,这便是Ant的精髓。 (more…)

9/17/2004

immutable property的幕后故事

Filed under: — site admin @ 5:07 pm

ant中的property有一个immutable特性,即:property一旦设置,就再不能更改。因为有了immutable,所以就产生了很多flexible,例如针对不同场景的环境配置。

考虑通常情况下的代码开发,属性被预先赋予缺省值。当我们需要根据环境,对这些已有缺省配置的属性进行再设定时,我们的设置行为是位于缺省设置之后的。因而这样的“property”是“mutable”的。而这样的配置往往也是深处于代码之中的,需要你对代码逻辑有所了解。有点类似于“白盒”。

回到ant,假如你很想让build.xml变得更灵活更易于复用,一些属性配置必然在提供缺省值的同时,也提供针对不同环境的再配置手段。假如你不希望因此而改动逻辑颇为复杂的build.xml(几百行的build文件对于一个稍大规模的project而言是家常便饭),假如你对build.xml的内部实现并没有半点兴趣(将它看作“黑盒”,你只关心那些有点像接口一样的可配置的property),那么property唯有immutable,才能做到“外部的再配置覆盖内部的缺省配置”。

这就是immutable property的幕后故事。

9/16/2004

好文,收藏

Filed under: — site admin @ 1:32 pm

工作遇到了麻烦,于是开起了小差,午休的时候耐着性子读完了两篇好文,值得深思:

放弃理想,未必能成就现实
认清现实,才能找回理想

P.S. 孟岩的文章很有特色,平直的文字,却是非常有理有据的。

9/13/2004

文章交付,有些忐忑

Filed under: — site admin @ 5:16 pm

周末将第二篇文章发了出去,今天得到编辑的确认,终于可以轻舒一口气了。接下来就是等着杂志付印出版,或者是之前被告知文章内容有误。不过,一个多星期来的辛劳,不能说深入理解,总算也将Tiger的JSR166和JSR114了解了个大概。当然还包括.NET Framework的System.Threading,以及ADO.NET。自觉收获不小。撰文的好处就是可以逼迫自己认真对待。每一个技术细节都要仔细推敲,多方引证,否则就会冒毒害读者的大不韪。一番折腾之后,自己的认识与理解也有了长进,所学所知也更为牢固与扎实。

平台的比较历来就是极为艰深的。这需要当事人对平台有着长期实践与深刻理解,需要有高屋建瓴的眼光与认识。即使如此,也未必能引来下面满堂喝彩,想想真是吃力不讨好啊。尤其是需要从大跨度的角度,在有限篇幅里,说清楚自己的观点,这更是难上加难。好在我自知能力有限,更不想成为众矢之的。因而选择的是类库的两个局部:多线程和数据库访问,也算是审时度势吧。不过就算是局部,字数也依然超出了预算,可见要是来个统观全局的大手笔,恐怕真要将自己了陷进去。还好自己没有“上了”编辑的当:)

9/1/2004

Manning的书皮

Filed under: — site admin @ 5:30 pm

优秀的国外图书出版商,总是喜欢将一个系列的书,做成统一的风格。专业、考究而又严谨的设计,捧在手里,就让人感到一种亲近感和敬畏感,而对于书中正文,即使还未曾读过,对其质量就已经有七八成把握了。当然,很多外版书籍在引进过程中由于翻译的问题,也给国内读者造成了错误的不良印象。 (more…)

8/28/2004

What’s Metaphor

Filed under: — site admin @ 9:10 am

今天,终于对隐喻(metaphor)有了一点点进一步的认识。根据我现在的理解,隐喻表现为一组形象贴切的,彼此关联的,并且是自包含的名词集合。它涵盖了人们对系统未来功能和特性的愿景。如果用隐喻向一个对系统还知之甚少的局外人作解释,应该可以使他快速的认识和理解,并且打消存在于其大脑中的诸多疑惑。另外,隐喻的使用者,自身也可以通过不断比较实现与隐喻之间的差异来确知实现是否偏离愿景。这也就是为什么时常采用拼图这个比喻来描述隐喻的原因,现在想想确实十分形象:拼块就是实现,完整的拼图就是愿景,拼图的过程——尝试、调整、剔除不合要求的拼块——就是软件开发的过程。

不过我觉得,要找到这样一组词汇也并非易事。比喻毕竟是比喻,对于复杂系统而言,首先自包含就是一个问题,如何能找到一组不多不少,刚好可以完全说明系统愿景的词汇呢。另外,如果自己对系统轮廓还比较模糊的时候,很有可能形成一些似是而非、模棱两可,看似贴切、实则误导别人的隐喻。这也许是一个逐步进化的过程(听起来有点向迭代)。

8/17/2004

开源项目通常的运作方式

Filed under: — site admin @ 1:19 pm

上次对开源项目的运作方式一直迷惑不解,今天在看《Java Development with Ant》中有关Ant的演化过程时,总算是有了点眉目,受了些启发。 (more…)

8/16/2004

亲历产品研发的全过程

Filed under: — site admin @ 11:36 am

如何了解一个产品研发的全过程?眼下也许是一个契机。尽管以前兼职期间我也曾亲历过产品研发的过程,但毕竟是在产品成熟时期介入的,并且中途又离开了。因此,很多时候都是局部的割裂的和感性的,而无法从认识上一窥全貌。很遗憾,一直都想把当初经历的点滴整理记录下来,却又因为时间和懒惰的原因,久未付诸行动,恐怕现在已经记忆模糊了。

不管眼下的产品最终会否成功,如果全力投入,总会对自己大有裨益,不单是技术,还包括技术之外的方方面面。这是纯粹的软件开发所无法体验到的。我要注意积累。

另一方面,纯粹的技术体验,可以从开源软件中获得,这方面我也有所打算。从设计到实现,作一个全程的跟踪。很久没有做这样的事情了。

8/13/2004

简单、专注——我所喜欢的流行风

Filed under: — site admin @ 11:26 am
Everything should be as simple as possible,but no simpler.
                                              ——爱因斯坦

我喜欢简单,也崇尚专注。 (more…)

8/9/2004

立足开源的产品研发方式

Filed under: — site admin @ 10:24 am

现在的IT,有很多单位都在做自己的产品。传统的产品研发是从轮子造起,一点一点,集腋成裘。这样的产品研发方式,我也经历过。但是,在有同类产品先期流于市场,且颇具竞争力的前提下,这样的方法难免风险过大,恐怕任何一个中小企业的决策者,除非有十足把握和雄心壮志,否则万不敢冒此风险。 (more…)

浅评微软,Java和开放源码运动[转贴]

Filed under: — site admin @ 9:45 am

今天早上看了同事的一篇文章,文章写于2002年底,不过里面的内容依然颇值得玩味。

题目:浅评微软,Java, 和开放源码运动

我也在IT里混了近十年了(当然是从大学三年级开始算的)。一直都在MS战线上混,很崇拜MS。是MS的忠实拥趸。其实偏向于反微软阵营的人和老记之流挂在嘴边的是微软没技术,微软只会抄袭模仿。其实就我感悟的来说,就总体上而言,微软是最有技术的。技术上模仿、借鉴、和创新超越的路子,其实每个公司都是一样的,特别对于市场上已经有先行者,而你又要击败先行者。既然是先行者,就有很多东西是已经经过摸索和证明了的,再做出来的东西类似,也就是必然的了。微软不是世界的全部,因此你不能指望微软能攘括所有的创新,任何公司都有自己的主要战线和技术局限性。
(more…)

8/6/2004

技术的围城

Filed under: — site admin @ 10:57 am

要学习的技术实在是太多了,一再感到书到用时方恨少。并且,许多知识点都是彼此关联,有着千丝万缕的联系的。因此,就像乱麻一样,很难一下理清思路,很难一下看清该从哪里入手。现在的我,正处在一个“艰难”的时期。

我想,首先需要花时间和力气,从横向的面上了解(但不是深入),对领域有大致的总体认识(这正是我目前在做的事情);在经过这段困难时期之后,结合实际选定某几个点,进行深入的学习、研究,并用到实际。前一点有助于解决千头万绪的困惑和左突右闯的盲目;而后一点,则是经历必经的混沌期之后的更为重要的一步,深入扎根于某一两项技术是自己得以有质的飞跃的关键,否则就只能是无源之水,无本之木,始终游走于技术的“围城”之外。

外面的人想冲进去,里面的人想出来。我现在的处境大概属于前者,因为想立足于技术的人,总还是想要进到围城里面的,虽然世事总难得兼:)

8/2/2004

一个很有意思的比喻

Filed under: — site admin @ 1:16 pm

“技术不断地改变人,刺激人不断地寻找改进技术的手段。于是,人就成为机器世界的性器官,就像蜜蜂是植物世界的性器官一样,它们使植物世界生殖和进化出更加高级的物种。机器世界给人回报商品、服务和赏赐。因此,人与机器的关系是固有的共生关系。”

——来自CNBlog

7/27/2004

从VS2005 Team System想开去

Filed under: — site admin @ 1:02 pm

在今天例行的下班“公车时段”,在最新一期的《程序员》杂志上看到了一篇关于Visual Studio 2005 Team System的介绍性文章。我承认,对于VS2005 Team System的所有了解完全是从这篇文章开始的。随后在网上Search后才知道,这个被称作为企业应用开发提供集成化的全面解决方案的“半成品”,在几个月前的TechEd2004上是众人瞩目的焦点。 (more…)

7/22/2004

与大师Kent Beck的一点共鸣

Filed under: — site admin @ 1:00 pm

在下班回来的公车上摇摇晃晃的看着一篇刊载于往期《程序员》上的题为“《测试驱动开发》精彩选读”的文章。Kent Beck的这本书确实很吸引人,只是这中译本的翻译不敢恭维,至少不能算作专业,有机会还是拜读原著比较好。不过这并不妨碍我在短短的公车时段里与这位我所钦佩的XP大师“碰撞”出思想的火花来。请不要误会,我并不想高攀。而是,忍不住幸喜于读到细微处的一点共鸣,虽然这和XP,TDD,本身似乎关系并不大。 (more…)

7/21/2004

由一场有关开源的争论所得到的收获

Filed under: — site admin @ 12:51 pm

昨天在CSDN看到了一篇讨论开源的文章,引来跟贴无数,甚是激烈。向来口水战总被指为意义甚微,不过还是会有许多人耐不住寂寞,当然这其中也不乏金玉,但轻率的争辩总是多过理性的交流,因此在这样的氛围里智者也很容易因为言词过激而自乱阵脚。 (more…)

第二期程序员技术沙龙

Filed under: — site admin @ 12:38 pm

上周末参加的活动,内容有关于Palm OS编程,只是讲座形式显得单薄呆板了些,不过我还算幸运,拿到了一个纪念品,居然还是以替补身份领奖的,不知哪位老兄有事未能出席,把这个机会让给了我:)

点击此处查看照片

7/16/2004

开场白

Filed under: — site admin @ 12:35 pm

终于决定把blog彻底搬到自己的网站上来了。这将会是一个纯粹技术性的blog,但不会局限于某项单一技术,因为:
- 不打算把这里当作调侃、发泄的场所,这会和网站的整体风格格格不入
- 我不是任何一项技术的狂热爱好者,对技术的探究深度也很有限
- 和生活一样,技术也该丰富多彩一些才是 (more…)

Powered by WordPress