Replace a product page that loads every photo up front and asks a slow price service on every render with a lazy photo and a caching price, both with the same interface as the real objects, so the page loads one photo, asks once per product, and forgets on invalidate.
A shopping app's product page builds all of its photos when it opens, although the shopper looks at the first one, and calls a slow price service on every render. The photo store, the real photo and the price service are given and must not change. Put proxies in front of them: stand-ins with the same interface, so the page does not need to know.
Build this API (names are Python's; JavaScript and TypeScript use the same names):
LazyPhoto(file, store): has show() like RealPhoto. Creating one loads nothing. The first show() builds RealPhoto(file, store) (which loads) and returns its show(). Later calls reuse that real photo.CachingPrices(real): has price(sku) like PriceService. It asks real.price(sku) the first time for each sku and answers later calls from memory. invalidate(sku) makes it forget one sku (an unknown sku is ignored). If the real service raises, the error comes through and nothing is remembered.ProductPage(photos, prices, sku): render() returns "<price> rupees, <photos[0].show()>, photo 1 of <n>". It takes photo and price objects and never builds, loads or caches anything itself. (The old page took a store and a list of file names.)Keep the old number: a page of 5 photos at 300 rupees renders 300 rupees, showing p1.jpg, photo 1 of 5. The change is how much work it takes to get there.
The tests check every message, that creating lazy photos loads nothing, that 4 renders load one photo and call the service once, that a cache keeps separate answers per sku, that invalidate forces a new ask, fakes that the test writes (a price object and a photo), a failing service, and that the page builds and loads nothing itself.
Write your code, then run 9 example tests and 4 hidden tests. Each run is limited to 8 seconds: an infinite loop gets stopped and the runtime restarts, your code stays.