当一个对象方法什么都没干时

oschina
 oschina
发布于 2013年12月12日
收藏 47

本文作者介绍

Michael Feathers

Michael Feathers是Object Mentor International公司的技术顾问。他的工作不仅是技术开发,他还参与对世界各地技术团队进行培训、指导等工作。他曾开发了将JUnit迁移到 C++的CppUnit的初始部分,还有FitCpp——一个C++版的FIT基础测试框架。他是《Working Effectively with Legacy Code》一书的作者。

重构的方式千差万别。当在分析一个很大的方法时,我会首先看一下它的整体结构,心里对如何分解它有了一个初步的感觉。里面的条件判断代码块通常都会是我认为有问题、可以入手的地方。

    if (...) {
      ...
    }

当看到有一个像这样的if语句后,我知道我面临着选择。我可以 提取这个if语句以及和它相关的代码块到一个新方法里,或者我只提取相关代码块。我并不知道这样或那样做哪一种更好——这要根据上下文来判断。有时候这个 条件语句非常重要,有必要重点突出它,而另一些时候,这些if语句和它的代码块可以干净的提取出去,使得调用它的程序的显得更整洁干净。但是,我们如何调 用这个提取出去的方法呢?

让我来看看一个实际例子:

    if (alarmEnabled) {
      Alarm alarm = new Alarm();
      ... 
      ...
      alarm.sound();
   }

我们可以把整个if语句和它的代码块提取到一个叫做soundAlarm的方法里。

    soundAlarm();

这样好吗?

大多数人最初的反应会说:现在的这块代码有时会说谎。它告诉我们它将要响起警报,但有时候它并不响。通常,如果有这样说谎的代码不是一件好事,所以,选择另外一种重构策略可能更好:

  if (alarmEnabled) {
    soundAlarm();
  }

但是,这样看起来并不像之前那样干净。

这 种两难抉择让我想起了Null对象模式。Null对象模式就是一种经常会让人感觉代码在说谎的另一个例子。在主调代码里,我们看到有消息发送到一个对象, 但让人震惊的是,我们发现相应的动作并没有发生。但并不是所有的人都会有这种感觉。我所在的这个团队里大量的使用了Null对象模式,我们对代码的理解有 这样的共识:当你告诉一个对象做X时,有时候它并不去做——发送执行X的消息意味着有时X事件并不一定会发生。这要由这个对象决定。

我的直觉告诉我,这没什么,但你需要理解为什么会这样,这是十分重要的——这是一个内部的理解问题。

如果说多态有任何意义,它至少在说对象是自己管理自己的。我们给它发送一个消息,这是由它来决定应该去做什么。这是面向对象的核心,也是 Alan Kay 最初的对对象的认识之一——消息只是它们的信息传递。这种观点在如今并不占主导地位。

当我非常想让这种提取变的更易懂时,我通常有两种策略——使用一种意指一个事件的名字,或泛化这个操作。在这种情况下,我会选择使用一个事件风格的过去式的名字。

   intruderDetected();//入侵检测

这种事件风格的命名方式的好处是,它强调了事件条件,而不是动作。现在,我们可以将任何想要的东西都放到intruderDetected方法里。

我们还可以选择去泛化这个操作。相对于说我们要想起警报,我们可以换成说我们要向世界通知一个关于我们的状态的信息。

  performNotifications();//执行通知

如果使用一个像performNotifications这样的名字,我就能使事情变得抽象。这里的通知是一个还是多个并不重要。关键是,主调程序触发这个动作,但不意味着动作没有发生就可以解释成在撒谎。

尽管这样,我仍然疑惑,我们是否应该永远不要相信一个显示它肯定将会做某事的方法名?

如果它没有做,我们可以认为它在撒谎吗?

[英文原文:When A Method Can Do Nothing ]

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处,尊重他人劳动共创开源社区。
转载请注明:文章转载自 开源中国社区 [http://www.oschina.net]
本文标题:当一个对象方法什么都没干时
加载中

最新评论(22

sky-update
sky-update
或者是一个抽象的
void onRequestDoSomething(){
//do something,至于我做不做,如何做,调用者不需要关心,但是不管怎么样,if死活是少不了的哇
}
sky-update
sky-update
没太看懂,不通过
boolean tryDoSomething(),
boolean requestDoSomething()这种情况用的比较多
自由建客
自由建客
过犹不及
BaiYang
BaiYang
连 if 一起提取的时候方法名应更确切点就可以了,比如:
soundAlarmIfNeeded();

使用 NULL 模式时也是一样的道理,可以叫 TryDetectedIntrusion() 之类的。
无忌
无忌
文章主要讲到:
将if里的代码提取出来做为一个方法,代码理清晰
更好的方法命名
提到Null Object 模式
cgcgbcbc
cgcgbcbc

引用来自“ddatsh”的评论

引用来自“石头左边”的评论

void sound_Alarm_If (bool alarm_enabled)

+1

这是ruby的习惯吧...
yuzhouliu
yuzhouliu

引用来自“Vect”的评论

引用来自“ueharaai”的评论

这种文章给懂的人看懂的人理解,不懂的人看,还是不懂,大量的编程实践在里面,不是靠理论能够获得的感悟。

同意

严重同意
酒逍遥
酒逍遥
此 对象 非彼对象
张乐1024
张乐1024
貌似理解到了一些东西!
小小志
小小志
are you ready ,go
返回顶部
顶部