Skip to main content

One Reason to Change

The Single Responsibility Principle is the S in SOLID, five rules for designing code that stays easy to change. It says: a type should have one job — and therefore only one reason to change.

When one type saves orders and sends emails, it changes when the storage changes and when the email text changes. Two jobs, two reasons, twice the risk of breaking one thing while touching the other.

In Go the rule applies to structs, their methods, and packages: keep each one focused on a single task.


Too Many Jobs in One Type

This order processor works — but it stores the order, writes the confirmation text, and "sends" it, all in one method. Testing the email text alone is impossible, and reusing the storage part elsewhere means dragging the email code along.

One type that does everything

Process() mixes two jobs: storing and notifying. Any change to either one means editing — and re-testing — this same type.

Prompt
Write a Go program with an OrderProcessor struct whose Process method does two jobs at once: it prints that the order was saved to storage and prints a confirmation email text for the customer. Process one order to show it works, as a starting point for the Single Responsibility discussion.
Output: Go program and captured output

One Job per Type

The fix: one type per job. OrderStore only stores, EmailSender only sends. A small function coordinates them.

The output is the same — but now each part can be changed, tested, and reused on its own.

Split into two types

Same behavior, separated: the store knows nothing about emails, the sender knows nothing about storage. The processOrder function just connects them.

Prompt
Refactor the order processing into two Go types with one job each: an OrderStore with a Save method that prints the storing step, and an EmailSender with a SendConfirmation method that prints the email. Add a processOrder function that calls both. Process one order and show the same output as before.
Output: Go program and captured output

The payoff: reuse without fear

Because the sender is its own type, it sends a shipping notice too — no storage code involved. And the store archives an order without composing a single email. Each type grew inside its one job.

Prompt
Using the separated OrderStore and EmailSender types in Go, show the payoff of single responsibility: send a shipping notification with the same sender without touching storage, and archive an order with the store without sending any email. Print each action.
Output: Go program and captured output