Memory Cache

Level: Intermediate 30–60 min

Concepts: StatePerformance

Solutions: C# | TypeScript | Python


A memory cache is a straightforward storage paradigm. One suitable example of a memory cache is a dictionary, where values are stored and retrieved using a key.

Distinct from a dictionary, the data in a memory cache can go stale based on a specified time to live (TTL) duration.

Additionally, it has a maximum capacity. Once the cache’s capacity reaches its limit, the least-recently-used key-value pair is removed and replaced with the incoming value.

This particular cache should be able to hold a maximum of 100 entries, with a TTL of 60 seconds.

It is important to note that both the key and the value are always strings.

Bonus

  1. Enable the TTL and maximum size to be read from a configuration file. Make sure to handle scenarios where the configuration file is not present or contains negative TTL or size limits.
  2. Additionally, allow the value type to be specified through the configuration file. This includes options such as int, double, or MyAwesomeType. The cache should accommodate both primitive and custom object types.

Reference Walkthrough

Full C#, TypeScript, and Python implementations live at tddbuddy-reference-katas/memory-cache. Twenty scenarios across construction, put/get, capacity + LRU eviction, and TTL expiry (lazy and explicit sweep) — shared across all three languages — with a generic Cache<V> aggregate, Clock collaborator, CacheBuilder + FixedClock test doubles, and named domain exceptions for invalid capacity/TTL.

  • C# (.NET 8, xUnit, FluentAssertions) — walkthrough
  • TypeScript (Node 20, Vitest, strict types) — walkthrough
  • Python (3.11, pytest, OrderedDict, Protocol clock) — walkthrough

This kata ships in Agent Full-Bake (F3) mode: one commit per language with the full domain design landing together. The walkthroughs read as design rationalewhy Cache<V> is generic, why Clock is injected, why evictExpired() is an explicit sweep like library-management’s ExpireReservations and video-club-rental’s MarkOverdueRentals. The reference scopes to the twenty core scenarios; the bonus items (configuration-file loading, runtime-configurable value types) are deliberately out of scope — the generic Cache<V> already shows the value-type seam, and config loading is an application-layer concern rather than a domain one. See the repo’s Gears section for when middle gear is the right call.