Mr. Latte


Lesson 1 of 13

Separate Roles and Contracts

If order processing directly chooses how email is sent, changing notifications also changes order code. Start by separating order handling from message delivery.

Receive the required capability

class EmailNotifier:
    def send(self, message):
        print("email:", message)

class OrderService:
    def __init__(self, notifier):
        self.notifier = notifier
    def accept(self, order_id):
        self.notifier.send(f"Order {order_id} accepted")

OrderService(EmailNotifier()).accept(7)

The output is email: Order 7 accepted. OrderService relies on a notifier offering send(message). Supplying another notifier changes delivery without rewriting the order flow. Providing required objects from outside is dependency injection.

Inheritance and composition

Composition is useful for replacing changing roles. Inheritance can suit extensions to a stable shared procedure. Neither is universally superior.

Check your understanding

What must change to replace email notification with screen output?

Show explanation

Provide another object honoring the same send(message) contract. Separating responsibilities lets order processing ignore delivery details.

Looking for a product partner? Founders, teams, businesses: from problem framing to launch.