سؤال

I have two coupled classes DhcpServer and SessionManager. I got the following requirements in my specs that led to that coupling:

  • DhcpServer must not issue an IP address lease if SessionManager forbids that (e.g. an error occurred while creating a session)
  • SessionManager must start a session upon creation of a new lease by DhcpServer and destroy a session as soon as that lease expires or gets released explicitly by a client
  • On the other hand DhcpServer must destroy the lease if SessionManager stopped a corresponding session (e.g. by sysadmin's request)

At first it was tempting to put all the code into a single class. But the responsibilities were distinct, so I split them into two and created two interfaces:

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

Then I implemented IDhcpObserver in SessionManager and ISessionObserver in DhcpServer. And that led to coupling. Even though the classes do not depend on each other directly they do depend on the interfaces declared in each other's packages.

Later I want to add another protocol for session initiation leaving SessionManager's logic intact. I don't want it to implement IAnotherProtocolObserver as well.

Also DHCP server as such has nothing to do with my notion of session. And since there's no DHCP protocol implementation for Twisted (which I'm using) I wanted to release it as a separate project that has no dependencies neither on SessionManager nor on its package.

How can I satisfy my spec requirements while keeping the code pieces loosely coupled?

هل كانت مفيدة؟

المحلول

A good way to decouple classes is to use events.

So what you need to do is to "fire" events when something happens. Example: Send an event "session created" when the SessionManager could create a session. Make the DhcpServer listen for that event and prepare a lease when it receives it.

Now all you need is a third class which creates the other two and configures the event listeners.

The beauty of this solution that it keeps everything simple. When you write unit tests, you will always only need one of the classes because all you need is to check whether the correct event has been fired.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top