Monthly Archives: October 2009

SQL编程中的曳光弹

有本书里提到了“曳光弹”这个东西。它让你在暗夜开枪时,除了靠你的本事命中目标之外,同时还会帮你把子弹的轨迹在夜空里展现出来。

在JAVA编程时,一种典型的曳光弹就是日志。

在SQL编程时,也可以用到曳光弹这个技巧。

一个例子就是:找出所有 A.a = B.a 的 A.c 记录集。我们在写这个SQL时,除了 select A.c之外,也可以同时select出 A.a 和 B.a,然后就可以用肉眼检查一下A.a和B.a是否相等,这样可以帮助保证SQL程序的质量。

另外一个例子是:找出所有符合某个条件的记录集,然后对它们进行批量更新。对这种问题,我们可也直接写一条 update + where全部搞定,但也可以先把符合条件的记录集插到一种临时表中,然后再按临时表去更新实际的记录。当你回头去看临时表时,你就可以切实地看到哪些记录被修改,可以检查这些记录是否符合修改条件,从而也更加保证了SQL程序的质量。

Notes on XP — No.6: Four Values

There are Four core values for XP

   1. Communication

        The more you communicate, the less you make a mistake

   2. Simplicity

        The simpler the system is, the less you have to communicate

   3. Feedback

        a. Feedback from tests

        b. Feedback from people

        The more feedback you have,the less risky it will be

   4. Courage

        It is the courage to make a overall change, or to throw away code.

And there is a deeper value: Respect between each other.  "If members of a team don’t care about each other and what they are doing, XP is doomed."

Notes on XP — No.5: Software process is like driving a car

"
Driving is about constantly paying attention, making a little correction this way, a little correction that way", said Kent Beck’s mum.

Note that
the driver of a software project is the customer. The customer should keep his eyes on the road, that is the system under developing.

So what do we programmers do?
We give them feedback about where we are on the road.

Notes on XP — No.4: Cost of Change

This chapter is exiting, but also making people to doubt.

Traditional views believe that the cost of changing a program rises exponentially over time.  And it’s better to make decisions at the early stages.

But Kent Beck believes that we can make the cost of change so low that this cost-time curve can be a very flattened one. Therefore, we don’t have to make decisions at the early stages so that the development will be more responsive and less risky.

But how to make the curve more flatten?

   1.OO Design

   2.Simple Design

   3.Automated Tests

   4.An attitude of constant refinement. 

 

PowerMock 下,调用JAR包中的Class的getResourceAsStream()会出问题

  If

    1. a JUnit test is run with PowerMock,

    2. and this test calls "this.getClass().getResourceAsStream()",

    3. and this test class is loaded in a jar file, instead of being loaded as a single file

  Then

    A "java.net.MalformedURLException" will be thrown at this.getClass().getResourceAsStream() when this test is invoked.

 

业务逻辑的冗余

比如说,要判断本公司某员工是否为中国人,在系统中可以分别通过调用两种接口来获取结果:

  a.护照上写的是中国人 => 此人是中国人

  b.工作证上“国籍”一栏填了“中国” => 此人是中国人

这两个逻辑冗余了,因为它们可以解决同一个问题,在现实世界里,这是很现实的事;但在IT系统中,不应该让这两种逻辑同时存在。也就是说,要判断一个人是否为中国人,只能去查他的护照,不准通过其它途径来判断。

为什么要这样? 因为如果不这样的话,
两条冗余规则中一旦改了一条,除了该规则自己的调用者受影响之外,另一条规则的调用者可能也会有问题。 比如说,如果上面的规则b改成 [ 工作证上“国籍”一栏填了“中国” 或 "香港" =》 此人是中国人],那么我们除了要改一下b接口 and/or 它的调用者,还要注意一下 规则a  and/or 它的调用者: 香港人的护照也是中国护照吗? 是,则万事大吉;如果不是,那就要把a接口改一下,或者把a接口的调用者都改一下。

思考一个问题:某个布尔值在系统中应该显式定义还是应该隐式推导?

比如说,
人和兽都是动物,业务规则是:直立者即人,爬行者为兽

那么
在“动物”表中, 除了要有 “行走方式” 这个字段,要不要再搞一个 “是人是兽” 字段?

隐方:不必了。通过站立方式已经可以推导出是人是兽了,
再搞一个字段就是冗余了,众所周知,冗余有很多坏处。

显方:我觉得应该搞一个“是人是兽”的字段。先不说冗余的问题,先说搞一个这样的字段有哪些好处。

   1.
最重要的一点,是可以帮助业务逻辑之间解耦,降低系统复杂度。  比如说,系统里判断一个动物能否说话时,先要判断这个动物是人还是兽,而要判断动物是人还是兽,要先判断它的行走方式是否为直立。 这样的话,“能否说话” 就依赖了 “是否直立行走”,如果这种依赖关系多了,这些关系就会在系统中形成一个网状结构,很复杂。而如果我们显式地搞一个 “是人是兽” 的 Mediator,网状结构就可以退化成星形结构,这样可以增强系统的可维护性。

   2.
业务逻辑之间解耦后,还可以减少公司里业务专家的压力。很多程序员,尤其是新来的五谷不分的程序员,并不知道直立的就是人,趴着的就是兽。要了解这一点,他们就得去问业务专家,即老工程师或者产品经理,这个代价可大可小。他也可以去查文档,但按我们的现状,文档未必完整,而且篇幅巨大,查起来也非常费劲。

隐方:对你的第二点我很赞同,但关于第一点,我觉得还是设计技巧的问题。
你在业务层写一个接口用于判断“是人是兽”,不就可以了吗?而且这样还可以封装判断的细节,当判断规则改变时,接口的调用者可以不必改写代码。

显方:这么看来至少你赞成搞一个“显式”的接口了,只不过是放在业务层;这样既可以实现业务逻辑的解耦,又可以避免数据库中的冗余。

隐方:是啊,很完美吧?

显方:但你的想法
需要一个大家定一个规矩:即所有人都必须通过个接口来进行人兽判断。这在代码不多、并且软件复用思想深入人心的小型团队里倒是很适用,因为这个规矩很容易执行;但在大型团队里,这个规矩很难执行;因为
很多人对业务层的重用并没有什么概念,他们会直接绕道去找数据库;而且
即使他们愿意重用业务接口,在项目紧张时也懒得去找相应的接口规格,因为他们根本不知道这个接口是否存在,也不知道应该去找谁问这个问题

隐方:这是另外一个问题了,主要跟软件过程有关系,或者可以借鉴SOA实践中的一些思想,我们另开一个话题再聊吧。

Selenium IDE 与 弹出框的冲突

今天发现,在Firefox中运行Selenium IDE时, 弹出框 (javascript 中的 alert/confirm )可能不被支持。

场景是这样的:

   1.用Selenium运行某个脚本,使之到达某页面

   2.在页面上点某个东西,期望点了之后会弹出一个对话框

   3.而实际是,这个对话框没有弹出来

然后,如果在点之前,手动刷新一下页面,或者手动去到别的页面再回来,再点,那个对话框却会出现! 真操蛋啊,浪费了我一个小时时间,我还以为我的JS程序有问题。