SOLID design: depend on abstractions

The SOLID principles are five guidelines for object-oriented design. Single responsibility: a class should have one reason to change. Open/closed: code should be open to extension but closed to modification. Liskov substitution: a subtype must be usable wherever its base type is expected. Interface segregation: prefer several small interfaces to one large one. Dependency inversion: high-level code should depend on abstractions, not on concrete details.

Python
class NoDiscount:
    def apply(self, amount):
        return amount


class PercentOff:
    def __init__(self, percent):
        self.percent = percent

    def apply(self, amount):
        return amount * (100 - self.percent) // 100


class FlatOff:
    def __init__(self, cents):
        self.cents = cents

    def apply(self, amount):
        return max(amount - self.cents, 0)


class Checkout:
    def __init__(self, rule):
        self.rule = rule

    def total(self, prices):
        return self.rule.apply(sum(prices))


cart = [1000, 2500]
for rule in (NoDiscount(), PercentOff(10), FlatOff(500)):
    print(type(rule).__name__, Checkout(rule).total(cart))
Read the full lesson