Right now the storage is hardcoded. In real systems you'll swap a dict for an LSM tree, an on-disk B-tree, or a networked shard. That's the Strategy pattern.
Define an abstract StorageBackend with put / get / delete / keys. Implement two concrete backends: a plain DictBackend and a SortedDictBackend that always returns keys in alphabetical order. Then make KeyValueStore accept any backend and delegate to it.
from abc import ABC, abstractmethod
class StorageBackend(ABC):
"""Strategy interface for storage backends."""
@abstractmethod
def put(self, key, value):
pass
@abstractmethod
def get(self, key):
pass
@abstractmethod
def delete(self, key):
pass
@abstractmethod
def keys(self):
pass
class DictBackend(StorageBackend):
"""In-memory dict storage."""
# TODO: Implement using a plain dict
pass
class SortedDictBackend(StorageBackend):
"""Dict storage; keys() returns keys in alphabetical order."""
# TODO: Implement using a dict, but sort keys() on return
pass
class KeyValueStore:
"""KV store that accepts any StorageBackend strategy."""
def __init__(self, backend: StorageBackend):
# TODO: Keep a reference to the backend
pass
def put(self, key, value):
pass
def get(self, key):
pass
def delete(self, key):
pass
def keys(self):
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
Right now the storage is hardcoded. In real systems you'll swap a dict for an LSM tree, an on-disk B-tree, or a networked shard. That's the Strategy pattern.
Define an abstract StorageBackend with put / get / delete / keys. Implement two concrete backends: a plain DictBackend and a SortedDictBackend that always returns keys in alphabetical order. Then make KeyValueStore accept any backend and delegate to it.
Press Run Tests or ββ© to check your solution.