Question

So, recently I have been doing a lot of programming in Python. I have noticed that my programs can be somewhat hard to read. I usually have one main class which does everything, sort of like this:

class main:
    def __init__(self, *args, **kwargs):
        # Make baseline variables here
        self.foo = "bar"
        self.hello = 12345
        # Get starting input.
        self.inputted = self.get_input()

    def get_input(self):
        inputted = input("Hello, world!")
        return inputted

    def do_something(self):
        # Do data processing, make stuff, call other functions within the class.
        pass

main()

I have been doing this for purposes of making variable access easy. Considering how it messes with code readability, should I be using another approach? If so, what?

Was it helpful?

Solution

Refactoring

Lots of people have written tomes and tomes on the subject. Martin Fowler has some good advice. Highly recommend looking through his work, also take a look at Kevlin Henney.

Sprout and Split

The problem is that you are writing a god class. Which is not a bad first approximation when you don't know how to solve a problem. Its just not a great long-term solution.

Sprouting is a technique where you look for small snippets of coherent code in the class, and extract them out into a reasonably named function/method (also on the same class).

The benefit of doing this is that it is easy to de-duplicate small snippets of code distributed throughout the class, and it is also easier to make larger functions smaller by removing a couple of lines at a time from them.

The downside is that your class goes from having say ten functions, to having hundreds.

This is where splitting comes in. You will likely notice as you sprout methods that the methods start to form categories. These functions are about input, those functions are about calculation X, these ones are about error reporting, etc... You will find that most of the variables on self are only used by one or two of these categories of functions and often the data path will be linear. Created here, read there.

The trick is to create a new class with one category of functions. Move any shared state along with it, and perhaps add a constructor to set that state up. Now rewire the original class to call an instance of the new class when it desires that category of service.

The pro here is that the program tells you what its structure actually is. And it does this in a very mechanical way.

The downside is that the structure revealed to you is not likely to be good. After all you write a god class because you don't have a good structure in mind, and instead have opted for finding something that works, rather than something that works well. You will likely have to take what you have learnt and rewrite large portions of the architecture several times before it will even start to resemble a decent solution.

Licensed under: CC-BY-SA with attribution
scroll top