论坛首页 Java企业应用论坛

我的酒窝

浏览 43499 次
锁定老帖子 主题:我的酒窝
该帖已经被评为精华帖
作者 正文
   发表时间:2007-01-04  
alin_ass 写道
用你这个取代mock类,万一接口方法名变了,重构挺麻烦的

我不是说:一般情况下你应该用implements关键字吗?只对“第三方接口”使用,如Connection, Map之类的。这些东西的签名不会变的,所以没有方法名变更带来的问题,而dimple可以帮你避免使用"implements"关键字创建stub带来的当接口在新版本里面增加新的方法的时候造成的问题。

还有,jmock也有重构问题的
0 请登录后投票
   发表时间:2007-01-05  
看了一下发型包,已经0.4啦?现在有sample了么?有没有想好写一些什么经典应用场景呢?比如在做stub的情况下,和easymock做一个对比。至少可以告诉大家,在只要stub的情况下,犯不着搬出mock框架这么重的东西来。
0 请登录后投票
   发表时间:2007-01-05  
ajoo 写道
再举一个adapter的例子。

不知道大家遇到过这样的情况没有。有一个api,有这个接口签名:
runApi(Map map){
  ...
  map.get(...);
  ...
}


它仅仅使用get()一个方法,但是因为种种原因,并没有使用最小接口(我认为这种设计是非常正常的),而是用了这个java.util.Map接口。


在使用这个api的时候,我们不幸的没有一个Map对象,而只有一个proprietary的PropertyMap(或者HttpServletRequest也行)对象:
interface PropertyMap {
  String getProperty(String key);
  boolean containsKey(String key);
  Set keySet();
}

需要写个adapter吧?目标代码如下:
PropertyMap pmap = ...;
runApi(convertToMap(pmap));


那么这个convertToMap怎么写呢?

Map接口相当的肥厚阿。继承AbstractMap的话要实现entrySet(),我们也没有。而我们明明知道runApi()只需要一个能支持get()的Map就成了。

一个方法呢,就是用dimple,下面是一个pojo的adapter(不依赖dimple):
public class PropertyMapAdapter {
  private final PropertyMap pmap;
  public Object get(Object key) {
    if(key instanceof String) {
      return pmap.get((String)key);
    }
    else return null;
  }
  public boolean containsKey(Object key) {
    if(key instanceof String) {
      return pmap.containsKey((String)key);
    }
    else return false;
  }
  public Set keySet() {
    return pmap.keySet();
  }
  public boolean isEmpty() {
    return keySet().isEmpty();
  }
  public int size() {
    return keySet().size();
  }
}

只需要实现我们关心的方法(一个安全的方法,可以显然PropertyMapAdapter implements Map,这样就可以用eclipse的代码生成来选择性地实现这些我们关心的方法,不会有typo。),不用管其它的乱七八糟的。

然后使用dimple,实现convertToMap如下:
Map convertToMap(PropertyMap pmap) {
  return Implementor.proxy(Map.class, new PropertyMapAdapter(pmap));
}


搞定。

可见,dimple并不是仅仅可以用做aop的interceptor,它还是一个克服静态类型局限的OO利器亚。而且不象aspectj,相当的light-weight,没有什么侵入性。



它仅仅使用get()一个方法,但是因为种种原因,并没有使用最小接口(我认为这种设计是非常正常的),而是用了这个java.util.Map接口。


看了这个例子,我的看法:
如果在视线中 需要这么复杂的代码来做测试,那么就意味着个这个接口设计并不“正常”了,根据你提到的“仅仅用到了map.get()"的这个意思,那么接口应该这样设计:
map.get()--->Object o

runApi(Map map)--->runApi(Object o) { // not dependent on map}


 

这个例子我存在异议。 看着有点困惑。

如果对于 因为”stub“比较难写,需要一个工具框架来自动实现这么一个stub,我赞成。
但是如果 因为”测试“难写而拼命的使用这么一个框架,我觉得有点舍本求末了。 或许,回过头来重构设计和代码,让测试更容易写 ,或许这样获得事倍功半的效果呢?

0 请登录后投票
   发表时间:2007-01-05  
呵呵,有些系统提供的接口我们是重构不了的啊。所以实现这些接口就是价值所在了。
0 请登录后投票
   发表时间:2007-01-05  
引用
这个例子我存在异议。 看着有点困惑。

如果对于 因为”stub“比较难写,需要一个工具框架来自动实现这么一个stub,我赞成。
但是如果 因为”测试“难写而拼命的使用这么一个框架,我觉得有点舍本求末了。 或许,回过头来重构设计和代码,让测试更容易写 ,或许这样获得事倍功半的效果呢?

这个例子不是测试阿。它的前提是:
一个模块设计成可以注射java.util.Map。这个设计是很自然的。
其他的普通客户代码都是直接用HashMap或者java.util.Properties之类的东西来注射。
单元测试代码也是用HashMap的。也没问题。

问题在于某个和第三方库或者legacy system集成的部分碰巧没有Map,而只有一个PropertyMap,这时就可以用dimple。
0 请登录后投票
   发表时间:2007-01-05  
taowen 写道
看了一下发型包,已经0.4啦?现在有sample了么?有没有想好写一些什么经典应用场景呢?比如在做stub的情况下,和easymock做一个对比。至少可以告诉大家,在只要stub的情况下,犯不着搬出mock框架这么重的东西来。

easymock倒也不算多重。而且它还有重构安全的特性。

区别仅仅在于stub vs. mock。如果需要做interaction-based test,当然是easymock,没得说。而如果要做state-based test,用easymock来做stub就有点别扭。

我的sample都很简单,已经写在confluence里了。当然也许有点生造出来的嫌疑。你有什么好的例子么?
0 请登录后投票
   发表时间:2007-01-05  
taowen 写道
呵呵,有些系统提供的接口我们是重构不了的啊。所以实现这些接口就是价值所在了。


我所能想到的 ”需要实现这些接口/抽象类的“  充要条件:

1) Easymock模拟的代码很难写 ,或者代码比用Dimple作stub要多得多

2)人家提供的接口是一个类,而不是一个接口。

对于1)如果我们依赖人家接口的一两个method,我觉的EasyMock写起来难度不大。  如果我们的逻辑依赖人家接口的大部分API 。 确实,stub要来得好得多。 但是此时,我可能就需要在 自己写一个stubImpl和用Dimple实现一个Stub来权衡了,但是这个结果是在 ”我们的逻辑需要依赖很多人家接口的method“情况下发生的,这样一来,估计看看Dimple的代码,满篇也是实现的代码了吧,在这个前提下,优势我暂时看不出来。

对于2) ,因为不用接口带来如此的难题,stub似乎不得不提出来了。但是作为选择,也可以用一个Adapter接口来封装人家的类。对这个Adapter接口的处理又回到了1)
0 请登录后投票
   发表时间:2007-01-05  
ajoo 写道
引用
这个例子我存在异议。 看着有点困惑。

如果对于 因为”stub“比较难写,需要一个工具框架来自动实现这么一个stub,我赞成。
但是如果 因为”测试“难写而拼命的使用这么一个框架,我觉得有点舍本求末了。 或许,回过头来重构设计和代码,让测试更容易写 ,或许这样获得事倍功半的效果呢?

这个例子不是测试阿。它的前提是:
一个模块设计成可以注射java.util.Map。这个设计是很自然的。
其他的普通客户代码都是直接用HashMap或者java.util.Properties之类的东西来注射。
单元测试代码也是用HashMap的。也没问题。

问题在于某个和第三方库或者legacy system集成的部分碰巧没有Map,而只有一个PropertyMap,这时就可以用dimple。


如果是这样的话,那么ConvertToMap 的逻辑也是有必要冒烟测试到的。 所以,

那测试也就很自然的从PropertyMap准备测试数据进行测试了,这样的测试也没有必要用DImple来模拟 ConvertToMap的逻辑阿,我只需要在测试里面测试到就可以了。
0 请登录后投票
   发表时间:2007-01-05  
没有看到我说的“不是测试的问题”么?

这里面dimple是用在production代码里面的。测试代码不用dimple。
0 请登录后投票
   发表时间:2007-01-05  
ajoo 写道
没有看到我说的“不是测试的问题”么?

这里面dimple是用在production代码里面的。测试代码不用dimple。



哦,不好意思,我满脑子都是测试,哈哈。 打错靶子了。

不过,我仍然想多啰嗦几句。


问题在于某个和第三方库或者legacy system集成的部分碰巧没有Map,而只有一个PropertyMap,这时就可以用dimple。

这个例子用Dimple确实可以,但是我看不出我直接用一个Utils.convertToMap的逻辑有何优势。


另外,对于你提到的需要拦截Connection.close ,而需要一个ConnectionAdapter 来统一拦截,以此提出了Dimple的设计。

我对这个出发点也提出疑义。  虽然这是一个很好的办法,但是我更倾向于用一个统一的接口来open,close Connection来达到统一拦截的目的,或许这个接口语义很弱,但是在一个项目/框架开发里面,把这个需求提到每个开发者的需求也不是很难的事情。

虽然,这里有点类似AOP的概念,但是对于AOP,正如ROD所说的,AOP不应该和OOP成为对立的关系,两者应该是互补的关系。 AOP应该在OOP设计良好的基础上成为良好的补充。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics