2

I have a Launcher class that manages (check if they're alive and if not respawns them, also starts, etc.) Clusters which are processes launched through the multiprocessing Discord module.

To post relevant code:

class Launcher:
    def __init__(self):
        self._clusters = []
        self._active = False

    def _keep_alive(self):
        while self._active:
            for cluster in self._clusters:
                ...

            time.sleep(1)

    def start(self):
        self._active = True
        for i in range(5):
            cluster = Cluster(str(i))
            self._clusters.append(cluster)
        self._keep_alive()

class Cluster:
    def __init__(self, name):
        self._name = name
        self._process = None

    def start(self):
        self._process = multiprocessing.Process(target=bot.Bot, name=self._name, daemon=True)
        self._process.start()

My question is fairly straightforward, I think designing this is easy but I'm not sure how to deal with it in a "Pythonic" way. The Launcher should be able to get to check whether the process is_alive() or it's exitcode.

How should I expose the self._process variable of Cluster to the Launcher class? Or exposing what it needs to function?

My original idea was to have two functions that returns the data the Launcher requires:

def is_alive(self):
    return self._process.is_alive()

@property
def exit_code(self):
    return self._process.exitcode

But I feel the more information I need it would become bloated. Another idea I thought of is to just:

def process(self):
    return self._process

Or just simply accessing cluster._process from the Launcher directly. I know there's no concept of private variables and it's up to the developer on how it's accessed and used which means I could also change whatever self._process is outside of the class.

What would make the most sense in these type of cases?

1 Answer 1

4

A class becoming "bloated" is not a good reason to expose internal data if the methods are still cohesive. While a large class can indicate it is doing too much, is is not an automatic decision to split the class up or expose private members to the outside world. Certainly don't expose private members simply because the class "might get too big." As soon as you expose internal state, external code can change this state in unexpected ways. You already have enough external forces to account for when managing processes. Don't add any more.

Instead of worrying about the size of the class now or in the future, focus on designing a proper abstraction so that consumers of the Cluster class do not need to worry about the internal state. This makes it easier to use this class, and extend it in the future if necessary. Even if you add 30 methods to the Cluster class that simply pass through to the Process class, it is often the methods you don't include that make the abstraction work.

For example, say you want to provide an easy interface to query for information about this process, but you explicitly do not want consumers of the Cluster class to kill the process or restart it. Simply don't provide those methods in the Launcher. This can simplify the Cluster's job of managing processes because only the Cluster (and the OS) can modify this process.

There is no "Pythonic" way of doing this. This is about the fundamentals of object-oriented programming:

  • Encapsulation — consumers cannot do something to the Cluster's internal state without the Cluster knowing about it.

  • Data hiding — the Process is concealed behind the abstraction provided by the Cluster class.

In summary:

  • Don't expose the Process object.
  • Keep adding methods to the Cluster class. Don't worry about the size of this class as long as the methods remain cohesive with each other.
2
  • Thanks! This is very informative. Just one question: On "Keep adding methods to the Launcher class. Don't worry about the size of this class as long as the methods remain cohesive with each other." Did you mean here to keep adding methods on the Launcher class or the Cluster class?
    – Blastcore
    Commented May 9, 2022 at 3:09
  • 1
    @Blastcore: I misread your question. Let me fix it. My advice remains the same, though (yes, keep adding methods to the Cluster class). Commented May 9, 2022 at 11:24

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.