
God objects
God objects are a tempting consequence of bad software design and also badly implemented object orientation.
Essentially, a God object is an object with either too many methods or too many properties; essentially, it's a class that knows too much or does too much. The God object soon becomes tightly coupled to (referenced by) lots of other bits of code in the application.
So what's actually wrong with this? Well, in short, when you have one bit of code tied into every single other bit of code, you quickly find a maintenance disaster. If you adjust the logic for a method in a God object for one use case, you might find it having unintended consequences for another element.
In computer science, it is often a good idea to adopt a divide and conquer strategy. Often, big problems are just a set of little problems. By solving this set of little problems you can rapidly solve the overall problem. Objects should typically be self-contained; they should only know problems about themselves and also should only solve one set of problems, its own problems. Anything that isn't relevant to this aim doesn't belong in that class.
It can be argued that objects relating to physical objects should be instantiated, while those that don't should be abstract classes.
The flip side to God objects being an anti-pattern is when developing embedded systems. Embedded systems are used to process data on anything from a calculator to LED signage; they are small chips that are essentially self-contained computers and quite low cost. In this use case, with restricted computational power you can often find that programming elegance and maintainability become peripheral concerns. Slight performance increase and centralization of control can be more important, meaning using God objects can be somewhat sensible. Fortunately, PHP is incredibly seldom used to program embedded systems, so you are incredibly unlikely to find yourself in this particular situation.
The most effective way of dealing with these classes is to split them into separate classes manually.
Another anti-pattern, called Fear of Adding Classes, can also play a part in this, along with failing to mitigating it. This is where developers are reluctant to create necessary classes.
So, here's an example of a God class:
<?php class God { public function getTime(): int { return time(); } public function getYesterdayDate(): string { return date("F j, Y", time() - 60 * 60 * 24); } public function getDaysInMonth(): int { return cal_days_in_month(CAL_GREGORIAN, date('m'), date('Y')); } public function isCacheWritable(): bool { return is_writable(CACHE_FILE); } public function writeToCache($data): bool { return (file_put_contents(CACHE_FILE, $data) !== false); } public function whatIsThisClass(): string { return "Pure technical debt in the form of a God Class."; } }
So, as you can see that in this class, we've basically combined lots of irrelevant methods. In order to fix this, we can split this class up into two sub-classes, one being a Watch
class and the other being a CacheManager
class.
Here is the Watch
class; this class is simply intended to show us the time in various formats:
<?php class Watch { public function getTime(): int { return time(); } public function getYesterdayDate(): string { return date("F j, Y", time() - 60 * 60 * 24); } public function getDaysInMonth(): int { return cal_days_in_month(CAL_GREGORIAN, date('m'), date('Y')); } }
And here is the CacheManager
class; this class separates all the cache's functionality so it is entirely separate from the Watch
class:
<?php class CacheManager { public function isCacheWritable(): bool { return is_writable(CACHE_FILE); } public function writeToCache($data): bool { return (file_put_contents(CACHE_FILE, $data) !== false); } }