【问题标题】:How to avoid class coupling when the specs insist on it当规范坚持时如何避免类耦合
【发布时间】:2012-08-18 17:18:06
【问题描述】:

我有两个耦合类DhcpServerSessionManager。我的规范中有以下要求导致了这种耦合:

  • 如果SessionManager 禁止,DhcpServer 不得发布 IP 地址租约(例如,创建会话时出错)
  • SessionManager 必须在 DhcpServer 创建新租约时启动会话,并在租约到期或被客户端明确释放时立即销毁会话
  • 另一方面,如果SessionManager 停止了相应的会话(例如,系统管理员的请求),DhcpServer 必须销毁租约

起初很想将所有代码放在一个类中。但是职责是不同的,所以我将它们一分为二,并创建了两个接口:

class ISessionObserver(object):
    def onSessionStart(**kwargs): pass
    def onSessionStop(**kwargs): pass

class IDhcpObserver(object):
    def onBeforeLeaseCreate(**kwargs):
        """
        return False to cancel lease creation
        """
        pass
    def onLeaseCreate(**kwargs): pass
    def onLeaseDestroy(**kwargs): pass

然后我在SessionManager 中实现了IDhcpObserver,在DhcpServer 中实现了ISessionObserver。这导致了耦合。尽管这些类不直接相互依赖,但它们确实依赖于相互包中声明的接口。

稍后我想添加另一个用于会话启动的协议,使SessionManager 的逻辑保持不变。我也不希望它实现IAnotherProtocolObserver

同样的 DHCP 服务器也与我的会话概念无关。由于 Twisted(我正在使用)没有 DHCP 协议实现,我想将它作为一个单独的项目发布,它既不依赖于 SessionManager 也不依赖于它的包。

如何在保持代码片段松散耦合的同时满足规范要求?

【问题讨论】:

    标签: python design-patterns architecture decoupling


    【解决方案1】:

    解耦类的一个好方法是使用events

    因此,您需要做的是在发生某些事情时“触发”事件。示例:当SessionManager 可以创建会话时发送事件“会话已创建”。让DhcpServer 监听该事件并在收到该事件时准备租约。

    现在您需要的只是第三个类,它创建另外两个并配置事件侦听器。

    这个解决方案的美妙之处在于它让一切变得简单。当您编写单元测试时,您总是只需要其中一个类,因为您只需要检查是否触发了正确的事件。

    【讨论】:

    • 这正是我所做的。我的观察者接口用于同样的目的。但这并不能解决问题:DhcpServer 需要知道SessionManager 将触发的事件类型,反之亦然。这与修改后的耦合相同。
    • 正如我所说:您需要在它们之间建立一个连接事件的类。它将接受“会话创建”事件,然后调用 DHCP 服务器上的方法,反之亦然。由于这个类比其他两个级别更高,它可以进行连接。这样可以保持服务类干净。
    • 所以,如果我理解正确的话,我的观察者界面没问题。但与其在DhcpServerSessionManager 中交叉实现它们,我应该介绍第三个。这个类将是实现观察者接口并调用DhcpServerSessionManager 的方法的中介,对吧?
    • @IhorKaharlichenko:是的,完全正确。将耦合移动到“配置”或“设置类”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 2011-08-12
    • 2018-03-19
    • 1970-01-01
    • 2012-05-02
    • 1970-01-01
    相关资源
    最近更新 更多