Tell, Don't Ask

本文探讨了面向对象编程中Tell, Don't Ask的原则,强调直接指挥对象行动而非询问其状态的重要性,避免破坏封装性和提高代码的松耦合度。

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

 

啥是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

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

# Natural Language Toolkit: Teen Chatbot # # Copyright (C) 2001-2024 NLTK Project # Author: Selina Dennis <sjmd@csse.unimelb.edu.au> # URL: <https://www.nltk.org/> # For license information, see LICENSE.TXT """ This chatbot is a tongue-in-cheek take on the average teen anime junky that frequents YahooMessenger or MSNM. All spelling mistakes and flawed grammar are intentional. """ from nltk.chat.util import Chat reflections = { "am": "r", "was": "were", "i": "u", "i'd": "u'd", "i've": "u'v", "ive": "u'v", "i'll": "u'll", "my": "ur", "are": "am", "you're": "im", "you've": "ive", "you'll": "i'll", "your": "my", "yours": "mine", "you": "me", "u": "me", "ur": "my", "urs": "mine", "me": "u", } # Note: %1/2/etc are used without spaces prior as the chat bot seems # to add a superfluous space when matching. pairs = ( ( r"I\'m (.*)", ( "ur%1?? that's so cool! kekekekeke ^_^ tell me more!", "ur%1? neat!! kekeke >_<", ), ), ( r"(.*) don\'t you (.*)", ( r"u think I can%2??! really?? kekeke \<_\<", "what do u mean%2??!", "i could if i wanted, don't you think!! kekeke", ), ), (r"ye[as] [iI] (.*)", ("u%1? cool!! how?", "how come u%1??", "u%1? so do i!!")), ( r"do (you|u) (.*)\??", ("do i%2? only on tuesdays! kekeke *_*", "i dunno! do u%2??"), ), ( r"(.*)\?", ( "man u ask lots of questions!", "booooring! how old r u??", "boooooring!! ur not very fun", ), ), ( r"(cos|because) (.*)", ("hee! i don't believe u! >_<", "nuh-uh! >_<", "ooooh i agree!"), ), ( r"why can\'t [iI] (.*)", ( "i dunno! y u askin me for!", "try harder, silly! hee! ^_^", "i dunno! but when i can't%1 i jump up and down!", ), ), ( r"I can\'t (.*)", ( "u can't what??! >_<", "that's ok! i can't%1 either! kekekekeke ^_^", "try harder, silly! hee! ^&^", ), ), ( r"(.*) (like|love|watch) anime", ( "omg i love anime!! do u like sailor moon??! ^&^", "anime yay! anime rocks sooooo much!", "oooh anime! i love anime more than anything!", "anime is the bestest evar! evangelion is the best!", "hee anime is the best! do you have ur fav??", ), ), ( r"I (like|love|watch|play) (.*)", ("yay! %2 rocks!", "yay! %2 is neat!", "cool! do u like other stuff?? ^_^"), ), ( r"anime sucks|(.*) (hate|detest) anime", ( "ur a liar! i'm not gonna talk to u nemore if u h8 anime *;*", "no way! anime is the best ever!", "nuh-uh, anime is the best!", ), ), ( r"(are|r) (you|u) (.*)", ("am i%1??! how come u ask that!", "maybe! y shud i tell u?? kekeke >_>"), ), ( r"what (.*)", ("hee u think im gonna tell u? .v.", "booooooooring! ask me somethin else!"), ), (r"how (.*)", ("not tellin!! kekekekekeke ^_^",)), (r"(hi|hello|hey) (.*)", ("hi!!! how r u!!",)), ( r"quit", ( "mom says i have to go eat dinner now :,( bye!!", "awww u have to go?? see u next time!!", "how to see u again soon! ^_^", ), ), ( r"(.*)", ( "ur funny! kekeke", "boooooring! talk about something else! tell me wat u like!", "do u like anime??", "do u watch anime? i like sailor moon! ^_^", "i wish i was a kitty!! kekekeke ^_^", ), ), ) iesha_chatbot = Chat(pairs, reflections) def iesha_chat(): print("Iesha the TeenBoT\n---------") print("Talk to the program by typing in plain English, using normal upper-") print('and lower-case letters and punctuation. Enter "quit" when done.') print("=" * 72) print("hi!! i'm iesha! who r u??!") iesha_chatbot.converse() def demo(): iesha_chat() if __name__ == "__main__": demo() 把她的说话风格变得和正常人一样
最新发布
09-28
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值