liveBook · Manning

Code to the interface principle

As explained in Software Design for Python Programmers

The Code to the Interface Principle structures code to depend on a superclass interface so it can work with any compatible subclass at runtime.

Code to the Interface Principle keeps client code dependent on a superclass interface rather than a specific subclass. At runtime, polymorphism lets the same code work with any compatible implementation. section 2.3.3 section 2.4

Apply the principle by:

  • Storing objects through a shared superclass or interface, such as Attributes, instead of naming FictionAttrs or CookbookAttrs in shared state. section 2.3.3
  • Calling the shared operation, such as is_match(), and allowing the assigned subclass to provide specialized behavior. section 2.3.3
  • Keep client code flexible as new compatible subclasses are added, while avoiding unnecessary subclass proliferation and hardcoded behavior. section 2.4

Books and interchangeable strategies

A Book stores an Attributes object, which may actually be FictionAttrs or CookbookAttrs. Catalogue searches Book objects and delegates matching to book.attributes.is_match(target_attrs). The same design appears in Strategy: Sport stores PlayerStrategy and VenueStrategy interfaces, so Baseball, Football, and Volleyball can receive interchangeable algorithms at runtime. section 2.3.3 section 8.2.3

Listing 2.12 (Program 2.3 Books-3): catalogue.py
from fiction import Fiction
from fictionattrs import FictionAttrs
from cookbook import Cookbook

class Catalogue:
    def __init__(self):
        self._booklist = []

    def add(self, attrs):    #1
        if isinstance(attrs, FictionAttrs): book = Fiction(attrs)
        else:                               book = Cookbook(attrs)

        self._booklist.append(book)

    def find_fiction(self, target_attrs):    #2
        return [book for book in self._booklist
                    if (    isinstance(book, Fiction)    #3
                        and book.attributes.is_match(target_attrs))
        ]

    def find_cookbook(self, target_attrs):    #4
        return [book for book in self._booklist
                    if (    isinstance(book, Cookbook)    #5
                        and book.attributes.is_match(target_attrs))
        ]

Inspect the Catalogue implementation to see shared Book storage, subclass selection, and delegated interface calls. section 2.3.3

Listing 8.12 (Program 8.4 Sports-StrategyDP): sport.py
class Sport:
    _SPORT_TYPE = ''

    def __init__(self, player_strategy, venue_strategy):
        self._player_strategy = player_strategy    #1
        self._venue_strategy  = venue_strategy      #1

    @property
    def SPORT_TYPE(self): return self._SPORT_TYPE

    @property
    def player_strategy(self): return self._player_strategy    #2

    @property
    def venue_strategy(self): return self._venue_strategy    #2

    @player_strategy.setter
    def player_strategy(self, ps):    #3
        self._player_strategy = ps

    @venue_strategy.setter
    def venue_strategy(self, vs):    #3
        self._venue_strategy = vs

    def recruit_players(self):
        return self._player_strategy.strategy()

    def reserve_venue(self):
        return self._venue_strategy.strategy()

Inspect Sport to see interface-typed strategy references, delegation, and runtime replacement of algorithms. section 8.2.3

How Software Design for Python Programmers covers it

How deep it goes
Explains interface storage, polymorphic dispatch, delegation, and runtime type checks, while cautioning against unnecessary subclass complexity.
Examples
Uses Book, FictionAttrs, CookbookAttrs, Catalogue, Sport, PlayerStrategy, and VenueStrategy as concrete Python examples.
What it assumes
Relies on understanding classes, subclasses, inheritance, interfaces, and polymorphism.
What you can do after
Apply it via polymorphism to replace compatible implementations without changing clients that depend on their shared interface.
How it connects
Connects polymorphism, inheritance, delegation, composition, the Strategy Design Pattern, and the Open-Closed Principle.

Also explained in

Compare how 2 books explain code to the interface principle →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Software Design for Python Programmers. The section links point to the parts of the book it draws on.