Tell, Don't Ask

原创 2011年01月24日 16:09:00

不知道看什么的时候看到了这篇文章,非常带感,所以这里写一些自己的感受。>>围观原文请猛击这里<<

 

啥是Tell,Don't Ask?

在这里,我把Alec Sharp大神的话摘抄在这里:

Procedural code gets information then makes decisions. Object-oriented code tells objects to do things. 
— Alec Sharp

我觉得这句话很好的将面向过程和面向对象区分了出来。也就是说,对于对象来说,我应该直接告诉它你该做什么,而不是先去问它的状态,然后根据这个状态再去告诉对象你需要做什么什么。

仔细回想一下,我还真在实际编程时做过这种事情:先去调用一个对象的getter方法得到某个状态,然后判断一下这个状态,最后根据这个状态调用对象的另外某个方法来让对象去完成某个操作。其实,仔细想想,对象的状态是什么样,该不该做,以及如何做都是对象自己该处理的,而不是我该操心的,这么做只能破坏了对象的封装,让调用它的代码和这个对象紧耦合起来。

 

那么,这个原则真的很重要么?

可以设想这样一种情景:我在程序中调用一个对象的某个getter方法,得到一个该对象的内部状态,比如得到的是一个String类型的东西。如果我接下来把这个String类型的东西用在了程序其它的地方,这时就产生了一种问题,我必须知道这个String类型的东西代表什么意思。比如说这个String类型的值是”RED”,那么,这个RED是什么意思?是一种颜色?还是一个人名?还是某种缩写?对于个东西的意思,那个对象再清楚不过了,而离开了那个对象,它就会被滥用和错用。

我们常说,一个对象就是数据和方法的抽象与封装。在我理解来看,就是使这写状态和方法有了上下文和语义,脱离了上下文,就破坏了它的封装。

 

除了上面所说的问题,还有么?

有!在编写程序的时候,难免与Iterator打交道。举个例子,比如有一组整数,我想在每个整数上加1,用Iterator的做法就是首先调用Iterator.hasNext()来判断是否为true,是的话调用Iterator.next()方法来取得一个整数,然后加1。但是这种做法在并行程序中就麻烦了。比如多线程程序,一个线程查询Iterator.hasNext()为true,但是另一个线程却在它之前调用Iterator.next()方法将最后一个数据取走了,那么前面的那个线程就杯具了。

仔细想想,其实我想做的仅仅是让这组整数自加1,我只要告诉这个对象:每一个都加1,就可以了。至于如何加1的,不应该是我考虑的事情,而是对象自己的事情。

换成代码应该是这样的:

 

好吧,我把该让对象做的,都移到对象内部去。

这样没问题了吧。我不在对象外边去查询它的状态了。我让对象内部自己去做。那么,是不是在对象内部我可以随便来查询和调用对象的方法了?

 

不行,我们要遵守迪米特法则(Law of Demeter)

迪米特法则也称为最小知识原则(Least Knowledge Principle, LKP),简单说,如果两个对象不必直接通信,那么这两个对象就不应当发生直接的相互作用。如果一个对象需要调用另外一个对象的某个方法的话,那么应该通过第三个对象来转发调用。迪米特法则可以简单的说成:Talk only to your immediate friends。

迪米特法则强调一个问题:如果我们在实现某个方法时调用的对象越多,那么我们的程序耦合度就越高。一旦某个地方需要修改,都会带来麻烦。所以根据迪米特法则,我们在实现对象O的方法M时,M能够调用的对象应该只有:

  • 对象O自己
  • M的参数
  • M内部创建的对象
  • O的直接组件对象

举个例子,我曾经这样写过某段代码:

代码很简单,我只是单纯的想往我们的商店中增加一本新的书。但是上面的这段简单的代码,依赖了bookStore、BookList甚至book对象,其实我们只是想单纯的在书店中加一本新书而已,我什么不能这么用呢?

这样,我们调用的代码仅仅以来bookStore一个对象了。

 

所以,请记住Tell,Don't Ask

这个真的可以帮助我,让我写出更加抽象的、松耦合的代码。

What Microsoft, Oracle, IBM, And SAP Don't Tell Customers

Share The four big software vendors -- Microsoft, Oracle, IBM, and SAP -- have hidden...

akka(tell,ask,send)

tell异步发送一个消息并立即返回。target.tell(message, getSelf());在Actor外部,如果没有回复,第二个参数可以为null;ask异步发送一条消息并返回一个 Futu...

Tell Above, and Ask Below - Hybridizing OO and Functional Design

I have an idea I’ve been holding back for a while because I think it is wrong.  It’s just too gene...
  • hnhbdss
  • hnhbdss
  • 2012年08月18日 23:02
  • 603

hdu 1798 - Tell me the area(求两圆相交面积) 解题报告

Tell me the area Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others...
  • Luwhere
  • Luwhere
  • 2015年08月10日 15:04
  • 535

关于APUE里面TELL_WAIT()之类函数的两种实现方式

Just a note.... #include static volatile sig_atomic_t sigflag; static sigset_t newma...

说一下你的思考过程 Tell me what you think(编程测试)

转自:http://blog.csdn.net/han_yankun2009/article/details/7647439 有这样一个脑筋急转弯的题目,不要试图去网络上寻找答案,思考一下,...

Click to tell us what you think:翻译成多国语言是啥样子

ar--Arabic(阿拉伯语) انقر لإخبارنا برأيك:   bg--Bulgarian(保加利亚语) Щракнете, за да ни кажете какво мислите...

How to Tell if the I/O of the Database is Slow - 2

IO的类型: 平均响应时间直接关联到具体的IO类型: 1. 读或写 2. 单块或多块         单块IO,指一次只读一个块。例如,当一个session等待一个单块IO时,典型的等待事件就是“db...
  • bisal
  • bisal
  • 2013年10月22日 18:19
  • 1741
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Tell, Don't Ask
举报原因:
原因补充:

(最多只允许输入30个字)