One module should have one reason to change. Keep responsibilities cohesive.
What to watch for
- Classes that do I/O, validation, formatting, and persistence in one place.
- Changes in one feature repeatedly break unrelated behavior.
- Lots of if/else branches for different “modes” or “types.”
// Before: one class doing many jobs
class InvoiceService {
generate(invoice) { /* build invoice */ }
email(invoice) { /* send email */ }
save(invoice) { /* write to DB */ }
}
// After: split responsibilities
class InvoiceGenerator { generate(i) { /* ... */ } }
class InvoiceMailer { email(i) { /* ... */ } }
class InvoiceRepo { save(i) { /* ... */ } }