3

私は2つの結合されたクラスDhcpServerSessionManager. その結合につながった仕様で次の要件を取得しました。

  • DhcpServer禁止されている場合は、IP アドレスのリースを発行してはなりませんSessionManager(たとえば、セッションの作成中にエラーが発生した場合)。
  • SessionManager新しいリースの作成時にセッションを開始し、DhcpServerそのリースが期限切れになるかクライアントによって明示的に解放されるとすぐにセッションを破棄する必要があります
  • 一方、対応するセッションが停止したDhcpServer場合は、リースを破棄する必要がありますSessionManager(たとえば、sysadmin の要求によって)。

最初は、すべてのコードを 1 つのクラスにまとめたいという誘惑にかられました。しかし、責任は別のものだったので、私はそれらを 2 つに分割し、2 つのインターフェイスを作成しました。

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

次に、とで実装IDhcpObserverしました。そして、それがカップリングにつながりました。クラスは互いに直接依存していませんが、互いのパッケージで宣言されているインターフェースに依存しています。SessionManagerISessionObserverDhcpServer

SessionManager後で、セッション開始用の別のプロトコルを追加して、のロジックをそのままにしたいと考えています。私もそれを実装したくありませんIAnotherProtocolObserver

また、DHCP サーバー自体は、私のセッションの概念とは何の関係もありません。また、Twisted (私が使用している) には DHCP プロトコルの実装がないためSessionManager、パッケージにも依存関係のない別のプロジェクトとしてリリースしたいと考えました。

コードの断片を疎結合に保ちながら、仕様要件を満たすにはどうすればよいですか?

4

1 に答える 1

5

クラスを分離する良い方法は、eventsを使用することです。

したがって、何かが発生したときにイベントを「起動」する必要があります。例: がセッションを作成できた場合、「セッションが作成されました」というイベントを送信しSessionManagerます。そのイベントをリッスンDhcpServerし、受信時にリースを準備します。

必要なのは、残りの 2 つを作成し、イベント リスナーを構成する 3 番目のクラスだけです。

このソリューションの利点は、すべてをシンプルに保つことです。単体テストを作成する場合、必要なのは正しいイベントが発生したかどうかを確認することだけなので、常に 1 つのクラスのみが必要になります。

于 2012-08-23T08:50:19.547 に答える