Skip to main content
Clean Architecture 60 XP · 6 min

The Two Values of Software: Behavior vs Structure

Software derives value from behavior and structure. A perfectly working but rigid system will fail when requirements change.

Showing
Ad (728×90)

Why this matters

Every piece of software provides two values to its stakeholders: behavior (what it does right now) and structure (its ability to change). Most developers and business stakeholders focus entirely on behavior — if it works, ship it. But a system that works today and cannot be changed tomorrow has already begun to die.

Martin argues that structure is more important than behavior. A system that doesn't quite work but is easy to fix can be made to work. A system that works perfectly but can never be changed will become useless the moment requirements shift — and requirements always shift. The developer's responsibility is to fight for the structure that keeps the system soft (soft-ware: easy to change).

The problem

Hardcoding behavior in a function leaves no room for change. When the pricing strategy must differ per region, per season, or per customer type, every change requires touching — and testing — the same function.

Bad

class OrderProcessor:
    def calculate_total(self, items: list[dict]) -> float:
        total    = sum(i["price"] * i["qty"] for i in items)
        discount = total * 0.10  # hardcoded — impossible to change
        return total - discount
class OrderProcessor {
  calculateTotal(items: { price: number; qty: number }[]): number {
    const total = items.reduce((s, i) => s + i.price * i.qty, 0);
    return total * 0.90; // hardcoded — rigid, not soft
  }
}

The solution

Injecting the strategy keeps behavior correct today and structure flexible for tomorrow. New discount rules are new classes, not edits to existing ones.

Good

class PercentDiscount:
    def __init__(self, rate: float): self.rate = rate
    def apply(self, total: float) -> float:
        return total * (1 - self.rate)

class OrderProcessor:
    def __init__(self, discount):
        self.discount = discount

    def calculate_total(self, items: list[dict]) -> float:
        total = sum(i["price"] * i["qty"] for i in items)
        return self.discount.apply(total)

proc = OrderProcessor(PercentDiscount(0.10))
print(proc.calculate_total([{"price": 100, "qty": 2}]))
interface DiscountStrategy {
  apply(total: number): number;
}

class PercentDiscount implements DiscountStrategy {
  constructor(private rate: number) {}
  apply(total: number) { return total * (1 - this.rate); }
}

class OrderProcessor {
  constructor(private discount: DiscountStrategy) {}
  calculateTotal(items: { price: number; qty: number }[]): number {
    const total = items.reduce((s, i) => s + i.price * i.qty, 0);
    return this.discount.apply(total);
  }
}

Key takeaway

Behavior satisfies today's requirements. Structure is what allows you to satisfy tomorrow's — and it is the harder, more valuable thing to protect.

Done with this lesson?

Mark it complete to earn XP and track your progress.