Skip to content

Single Responsibility Principle ​

Also related: Separation of Concerns

Intent ​

A class should have one primary reason to change. Put different kinds of work in different places.

Responsibility ≈ a reason the class would need to change — not “number of methods.”

Problem ​

You start a simple Journal: add entries, remove them, print them. Then someone asks to save to disk. You add save() on the same class.

Now the class changes when entry rules change and when file format or I/O changes. Two reasons. Testing and reuse get harder.

Solution ​

Keep Journal focused on entries. Move persistence to PersistenceManager.

That second class is the fix, not the violation.

Structure ​

ClassResponsibilityMethods
JournalManage diary entriesadd_entry, remove_entry, __str__
PersistenceManagerWrite a journal to disksave_to_file

Compare code ​

Violation — persistence inside Journal

python
class Journal:
    def add_entry(self, text): ...
    def remove_entry(self, index): ...

    def save(self, filename):  # second responsibility
        with open(filename, "w") as f:
            f.write(str(self))

Compliant — this repo

python
class Journal:
    def add_entry(self, text): ...
    def remove_entry(self, index): ...
    # no save / load here

class PersistenceManager:
    @staticmethod
    def save_to_file(journal, filename):
        with open(filename, "w") as f:
            f.write(str(journal))

Walkthrough ​

Quick check ​

In the compliant example, which statement is true?

Run locally ​

bash
uv run srp

Source: main.py · tutorial README

Takeaway ​

  • Domain object → business data and behavior
  • Persistence helper → how that data is stored
  • Mixing them couples your model to the filesystem