首页 > 编程 > 管理软件的隐藏复杂性

管理软件的隐藏复杂性

今天在bbs上看到一篇帖子,里面讲了这么一句话:有两种方式构建软件设计:一种是把软件做得很简单以至于明显找不到缺陷;另一种是把它做得很复杂以至于找不到明显的缺陷。很有意思的一段话。传说这段话来自于《A Byte of Python》,没看过,但是可以想象,既然来自于python的社区,作者应该是倾向于前面半句话的。

OK,现在是提问时间:为什么人们都在追求简单?正如这段话当中所说:软件做的简单的目的是为了能够减少缺陷。究其原因就是人类思考能力的限制:人们计算(1+100)*100/2和计算1+2+3+…+100的出错概率是不可以同日而语的。如果我们快速的过一下软件开发的历史,从最早的打孔纸带和汇编语言,到C语言和众多的具有不同设计哲学的高级语言,再到今日蓬勃发展的脚本语言,似乎都在做同一件事:让程序变得简单。这种简单源于语言对于特定概念的抽象和众多可以复用的库和框架,在这种软件简单性,源于封装起来的复杂性,在其背后,也许是更加复杂部分的逻辑。这种复杂性,也就是软件的隐藏复杂性。

显然,软件的隐藏复杂性是一把双刃剑,一方面,对于不必要复杂性的封装,让程序本身变得简单,能够更加直接 地表明业务的逻辑;另一方面,作为软件一部分的它们,本身也是一个软件,也有存在缺陷的可能,而一旦来自这种隐藏的复杂性当中的缺陷出来,却也会带来排错的巨大难度。从实际当中来说,这种隐藏的复杂性源于很多地方:操作系统,运行库,第三方库,以及框架。如何处理隐藏的复杂性,以及决定是否要引入一种隐藏的复杂性,这是一个项目的领导者必须做的一个决定。每个隐藏的复杂性都可以引入更简单的设计和更多的潜在的缺陷。

举几个例子吧,我们在做最近的一个产品的时候,出现了内存泄漏,经过一个星期的分析和排错,最终发现内存泄漏发生在微软的CRT库的istream当中;在同一个产品当中,beta客户处出现了程序hang住的情况,最终发现问题出在第三方的icu库当中。使用C++ iostream库和icu库毫无疑问使得程序变得简单,但是一旦出现了缺陷,却也是非常难以排除的。

还有其他的隐藏复杂性却有更隐晦的潜在问题,有些问题甚至无法解决。另一个小组正在做的项目当中出现了另一个问题,tomcat在特定的情况下可能崩溃。经过近半个月的排查发现,问题出现在JRE的socket对于solaris操作系统的socket封装问题:JRE的socket可能在系统已经将socket关闭之后再对其进行操作,这导致了tomcat的崩溃。这也是操作系统和运行库所带来的隐藏复杂性的代价。

但是这并不应该成为拒绝引入隐藏复杂性的理由,否则就是把孩子和洗澡水一起泼掉了。这里提到的几个例子都是源于著名的运行库,虽然出现了问题,但是它们所带来的便利也是毋庸置疑的。我们需要做的,就是在这种简单性和隐藏的复杂性之间做出权衡。

标签:
  1. No name
    2007年6月15日00:11 | #1
    呵呵,如何testing这种产品,倒真是个问题。
    是否需要流程test这种SDk问题呢?
  2. 益荣 杨
    2007年6月15日00:11 | #2
    恩,非常同意这样的观点,重要的在于不断的牺牲和斗争后,能够出现一个标准,然后就可以降低人们的成本。
  3. Zhang Cong
    2007年6月15日00:11 | #3

    其实我认为标准倒是次要的,因为即使有标准也会有不同的实现。更重要的是如果决定引入一种隐藏的复杂性的话,最好使用久经考验的技术和第三方库。软件的核心价值在于时间上的积累,这点我深信不疑。

    至于对于SDK的测试,我觉得对于产品没有什么必要。当然,对于构建SDK的公司,另当别论。

  4. å…‰ å­£
    2007年6月17日00:11 | #4

    我倾向于完善下层支持让软件简单。iostream人人都用,如果有错终有一天会被发现;如果cout的代码需要开发员自行编写,100个人会写出100个模样,花费了多少时间又有多少个错就更难说了。

  5. Zhang Cong
    2007年6月17日00:11 | #5

    是的。而且更多的可复用的组件的存在也应该是软件发展的方向。
    我写这篇文章的动机就在于,实际的项目当中,任何的第三方组件都是可能带来风险的,而这种风险,都应该纳入到软件开发的风险管理当中。

  1. 本文目前尚无任何 trackbacks 和 pingbacks.