Blob (God Object)
This is a bloated thing that does everything. Usually a class that first grew into a universal problem-solver for the whole project, and then almost became an operating system.
It can appear because of bad architectural decisions or simply from encapsulating everything in a terrible hurry. Or from the gradual "improvement" of some class by several generations of developers who just wanted to slap on a workaround and move on.
This thing stops being fully object-oriented and takes us back to the dark ages of programming. In practice, I have seen such constructs in banking legacy. Everything designed roughly after the 2000s was already done with care — whether object-oriented or functional. Even old monoliths can be split into functions in a way that yields a modular structure that easily survives changes (it only ships together, but is developed independently).
Symptoms
- The class is huge and has a dozen responsibilities: business logic, validation, data access, logging, formatting.
- The module "knows everyone": it calls services, hits the database, builds reports.
- Almost every method takes and returns "everything under the sun".
- Any change has to go through this class.
Why it happens
Again, very often the blob is just the first symptom of deeper problems. I have seen brave people try to refactor it (and I took part a couple of times myself). Behind that pile-up there are usually dozens of specific bad practices.
I think I won't be far off the mark saying that every bank in Russia's top-10 has a system older than 15 years with a business-logic construct the size of a framework, around which handlers and various external interfaces are neatly arranged. The system itself resists decomposition and cannot be rewritten in the coming years.
Example
The "bad" version: one class that does everything:
class OrderService:
def create_order(self, cart):
...
def apply_discount(self, order, code):
...
def calculate_total(self, order):
...
def save_order(self, order): # data access
...
def build_invoice_pdf(self, order): # reports
...
def send_email(self, order): # notifications
...
def validate_customer(self, c): # business rules
...
The "good" version: the class delegates responsibilities to services:
class CreateOrderHandler: # orchestration
def __init__(self, pricing, storage, notifier):
...
def handle(self, cart):
order = Order(cart.items)
pricing.apply_discounts(order)
storage.save(order)
notifier.order_created(order)
How to fix it
- Split responsibilities by what changes together (the single responsibility principle).
- Break it into services and modules without touching external interfaces.
- First add characterization tests, then extract methods and classes one by one.
- Don't try to rewrite it all at once — refactoring proceeds in iterations.