Problem statement
Design the object model and core APIs for the shopping-cart component of an online store. The cart holds the goods a shopper has picked but not yet paid for: it tracks line items and their quantities, lets the shopper add, remove, and change quantity, checks that stock exists before an item goes in, and computes running totals with a hook for discounts. Whatever sits above it — a web controller, a mobile client, or a test harness — calls these APIs and reads state back.
Operating context. One shopper's cart at a time, driven in-process by a single caller. A catalog supplies each product's current unit price and available stock; the cart does not own the catalog and must ask it. A line item is a (product, quantity, captured unit price) triple, and the same product added twice merges into one line with a summed quantity rather than a duplicate row. Totals are a subtotal (sum of line prices), an optional discount, and a grand total. Discounting is open-ended — today a percent-off code, tomorrow a buy-one-get-one or a threshold rule — so the cart must call out to a pricing rule instead of hard-coding the arithmetic. The cart's contents must survive being set down and picked back up later, so storage sits behind an abstraction rather than being wired to any one database.
Out of scope. Checkout, payment, and order placement; the catalog / inventory service internals (assume it answers price and stock queries); user accounts and authentication; the HTTP or UI layer; and multi-currency or tax computation. Design only the in-process cart object model and its collaborators, not the transport, storage engine, or catalog behind them.
What to produce. The class hierarchy (entities such as Cart and LineItem, value objects such as Money and Quantity, and the collaborator interfaces for catalog, pricing, and persistence), the public API each class exposes, and the state a cart moves through as items come and go. Be explicit about: how adding an already-present product merges into the existing line, how a stock check gates every add and quantity increase, how the discount hook is abstracted so a new rule drops in without editing the cart, how subtotal and grand total are recomputed, and how the persistence seam keeps the cart storage-agnostic and unit-testable.