Skip to main content
CodeOath
← All posts

Architecture & Patterns110 min total · 26 parts

ACID, SOLID, and Design Patterns: A Complete Software Design Reference

Part 7 of 26 · ~2 min

Single Responsibility Principle

Give a class one job, and one job only — a single axis it's allowed to change along. Not one function, not one file's worth of code: the real test is whether two unrelated forces inside the organization could each demand a change to this same class, for reasons that have nothing to do with each other.

Here's where a small nonprofit's volunteer-scheduling tool — we'll call it ShiftDesk — starts. It coordinates volunteers across three sites: a food bank, an animal shelter, and a community garden. One class does the whole job of getting a week's schedule in front of people:

// Violates SRP — three unrelated reasons to change this class: a change
// to how the roster gets assembled, a change to how it's laid out for
// the printed clipboard at the front desk, and a change to how text
// reminders go out all land in the same file.
public class ShiftScheduler
{
    public List<ShiftAssignment> BuildWeeklyRoster(DateTime weekStart) { /* query + assemble */ return new(); }
    public string FormatForPrinting(List<ShiftAssignment> roster) { /* build a plain-text layout */ return ""; }
    public void SendNightBeforeReminders(List<ShiftAssignment> roster) { /* talk to an SMS gateway */ }
}
// Each class has exactly one reason to change.
public class ShiftRosterBuilder
{
    public List<ShiftAssignment> BuildWeeklyRoster(DateTime weekStart) { /* query + assemble */ return new(); }
}

public class SchedulePrinter
{
    public string FormatForPrinting(List<ShiftAssignment> roster) { /* build a plain-text layout */ return ""; }
}

public class ReminderSender
{
    public Task SendNightBeforeAsync(List<ShiftAssignment> roster) => Task.CompletedTask;
}

A useful gut-check: try summarizing what ShiftScheduler does in one clause with no conjunction. It can't be done honestly — building a roster, laying it out for print, and pushing text reminders are three separate verbs stitched together with "and," and that stitching is usually the giveaway. Splitting it apart pays off immediately, not just tidily: ShiftRosterBuilder can be unit tested with zero string formatting or SMS gateway involved, and the day the front desk asks for the printed schedule to include a QR code, nothing about roster-building or reminders is anywhere near the diff.