Alright, you got assigned to a team that is working on this - quite old - project and you're really looking forward into getting your hands dirty with some legacy code.
After a brief technical onboarding on the whiteboard by the techlead you go with her to a pairing station and start setting up the local environment for your first day of work. After exploring the code a bit you get to the Listing
class and, as you scroll the never ending file, you already start hating this Godclass.
And, as you wonder how that class got this big, you start imagining how the first weeks of work on this project were. Maybe after a discussion with some "business people" the team figured it would be necessary to have the Listing
class. From there it was easy to just add more and more stuff to it. This is a auction system after all, so it makes sense that the central element is a listing
.
As you read the methods and test cases, it all start to make sense. Since a listing can be in many states - like draft, preview, published, ... - you need to control all of that. And each state enables different behavior, so sure there are quite some if
s spread around the code. A listing also contains a lot of information, so there is definitely a lot of fields in the object. But hey, at least it has a lot of testing!
As you see yourself starting to agree that all this messy code actually makes sense, you stop and slap yourself in the face (but that's all in your head, so don't worry, no one saw it). No class, no matter how important, should be this big and violate the Single Responsibility Principle like that!
A class becomes a Godclass
Of course, right? No one creates a Godclass from day one, as the old saying goes: it takes a village to raise a Godclass.
A class turns into a Godclass because it just makes sense! Think about a domain and what would be a good candidate for a Godclass: an e-commerce will probably have a Product
, an auction system will have a Listing
, and is very likely that an aviation application would have a Flight
and a Passenger
. It just makes sense.
Usually a Godclass will capture the essence of your domain, like a Product
in an e-commerce, and it will probably become a central point of the design. Everything in an e-commerce platform revolves around people buying products, so the way you create a product, the way you show them and how you handle inventory is key.
Are we all destined to create a Godclass? Is it just a matter of time?
What if there's no Godclass?
If you work with an old enough system, you probably have a Godclass hanging around on your codebase (hopefully you'll have only one).
Now think for a minute, what if there was on Listing
class on an auction application? How would you go about modeling the domain without using this name? How would you group the behavior for publishing a listing and handling bids without using the word "listing"?
Think for a minute. Ok, just a few seconds will do, I know we're all busy these days.
...
It's hard right? It just makes sense to have a Listing
.
Not using a name that is central to your domain is probably a bad idea, since this name will capture the essence of your domain. But the exercise of completely eradicate the Godclass and banish the name from the vocabulary might be interesting.
If you don't have a Godclass, all that behavior will have to be split among other classes right? I mean, you'll have to support the same features and use cases, so the code will have to be there, somewhere. Will a new Godclass appear? Could some behavior be absorbed by an existing class? Can you identify what can be split in other classes? How those classes will look like?
Doing this exercise will provide good hints of how you could reduce the power of the Godclass and, potentially, improve the design of your application. It will also show how well you know your domain and how sharp your modeling skills are.
Don't forget that there's much more to software development than just writing code :)
Top comments (3)
Good piece, thank you! Decomposing these good classes into multiple classes and leveraging DI is probably the best way to manage the complexity. I find it helpful to graph a class and put complex or large amounts of functionality into their own classes.
The most GodClass that I've seen was related to a lack of understanding the domain. Normally, the domain class that I've seen were dummy class without any logic. And the logic is another class like service.
First thing I do when I get my hands on some legacy code is linting and static code analysis. Then I deem it worth looking at.