2

I'm in the process of writing an bidirectional, asynchronous socket server and server handler. The base handler class I'm working off of is as follows:

class BaseAsyncSocketHandler:
    async def send(self, data: bytes) -> int

However, I want to write a subclass that sends two arguments, an event and arbitrary corresponding data, which suggests the signature:

   async def send(self, event: str, data: object) -> int:
       return await super().send(event_data_magic_to_bytes(event, data))

Unfortunately, this violates the Liskov substitution principle, and I don't think writing it as a mixin will makes the situation any better, so I'm hoping somebody has either seen this before or can think of a better design pattern (or tell me this is an unnecessary abstraction in the first place).

  • Does your subclass allow its users to send arbitrary bytes in addition to sending event/data combinations? – Bart van Ingen Schenau Apr 13 '17 at 6:11
  • No, it wouldn't. I intended for the data bytes to consist of the packaged event and serialized object. I definitely was considering optional/keyword arguments, if that's what you were suggesting though. – noahbkim Apr 13 '17 at 13:55
  • Why not change the name of the method? Liskov substitution is about behavior specifications as well as signatures, but in this case, I think you are only talking about the signature. – Frank Hileman Apr 13 '17 at 22:44
  • Ultimately, this is sort of what I did. I'll add my solution below. – noahbkim Apr 13 '17 at 23:13
  • 2
    Why are you even using inheritance? That's the real issue here! – gardenhead May 14 '17 at 3:51
2

In the end, I settled on providing the following:

class BaseAsyncSocketHandler:

    async def _send(self, data: bytes) -> int:
        ...

    @abc.abstractmethod
    async def send(self, *args, **kwargs) -> int:
        pass

This way the user can implement subsets of the send method while using the base send method provided by the socket wrapper. As to why I wanted to use send instead of just creating another class method like send_event, I think I mostly just wanted the interface to the class to remain compact and usable while allowing for different socket methodologies.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.