3

I'm writing a high level wrapper around the Python socket.socket object. Specifically, I want to do this for IPv4 TCP sockets (though it would be useful to be able to expand the library later with other families / types). As you may know, the socket module defines these as socket.AF_INET and socket.SOCK_STREAM. Is it a good idea to 'copy' these constants and make them constant class attributes, i.e.:

import socket


class IPv4TCPSocket(socket):
    FAMILY = socket.AF_INET
    TYPE = socket.SOCK_STREAM

    def __init__(self):
        ...

Or should I refer to them directly? I get this may seem like a weird question since they're already constants in the socket module, but referring to them by <libname>.socket.AF_INET may be a bit awkward. Any thoughts on this?


As an alternative I just leave out the class attributes and initialize like this:

super().__init__(family=socket.AF_INET, type=socket.SOCK_STREAM)

This entirely leaves out a reference to the socket family and type, which I guess isn't a problem, except if someone else needs to create a custom socket (or derive one from IPv4TCPSocket):

from <name> import IPv4TCPSocket as sock


print("Creating a new socket with family {} and type {}!".format(sock.FAMILY, sock.TYPE))

As opposed to

import <libname>

print("Creating a new socket with family {} and type {}!".format(<libname>.socket.AF_INET, <libname>.socket.SOCK_STREAM))

It's slightly more work and doesn't feel like an intuitive public interface to me. And hey, I may just be turning this into a way bigger problem than it really is, but I do that a lot :)


Second edit: new thoughts on the matter. After reading James' comment I found out (again, duh!) that socket.socket.type and socket.socket.family exist, which return the socket instance's type and family respectively. So, since I want to separate class behavior on a type & family basis, I may not subclass socket at all. The question remains the same, however, since each of those wrapper instances need a private _socket attribute of sorts as well.


The only real motive I can find to do this is to make the public interface easier to use. Or I might as well leave the attributes out altogether since the class name describes the socket. Decisions, decisions.


Answers are still very welcome, but I've decided to remove the constants and just let the class name signify its family and type.

5
  • 2
    It's difficult to tell exactly what you're considering. Not using FAMILY or TYPE? Not inheriting from socket? Could we see some example code with the alternatives you're considering? Dec 5, 2017 at 20:50
  • 3
    I wouldn't duplicate constants that already exist, unless you need to do so for reasons of brevity. The whole reason for having a constant is to provide a single point of definition. Having multiple constants that mean the same thing defeats the purpose. Dec 5, 2017 at 20:53
  • What's the benefit of adding private copies? You'll always be setting them to public values in scope. Dec 5, 2017 at 20:54
  • @CandiedOrange I clarified a bit, but if you'd prefer to see larger code samples, no problem.
    – Daniel
    Dec 5, 2017 at 22:13
  • 1
    @Coal_ It looks to me that your classes provide an abstraction for the families/types so you don't need to expose them in your high level interface. You would be mixing different levels of abstraction. Dec 6, 2017 at 11:39

1 Answer 1

3

Generic answer to the the question:

The real design question is if you want to leak or show the underlying dependencies of your library. Unless you really have good reasons to, it is better not to expose the inner "building materials" of your software on its APIs. Ignorance is bliss here.

The first and most important reason is that if you "hide" what you are using, your library is not married to that dependency until death tears them apart. If one day you found another library that serves your purposes better (or you decide to implement that functionality yourself), you can do the swap without your users noticing it.

And then, another reason is that most of the times your users are looking for an abstraction/simplification over the raw low-level libraries. They want "don't make me think" solutions with minimalist, elegant APIs that allow them to get shit done quickly and without wasting any extra brain cycles. If you expose or leak internal details on your API, you are just making your users have to know unnecessary details and making their life harder for no good reason.

That said, there are situations in which you may want to "get married" and have some kind of "leaky APIs" instead of a full fledged abstraction. For example if you provide extra functionality in a given subclass, and want your users to use your new class as a drop-in replacement.

Concrete answer to your problem:

If you are designing a class called IPv4TCPSocket, it does not make any sense to make family or type in any way visible or configurable, since a TCP socket pretty much defines a given family and type. Doing so would just confuse users and make the abstraction kind of absurd. The cleanest approach would be to store the underlying socket instance in private members of your class, and expose the desired members.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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