Monolithic class handling all tasks
Backend & Runtime / Knowledge library
Single Responsibility Principle
Gives a module one coherent reason to change
Why learn Single Responsibility Principle?
It keeps responsibilities focused and change impact local
The problem it solves
It reduces unrelated behavior accumulating in one component
Where it came from
Single Responsibility Principle is a software design principle that gives a module one coherent reason to change. Its guarantees and tradeoffs depend on the concrete implementation and operating context.
Build your understanding
Work through these exercises in order. Try the task before opening a reference.
- Define Single Responsibility Principle and distinguish it from a neighboring concept.
- Choose a realistic task where Single Responsibility Principle is appropriate.
- Identify a failure mode caused by misusing Single Responsibility Principle.
- Interpret a small design or result involving Single Responsibility Principle.
- Explain one tradeoff or limitation of Single Responsibility Principle.
Documentation and sources
- Software Engineering at Google (abseil.io)
Connect the ideas
Explore next
Real World Example
Automated Logistics Invoice Processing
A regional logistics firm managing thousands of daily freight shipments.
The business problem
The firm utilized a monolithic 'ShipmentManager' class that handled database persistence, PDF invoice generation, and external API communication for customs clearance. When the customs API updated its authentication protocol, developers inadvertently broke the invoice generation logic because both responsibilities were tightly coupled within the same module, leading to high regression risks.
How this topic solves it
By applying the Single Responsibility Principle, the firm refactored the monolith into distinct, decoupled services. Each module now possesses one coherent reason to change: the Persistence Service handles data storage, the Invoice Generator manages document formatting, and the Customs Client manages external communication. This isolation ensures that changes to external API requirements do not impact the internal document generation logic.
- Identify distinct functional domains within the existing monolithic class.
- Extract the data persistence logic into a dedicated repository class.
- Move document formatting and template rendering into a separate generator module.
- Isolate external API interaction logic into a standalone client service.
- Update the main application controller to orchestrate these services via dependency injection.
This diagram illustrates the transition from a monolithic class to a decoupled service architecture.
Handles database operations
Handles PDF creation
Handles external API calls
- ShipmentManager → extracts → PersistenceService
- ShipmentManager → extracts → InvoiceGenerator
- ShipmentManager → extracts → CustomsClient
Expected business outcome
The codebase becomes significantly more maintainable, as developers can modify external integration logic without fear of disrupting internal document generation or database operations.
Limitations and checks
The primary tradeoff is increased architectural complexity, as the system now requires managing multiple smaller classes and their dependencies. This can be verified by checking the number of files and the depth of the dependency graph; if the number of classes grows disproportionately to the feature set, the system may be over-engineered.