2010-06-30 103 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相似呢,如果你喜欢 - 我通常会发现它有用这样做,因为它使单元测试更加容易,并保持协议的分析逻辑从应用程序逻辑中分离出来 - 但这取决于你。