2010-06-30 102 views
1

查看twisted.words.protocols.irc.IRCClient,在我看來,似乎有一些奇怪的冗餘方法。例如,有一種方法「PRIVMSG」也是一種方法「irc_PRIVMSG」作爲客戶端方法的'METHODNAME'與扭曲的irc_'METHODNAME'

另一個例子考慮「加入」和「irc_JOIN」

我想知道的是爲什麼冗餘,這些都是隻有兩個許多例子。兩種不同的類型在不同的環境中使用嗎?我們應該使用一種類型而不是另一種?

回答

4

您對正在不同環境中使用的兩種不同類型的方法有正確的認識。通過檢查IRCClient處理收到的數據的方式,可以很容易地看到這一點。第一它解析它們變成線,然後將其分割線向上並傳遞件到其自己handleCommand方法:

def handleCommand(self, command, prefix, params): 
    """Determine the function to call for the given command and call 
    it with the given arguments. 
    """ 
    method = getattr(self, "irc_%s" % command, None) 
    try: 
     if method is not None: 
      method(prefix, params) 
     else: 
      self.irc_unknown(prefix, command, params) 
    except: 
     log.deferr() 

這是這是在扭曲的協議實現相當普遍,並且甚至更通常的圖案的一個例子,在Python程序中是一個整體。某些輸入部分用於動態構建方法名稱。然後使用getattr查找該方法。如果找到了,它被調用。

由於服務器發送客戶端線,如「PRIVMSG ...」和「加入...」,這將導致IRCClient看着像irc_PRIVMSGirc_JOIN方法。

這些irc_*方法只是調用拆分,但其他方式未分離的行剩餘部分。這提供了與該消息一起提供的所有信息,但它並不總是最好的數據格式。例如,JOIN消息包括包含主機掩碼的用戶名,但通常主機掩碼是不相關的,只需要暱稱。所以JOIN做一些事情,是相當典型的irc_*方法:它原來粗糙的數據到更多的東西更易操作,並傳遞到userJoined結果:

def irc_JOIN(self, prefix, params): 
    """ 
    Called when a user joins a channel. 
    """ 
    nick = string.split(prefix,'!')[0] 
    channel = params[-1] 
    if nick == self.nickname: 
     self.joined(channel) 
    else: 
     self.userJoined(nick, channel) 

你可以看到,這裏還有這裏的條件,有時請致電joined而不是userJoined。這是將低級數據轉換爲應用程序開發人員更容易使用的另一個示例。

此分層應該可以幫助您決定處理事件時要覆蓋哪些方法。如果最高級別的回調(如userJoined,joinedprivmsg)滿足您的要求,那麼您應該使用這些回調,因爲它們會使您的任務變得最簡單。另一方面,如果他們以不方便的格式顯示數據,或者以其他方式使用這些數據很尷尬,則可以降至irc_*級別。您的方法將被調用,而不是在IRCClient上定義的方法,因此您可以使用較低級別的格式處理數據,並且甚至不會調用較高級別的回調(除非您在覆蓋方法時也調用基本實現) 。

您還會發現有一些IRC消息,其中IRCClient甚至沒有定義irc_*方法。正如我們上面在handleCommand方法中所看到的,這些全部轉到irc_unknown回調。但是如果您在IRCClient子類上定義了irc_*方法,則handleCommand將開始將數據傳遞給該方法。顯然在這些情況下,您唯一的選擇是定義irc_*方法,因爲沒有更高級別的回調(如irc_PRIVMSG/privmsg案例中的privmsg)。

你可以構建你的irc_*方法的實現方式IRCClient相似呢,如果你喜歡 - 我通常會發現它有用這樣做,因爲它使單元測試更加容易,並保持協議的分析邏輯從應用程序邏輯中分離出來 - 但這取決於你。