SRP Violation Structure: Identifying Mixed Responsibilities
Anatomy of an SRP Violation
SRP violations occur when a class mixes concerns from different actors or business domains. The key indicator is asking: "If requirement X changes, would this class need to be modified? What about requirement Y from a different department?" If multiple unrelated requirements affect the same class, SRP is violated.
Classic Violation Example: Invoice Processing
- customer: Customer
+ saveToDatabase(): void
+ generatePDF(): File
+ sendEmail(): void
Identifying the Actors
The violated Invoice class serves four different actors:
First, the Finance team owns business logic like tax calculations and discounts. They change calculateTotal() when tax rates change.
Second, the Database team owns persistence strategy. They change saveToDatabase() when migrating from SQL to NoSQL.
Third, the Reporting team owns output formats. They change generatePDF() when adding watermarks or changing layouts.
Fourth, the Customer Success team owns notification templates. They change sendEmail() when updating branding or adding SMS support.
Consequences of Violation
When the Reporting team updates PDF generation to fix a margin issue, they must modify the Invoice class. This requires recompiling and retesting all invoice functionality, including database operations and email sending. If the reporting developer introduces a bug, it might break invoice persistence. Changes ripple across unrelated concerns.
Refactoring Strategy
To fix SRP violations, extract each responsibility into its own class. The original class becomes a coordinator or facade if needed, but core responsibilities live in focused, single-purpose classes. Use dependency injection to wire these classes together at runtime.