Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Design Principles  ›  Lesson

SOLID, Part 1 — Single Responsibility and Open/Closed

SOLID 16 minA class should have one reason to change, and new behaviour should arrive as new code rather than as edits to working code.

SOLID, Part 1 — Single Responsibility and Open/Closed

Marketing asked for a new font on Shelfwise's weekly sales report. The change went out, and on Monday finance found the revenue numbers were wrong: the layout code and the revenue maths lived in the same class, and the edit disturbed both. SOLID is five design principles that prevent exactly this kind of collateral damage. This lesson covers the first two letters.

The rule

One reason to change per class; add behaviour by adding code, not editing it.

S — Single Responsibility Principle (SRP). A class should have one reason to change. The most useful way to read "reason" is actor: the person or team who asks for changes. Organise code by the actor it serves.

class SalesReport:
    def revenue(self): ...        # finance's rules
    def render_pdf(self): ...     # marketing's layout
    def email_monday(self): ...   # operations' schedule

Three actors, three reasons to change, one class: any team's request can break another team's feature. Split it into RevenueCalculator, ReportLayout and ReportMailer, and each change touches only its own class.

O — Open/Closed Principle (OCP). Code should be open for extension, closed for modification. When a new variation arrives, you should be able to add it as new code, without editing code that already works and is already tested.

class ReportLayout(ABC):
    @abstractmethod
    def render(self, figures): ...

class PdfLayout(ReportLayout): ...
class CompactLayout(ReportLayout): ...   # new request = new class

The report code calls layout.render(figures) and never changes when a layout is added. Polymorphism, from the previous section, is what makes this possible. Fixing a genuine bug in PdfLayout is still allowed; "closed" protects working behaviour from feature edits, not from repairs.

The shortcut

For SRP, list who would ask for a change to the class. More than one name means more than one class. For OCP, imagine the next variation (a new layout, discount, carrier). If adding it means editing an if chain in working code, extract an interface.

Checking Shelfwise's Invoice classStep 1 of 4
  1. List the actors

    Tax rules come from finance. Invoice wording comes from customer support. Saving to the database comes from the platform team.

The trap is over-splitting. SRP does not mean one method per class. Methods that change together, for the same actor, belong together.

Drills

Answer fast — trust the rule.

quick drill

Under SRP, what is the best meaning of "one reason to change"?

quick drill

A Customer class validates addresses (support), calculates loyalty tiers (marketing) and writes SQL (platform). How many classes does SRP suggest?

quick drill

What does "closed for modification" mean in the Open/Closed Principle?

quick drill

Every new shipping carrier means adding an elif to calculate_shipping. Which change best follows OCP?

Remember

  • One reason to change per class; a reason is an actor who asks for changes.
  • Add behaviour by adding code: new variations become new classes behind an interface.
  • Trap: over-splitting; things that change together for one actor stay together.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainUntangle the sales report

Shelfwise's SalesReport class computes revenue figures (asked for by finance), lays them out as a PDF (asked for by marketing), and emails the file every Monday (asked for by operations). Finance now wants a new revenue rule and marketing wants a new layout. Use the Single Responsibility and Open/Closed principles to explain the problem and propose a design.