BeginnerSoftware Engineer

Refactor a God class using SOLID

Take a realistic God class that handles HTTP request parsing, database writes, and email sending all in one place. Refactor it into three focused classes connected by dependency injection, applying the Single Responsibility and Dependency Inversion principles explicitly. The interface should not change from the caller's perspective.

Why this matters

God classes are the most common form of technical debt in production codebases. They are hard to test, hard to change, and impossible to reuse. Learning to decompose them using SOLID is not academic; it is the core skill that separates engineers who can work in any codebase from those who can only work in their own.

Before you start

Step-by-step guide

  1. 1

    Read the God class and list its responsibilities

    Write down every distinct thing the class does. Do not look for patterns yet; just list actions. A well-decomposed God class will have 3-5 clearly separable responsibilities. If you find more than 6, it may need two rounds of refactoring.

  2. 2

    Define interfaces for each responsibility

    Before writing any classes, write Python Protocols or TypeScript interfaces for each responsibility. An interface for a database writer might have a single method: save(record) -> None. Writing interfaces first forces you to think about contracts before implementation.

  3. 3

    Extract each class

    Create one class per responsibility, each implementing its interface. Move the relevant methods from the God class verbatim first; do not improve them yet. Verify each class can be instantiated and called in isolation before connecting them.

  4. 4

    Connect via dependency injection

    Rewrite the original class to accept the three new classes in its constructor rather than creating them internally. The caller now controls which implementations are injected. This is what makes the system testable; you can inject a mock database writer without changing the class.

  5. 5

    Write three unit tests

    Write one test per extracted class, injecting mocks for any dependencies. If a test requires more than 5 lines of setup, your decomposition may not be clean enough. The tests should be fast, isolated, and read like specifications.

Relevant Axiom pages

What to do next

Back to Practice Lab