Card 07/ 08

ExerciseDifficulty: Intermediate1 min

Practice: Splitting a Storage Interface

A read-only cache that must still implement write, delete and backup.

Splitting an interface by its clients is the skill practised here. A Storage interface declares read, write, delete and backup. A ReadOnlyCache serves prices from a snapshot and cannot change it. Three clients use storage: a price lookup that only reads, a sync job that reads and writes, and a nightly job that only backs up. Answer three questions: which methods of the cache are forced, what interfaces would you create, and what does the sync job take?

py
from abc import ABC, abstractmethod


class Storage(ABC):
    @abstractmethod
    def read(self, key): ...

    @abstractmethod
    def write(self, key, value): ...

    @abstractmethod
    def delete(self, key): ...

    @abstractmethod
    def backup(self): ...


class ReadOnlyCache(Storage):
    def __init__(self, snapshot):
        self.snapshot = snapshot

    def read(self, key):
        return self.snapshot.get(key)

    def write(self, key, value):
        raise NotImplementedError("cache is read-only")

    def delete(self, key):
        raise NotImplementedError("cache is read-only")

    def backup(self):
        pass


cache = ReadOnlyCache({"price:pen": "1.20"})
print(cache.read("price:pen"))
try:
    cache.write("price:pen", "1.50")
except NotImplementedError as error:
    print(f"NotImplementedError: {error}")
OutputRan with python:3.12-slim (Python 3.12.13)
1.20
NotImplementedError: cache is read-only
A read-only cache forced to implement every method of Storage.
Show the answers

The forced methods. write and delete raise, and backup silently does nothing, which is worse: a backup job given the cache would report success having saved nothing.

The interfaces. Split by client: Reader with read, Writer with write and delete, and Backup with backup. Keep write and delete together, because the only client that changes data uses both.

The sync job. It reads and writes, so declare ReadWriteStorage as an interface extending Reader and Writer, and have the sync job take that. The price lookup takes Reader, which the cache implements and nothing more. The cache's three stub methods are deleted.