Chinaunix首页 | 论坛 | 博客
  • 博客访问: 960022
  • 博文数量: 134
  • 博客积分: 7443
  • 博客等级: 少将
  • 技术积分: 1411
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-10 20:18
文章分类

全部博文(134)

文章存档

2012年(7)

2011年(29)

2010年(16)

2009年(6)

2008年(18)

2007年(58)

分类:

2007-12-30 13:13:50

使用面向对象的设计方法,可以产生很棒的设计,但也很容易搞出很糟糕的设计.为了更好地使用面向对象的方法,来听一下反对者的声音:

Stephen C Johnson: 面向对象的模型使得我们可以用聚少成多的方法来写程序。这通常是说,它提供了一种用结构化的方法写出烂面条般程序的方法。

一般观点认为,面向对象设计方法比传统的结构化设计方法要好。对象是“更好的模块”,他把属性和方法放在了一起,使用少量的接口对内部信息进行封装。但对象确实是“更难把握的模块”。面向对象有时候为坏的设计提供了一个好的理由。当前有些反对面向对象的声音,就是因为此。面向对象的设计方法优点和缺点都十分突出的,也许是因为越强大的东西越难以掌握吧。要更好地使用面向对象必须了解面向对象的缺点。

为了解公司软件的开发质量,最近做了许多代码阅读的工作。终结了一些面向对象常犯的错误。

面向对象为全局变量辩护

大家都知道使用全局变量是糟糕的设计,因为全局变量带来了过分地耦合,应该尽量的避免。许多初学者,在使用面向对象的语言之后,喜欢把设计出的全局变量,封装在一个对象里面,在定义几个接口函数对这些全局变量访问,这时全局变量好像消失了。甚至,一些对见多识广的程序员,这时会使用单件模式,把一个或多个全局变量放到一个全局唯一的对象中。没有了全局变量,程序员心安理得,甚至为自己使用了设计模式而骄傲。可是全局变量其实没用消失,而是使用一个“单件对象”的面目把自己隐藏起来,他所带来的过分耦合没用消失,甚至是加重了:如果你把几个无关的全局变量封装到了一起,原来共享一个全局变量的模块,现在要和更多的模块共享这个全局对象。

过度使用胶水层封装别人的代码

在代码中我发现,有许多helper形式的类。在多个人开发的项目中,许多程序员不喜欢直接使用别人提供的接口。而是按照自己的调用习惯进行封装。甚至常常创建一套新的逻辑来封装旧的逻辑,甚至创造更复杂的逻辑来隐藏一个简单的逻辑。结果这个厚厚的胶水层,增加了整个系统的复杂度,特别是增加了debuging的难度。程序员很可能是担心别人的东西发生变化,而使用这个胶水层把自己保护起来,希望:万一别人发生变化,自己只修改这个胶水层就可以了。往往实际的效果是:因为这个胶水层要调和双方的逻辑,当发生变化时,不太容易修改它。在传统的面向过程的语言中,这种情况就相对较少,传统的语言更鼓励对别人的函数进行简单和直接地调用。

所有的基类都定义成虚类(或接口)

“接口与实现分离”,程序员一但掌握便开始坚信的哲学。“要为未来变化准备好”,将来我可以在不改变接口的情况下,添加一个子类实现,而对其他模块不产生影响。其实,基类还是是实现子类公共行为的地方。把子类的公共逻辑放到基类里面,子类就不需要重复实现这些逻辑。这样对未来准备得更好,当添加一个新的子类实现时,你不需要重复实现已经有的功能。

举个例子:

  1. 设计一个类ConfigInfo,其对象保存程序需要的配置信息。设计合适的数据结构,对象aConfigInfo把配置信息从外部的存储介质加载到内存中。
  2. 其他模块就可以通过aConfigInfo提供的接口访问这些配置信息。
  3. 当接受到配置信息更新信号时,发“重新加载”的消息给aConfigTable。
  4. 存储配置信息的存储介质可能是文本文件,也可能来自数据库中。分别使用两个子类实现:ConfigDbImp和ConfigFileImp。

如果把ConfigInfo定义成接口,ConfigDbImp和ConfigFileImp会重复实现存储配置信息的数据结构,重复实现内存中配置信息的访问接口,两个子类会有许多相似的代码。如果这些行为都交给父类实现,每个子类就可以只重写一个load()操作:把配置信息从外部的存储介质加载到内存。另外,如果这个东东用在多线程环境,线程同步的所有逻辑也可以交给基类ConfigInfo实现。如果将来出现了一个新的配置文件格式,只需要定义一个新子类并重写load操作。

(未完待续)

阅读(3972) | 评论(7) | 转发(0) |
0

上一篇:木桶效应2.0

下一篇:胆小鬼游戏

给主人留下些什么吧!~~

GFree_Wind2011-12-31 10:28:19

虽然我工作中一直用C,但是也不妨碍应用面向对象的思想。我个人还是挺喜欢C++和面向对象的。

不过正如博主在文中所言,滥用面向对象,设计出来的东西比面向过程要难以维护的多。

不过罪恶在于使用菜刀的人,而非菜刀

chinaunix网友2010-09-12 18:53:42

linux之父,linus炮轰C++时也提到:C++会导致非常非常糟糕的设计选择. 我现在视乎有些理解了

cuichaox2008-01-04 17:46:10

你说的很对: (1)这篇文章并非在批评“面向对象”(2)我日常就是使用面向对象的设计方法。(3)如文章开头所说,“面向对象”可以产生很棒的设计。(4)我整理的这些:人在面向使用对象时,容易犯的错误。因为我认为,了解这些错误对更好的使用面向对象很有意义。(5)要用好一个东西,必须了解它的缺点的一面。面向对象的方法难以掌握,正因为这个缺点,所以更容易犯错误。为了掌握它,必须了解这些。 好的设计会来自“懒惰”,也会来自过于”勤奋“,不晓得简化和重用的勤快人很多。---应该这样概况:好的设计人员脑勤手懒,差的程序员手勤脑懒。 对应用领域的理解肯定是必要的,这是必要条件,这很对。这让我想起来另外一个情况:人都寄希望与在应用领域直接抽象出概念,构造对象模型,面向对象的设计方法,也是这样讲的。可是:并非所有的领域都能直接抽象出对象。面向对象的方法在三个领域最为成功(计算机图形,GUI和模拟现实)。因为这三个领域能容易抽象出模型,而其他其他领域,并没有像人们开始想象地那样能直接地寻找到对象(这个说法来自《UNIX编程的艺术》)。 这样的领域中,更多的概念来自设计人员的“发明”而不是

fera2008-01-04 11:04:13

其实糟糕的设计来自于懒惰和对应用领域的背景知识不了解导致的,并不是由面向对象方法带来的。OO的本质是识别和组织应用领域地概念,但是有多少人能够“完美”地掌握这些概念并对概念进行分组?例如window窗体类的设计,相信会有很多不同的设计,这是因为大家眼中看见的概念互不相同。 所以不能简单的把糟糕的设计归咎于OO方法。

chinaunix网友2008-01-02 10:57:51

額,,, 確實經常有helper