-1

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?

4
  • Is there any particular reason why this should be a class? Commented Jan 6, 2020 at 14:28
  • See the last paragraph. Commented Jan 6, 2020 at 23:13
  • It's a class "to make variable access easy"? These are basically global variables and the usual rule of "try not to use global variables" applies. Commented Jan 7, 2020 at 11:03
  • @user253751 What I mean is that, while yes: you should not use global variables, sometimes you need to pass variables between functions, which can be a pain. By using the class approach, I can avoid the otherwise necessary globals. Commented Jan 7, 2020 at 14:59

1 Answer 1

5

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.

3
  • Thank you, this is very helpful. ++1. Commented Jan 6, 2020 at 0:28
  • I've struggled for a long time with how to communicate techniques for refactoring code from large classes into many small classes. The terms "sprouting" and "splitting" do a great job of this. Great answer! +1 Commented Jan 8, 2020 at 22:56
  • @GregBurghardt I wish I had come up with them, but I can't lay claim. I read them in a book. I think it was called: Working Effectively with Legacy Code.
    – Kain0_0
    Commented Jan 8, 2020 at 23:17

Your Answer

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

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