Best way to design a class in python

11,464

Solution 1

If each FooBar is responsible for bar then the first is correct. If bar is only needed for execute() but not FooBar's problem otherwise, the second is correct.

Solution 2

In a single phrase, the formal term you want to worry about here is Separation of Concerns.

In response to your specific example, which of the two examples you choose depends on the concerns solved by FooBar and bar. If bar is in the same problem domain as FooBar or if it otherwise makes sense for FooBar to store a reference to bar, then the second example is correct. For instance, if FooBar has multiple methods that accept a bar and if you always pass the same instance of bar to each of a particular FooBar instance's bar-related methods, then the prior example is correct. Otherwise, the latter is more correct.

Ideally, each class you create should model exactly one major concern of your program. This can get a bit tricky, because you have to decide the granularity of "major concern" for yourself. Look to your dependency tree to determine if you're doing this correctly. It should be relatively easy to pull each individual class out of your program and test it in isolation from all other classes. If this is very difficult, you haven't split your concerns correctly. More formally, good separation of concerns is accomplished by designing classes which are cohesive and loosely coupled.

While this isn't useful for the example you posted, one simple pattern that helps accomplish this on a broader scale is Inversion of Control (IoC, sometimes called Dependency Injection). Under IoC, classes are written such that they aren't aware of their dependencies directly, only the interfaces (protocols in Python-speak) which their dependencies implement. Then at run time, typically during application initialization, instances of major classes are created by factories, and they are assigned references to their actual dependencies. See this article (with this example) for an explanation of how this can be accomplished in Python.

Finally, learn the four tenets of object-oriented programming.

Share:
11,464
frazman
Author by

frazman

Updated on July 19, 2022

Comments

  • frazman
    frazman almost 2 years

    So, this is more like a philosophical question for someone who is trying to understand classes.

    Most of time, how i use class is actually a very bad way to use it. I think of a lot of functions and after a time just indent the code and makes it a class and replacing few stuff with self.variable if a variable is repeated a lot. (I know its bad practise) But anyways... What i am asking is:

     class FooBar:
           def __init__(self,foo,bar):
               self._foo = foo
               self._bar = bar
               self.ans = self.__execute()
    
           def __execute(self):
                return something(self._foo, self._bar)
    

    Now there are many ways to do this:

       class FooBar:
             def __init__(self,foo):
               self._foo = foo
    
    
           def execute(self,bar):
                return something(self._foo, bar)
    

    Can you suggest which one is bad and which one is worse?

    or any other way to do this.

    This is just a toy example (offcourse). I mean, there is no need to have a class here if there is one function.. but lets say in __execute something() calls a whole set of other methods.. ?? Thanks

  • user2392398
    user2392398 over 2 years
    Shouldnt you declare all input variables in init so you can easily see the interface of the object and program according to it. The second example looks like leakage to me because imagine many functions within the class and one of them has a variable that is not declared in init and is needed for the function. It is like buried/hidden from the programmer's sight