`

从设计角度审视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了,注意是"要"哦

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

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

相关推荐

    重构糟糕设计的五步技能链

    温昱老师根据实践经验总结出五个不同质量级别的项目案例,这些案例从不同的角度揭示了设计对项目成功的关键作用: 1. **优秀**:设计合理,团队成员有成就感,项目按时完成,Bug少。 2. **良好**:设计尚可,项目能...

    CEDIT派生类,有个小小BUG

    在编程领域,派生类是面向对象编程中的一个重要概念,它是从一个已有的基类(这里指`CEDIT`)创建新类的方式。`CEDIT`通常是指MFC(Microsoft Foundation Classes)框架中的CEdit类,它是一个用于处理文本编辑控件的...

    写Java程序最容易犯的错误例析

    - 重新审视类的设计,确保每个类都有清晰的职责。 #### 7. Data Clumps(数据簇) **定义:** 数据簇是指一组总是同时出现的数据。这通常是因为这些数据紧密相关,但被错误地分散在多个类或方法中。 **问题:** -...

    Oracle管理艺术-顾问级DBA的思维锻炼与经验传承

    因此,DBA需要具备能够从不同角度审视问题,并且在必要时能够打破常规思维,创造性地找到问题的解决方法。 经验传承是书中另一个重要主题。顾问级DBA通常拥有丰富的实践经验,而如何将这些经验有效地传授给其他DBA...

    2020经典语句[参考].pdf

    19. 角度转换:看待问题时,尝试站在他人的角度,这有助于增进理解,改善团队关系,也有利于解决开发中的冲突。 20. 简单与本质:如同白开水与五彩饮料,软件开发有时也需要回归本质,专注于解决核心问题,避免被...

    C++编程初学者demo

    理解基本概念如变量、数据类型、运算符、控制流语句等是学习的基础。不要急于求成,把这些基础知识牢牢掌握。 2. 多加练习 理论知识固然重要,但实践演练更为关键。每学会一个新概念,都要亲自动手编写示例代码,并不断...

    【最新推荐】201X年度软件工程师年终总结范文(四)-实用word文档(2页).pdf

    在这篇年终总结中,我将详细分享我在过去一年中的经历与成就,以此作为自我审视和规划未来职业生涯的重要依据。 一、技术学习的扎实根基 作为软件工程师,技术的不断学习与进步是职业生涯的核心。今年,我开始了对...

    嵌入式C语言进阶之道

    合理地使用代码缩进、分割长语句、正确地书写函数参数以及大括号的使用规范,都是编写可读性强的代码所不可或缺的要素。 此外,模块化编程是嵌入式系统开发中不可或缺的技能。在实际工作中,通常需要与团队其他成员...

Global site tag (gtag.js) - Google Analytics