`

从设计角度审视Bug - 卫语句&良好的接口

阅读更多

最近项目组里有一个bug,虽然我们大家都没有因为他而享受到“深夜静静改bug”的“乐趣”,但他也着实郁闷了我们一番。还好我们的Mr S同学已经将他拿下,在这篇blog,将记录下我看到这个bug时的思考:

 

bug描述:我们既存的一个连接池出现了泄漏问题。

 

bug原因:

我们有下面这么一个函数

 

void freeConnection(String type, ConnectionAdapter con);

 因为我们有两个连接池,一个叫做Derby,一个叫做demo,使用一个字符串指明链接要网哪里还。然而问题来了,以前的一位同事,写下了下面这样的代码:

String dbConnType = "derby"
......

db.freeConnection("dbConnType", conn);

 是的,因为根本不存在dbConnType这么一个连接池。所以运行一段时间之后,我们的的连接池里面没有了链接。

 

bug改修:

那么这个bug该怎么改呢? 拿掉那个变量的双引号?我想不是的。好的办法我认为有几个,最后一个是前面几个的递进,但他们思考的角度都是让接口更友善,让使用更方便:

 

1.  从freeConnection的角度思考,在freeConnection里面加卫语句。

     既然我们能确定我们的代码中只有两个pool,那么当freeConnection在接受到"derby"和"demo"这两个参数以为的参数的时候,他就应该报告他的调用者,说:“嗨,你使用我使用错了。” 比如我们可以抛出一个IllegalArgumentException。

 

2.  从freeConnection的调用者的角度思考。改变freeConnection的调用参数。

     这个问题的一个很隐晦的地方在于,使用了字符串来标识,我们要释放拿个池的链接。而程序中又充值着这样的使用方法。

db.freeConnection("derby", conn);             //想加引号,因为想直接释放derby这个池

db.freeConnection("dbConnType", conn);   //不想加引号,无用了,但是编译器没有帮我们区分过来。

 

    这两个用法本身就很容易混,那么从freeConnection函数的使用者看来,完全有理由呼吁一个更友善的接口,比如像下面这样

 

ConnectionManager{
    ...
    public static final  ConnectionPool  DERBY_POOL = ...
    public static final ConnectionPool  DEMO_POOL = ...
    ...
}

void freeConnection( ConnectionPool pool , ConnectionAdapter con);  

 

    这样做的好处是,利用类型保证了参数不会被误传,但是这样做的同时也暴露了很多东西,引来了其他的一些不可取之处。比如带着一个没用的参数,还是一个链接池,在代码各处跑来跑去,这么麻烦我们当初还为什么要写ConnectionManager

 

3.  综上,所以有了方法三:freeConnection方法的接口其实根本就应该是这样的;

      freeConnection(Connection conn);

是的,总之是用户传递错误了参数,那么与其像上面那样,帮助用户传递正确的参数,到不如压根就不要求用户传递这个参数。而且,既然你有意要做一个ConnectionManage,那么关于这个池那个池的,本身就应该封装在你的里面,Don't make user think了。

 

恩,事情说完了。<!----><!----> <!---->保证质量是多方面的,不是很努力的测就可以解决的问题,先撇开测试调试的技巧之类,其势必也受质量等其他因素的制约。好的设计从哪里来呢?好的设计应该即是程序员推敲的结果,又是他们的直觉使然。

分享到:
评论
1 楼 wjason 2009-01-08  
时隔这么久, 今天终于要改这个bug了,注意是"要"哦

看到不够美的代码我总是很想第一时间来重构他, 干掉他.
然而实现这个愿望在我们的组织里面还有很多阻力.

写代码, 虽有兴, 然未尽兴.

相关推荐

Global site tag (gtag.js) - Google Analytics