logoNEURAL COOK
SearchAll PostsTagsNotesAuthor
instagramtwitterfacebookyoutubelinkedinmailgithubrss
Copyright © 2026 All rights reserved.
•
VIKI
Built with Vikramaditya Singh
Built with
VIKI - A posts created with Next.js and Tailwind.css
About
Composition, Asociation & Aggregation
Database locking / atomic updates
The Four Pillars of OOP
60-Day LLD & Machine Coding Mastery Roadmap
Class Design
Advanced Class Design & Robust Architecture
Clean Code
Don't Repeat Yourself (DRY) Principle
Keep it Simple, Stupid (KISS) Principle
You Aren't Gonna Need It (YAGNI) Principle
Design Patterns
Design pattern
Problems
Design a Library Management System (LMS)
Design a Parking Lot
Vending Machine
SOLID
D : Dependency Inversion
I : The Interface Segregation Principle
The SOLID Foundation
L : The Liskov Substitution Principle
O : The Open/Closed Principle
S : The Single Responsibility Principle
UML
UML Activity Diagrams: Modeling Process and Workflow
UML Class Diagrams: Static Structure Modeling
Unified Modeling Language (UML): Comprehensive Guide
UML Sequence Diagrams: Modeling Dynamic Interactions
Use Case Diagrams: Functional Requirement Modeling
Low Level Design›problems

Vending Machine

Design a vending machine that supports product selection, inventory management, payments, dispensing, change, and failure recovery.

# Core requirements — must implement

  • Support multiple products with different prices and available quantities.
  • Allow customers to select a product using a product code.
  • Accept coins and notes of different denominations, as well as card payments.
  • Validate product availability and ensure sufficient payment before dispensing.
  • Dispense the selected product after successful payment.
  • Return change when cash payment exceeds the product price.
  • Update inventory after successful dispensing.
  • Handle invalid selections, out-of-stock products, and insufficient funds.
  • Allow customers to cancel a purchase and return inserted cash when permitted.
  • Support concurrent transactions without overselling inventory or corrupting purchase state.
  • Provide admin operations to restock products and collect money.

# Extended requirements — discuss if time permits

  • Handle payment failures, timeouts, retries, and uncertain payment outcomes.
  • Detect whether exact change is available and manage coin inventory.
  • Handle dispensing failures after payment, including refunds and transaction recovery after crashes.
  • Support product expiration and out-of-service slots.
  • Generate sales, inventory, and revenue reports.

# Non-functional requirements

  • Correctness: Never dispense more units than are available or reserved for valid purchases.
  • Consistency: Keep purchase, payment, and inventory states consistent, including after failures.
  • Concurrency safety: Ensure simultaneous transactions cannot claim the same final unit.
  • Extensibility: Make it easy to add payment methods and pricing or product rules.
  • Testability: Allow payment providers and dispensing hardware to be replaced by test doubles.
  • Recoverability: Recover or reconcile interrupted purchases after hardware failures or crashes.

# Explicit assumptions

AreaAssumption for our solution
Product selectionCustomer selects one product using a code such as A1.
PricingEach product has a price; the price is captured when a purchase starts.
InventoryEach slot stores a product and its available quantity.
Purchase concurrencyA unit is reserved before payment so two customers cannot purchase the same final unit.
Cash paymentCoins and notes are accepted; excess payment requires change.
Card paymentPayment is handled through a payment abstraction.
Inventory deductionA reserved unit becomes sold after successful dispensing; failed purchases release the reservation if dispensing is confirmed not to have occurred.
CancellationCash can be returned before payment is committed; completed card payments require a refund flow.
Hardware failuresAn uncertain dispensing outcome must be reconciled instead of blindly retrying.
StorageIn-memory for the basic version; database transactions and durable recovery are production extensions.

# Solution

# Entities

They represent domain concepts and maintain their own valid state.

EntityMembersRecommended design
Itemprice, expirationProduct details: productId, name, price, expiration rules if applicable
Inventoryslot, item, unitsRepresents a slot's stock and quantity, linked to an Item
Paymentamount, method, statusRepresents a payment attempt, amount, method, status, and transaction reference (How the customer attempts to pay for that purchase.)
ChangeInventorydenomination, quantityTracks available coins/notes by denomination
Purchaseid,item,price,quantity, status, paymentTracks one customer transaction from selection through payment, dispensing, and completion (What the customer is trying to buy, including the selected item, agreed price, and transaction status.)

# Services — application workflows

  • VendingMachineService
    • Orchestrates the purchase lifecycle: selection, payment, dispensing, cancellation, and completion
      • Validate the selection request.
      • Create and track the purchase.
      • Coordinate stock reservation and payment.
      • Request dispensing only after payment succeeds.
      • Complete the purchase after confirmed dispensing.
      • Coordinate cancellation and recovery.
      • Expose purchase status.
  • InventoryService
    • Checks availability, reserves stock, confirms a sale, releases reservations, and supports inventory queries
  • DispensingService
    • Interfaces with the dispenser hardware and reports success, failure, or uncertain outcomes
  • RestockService
    • Restocks slots and updates stock records
  • PaymentService
    • Processes cash/card payments, tracks payment status, and coordinates refunds.
    • Calculates change and checks whether sufficient denominations are available

# Extension points

  • PaymentGateway : provide a separate implementation for each payment method.

# Design Patterns

# Strategy pattern — payment methods

Problem it solves: The vending machine can accept cash, cards, and potentially new payment methods in the future. Each method has a different way of processing payments.

Use Strategy to define a common interface and provide a separate implementation for each payment method.

The change algorithm can also use Strategy if the machine supports different policies.

For example:

  • MinimumCoinCountStrategy: tries to return change using the fewest coins/notes.
  • PreferredDenominationStrategy: prioritizes certain denominations.
  • SimpleGreedyStrategy: takes larger denominations first, where the denomination system makes that approach valid

# State pattern — purchase lifecycle

Problem it solves: A purchase must not be allowed to perform arbitrary operations in arbitrary states.

A purchase can only perform certain actions in certain states

  • Makes valid and invalid transitions explicit.
  • Prevents operations that are illegal for the current lifecycle state.
  • Makes failure recovery easier to reason about.

Purchase holds a reference to a state object. Instead of checking its status with repeated conditionals, it delegates the requested operation to that object

# Adapter pattern — payment provider and dispenser hardware

Problem it solves: External payment providers and vending hardware may expose different APIs and response formats.

The business logic shouldn't depend directly on those APIs.

  • The application uses a consistent interface regardless of the vendor.
  • Provider-specific request formats and response codes are isolated.
  • Tests can substitute fake implementations.
  • Replacing a vendor doesn't require rewriting the purchase workflow

# Factory pattern — creating payment strategies

The application needs the correct payment strategy based on the customer's selected method.

Factory and Strategy are complementary: the Factory chooses which strategy to provide; the Strategy performs the selected behavior.

# Observer pattern — notifications and monitoring

Problem it solves: Other components may need to react when a purchase completes, without being directly coupled to VendingMachineService.

Other parts of the system may need to react without being tightly coupled to the purchase workflow.

# Concurrency

# Idempotency

Problem : Imagine a payment request times out. The customer retries, or a client automatically resends the request.

An idempotency key identifies a logical operation so a repeated request can return the existing outcome instead of repeating the side effect.

The actual keys should be generated and managed consistently so retries of the same operation reuse the same key.

# Atomic reservation

Problem : Two customers buy the last unit, both customers can read quantity 1 and incorrectly proceed. This is a race condition, meaning the outcome depends on the timing of concurrent operations.

The availability check and reservation must behave as one indivisible operation

# Verfication

RequirementHow it’s handled
Support multiple products with different prices and quantitiesItem stores product details and price. Inventory maps slot codes to items and tracks physical, reserved, and available quantities.
Select a product using a product codeVendingMachineService looks up the slot using its code, validates eligibility, creates a Purchase, and requests stock reservation.
Accept coins and notes of different denominations, as well as card paymentsPaymentService uses the Strategy pattern through PaymentStrategy, with CashPaymentStrategy and CardPaymentStrategy handling method-specific behavior.
Validate product availability and sufficient payment before dispensingInventoryService atomically reserves stock. PaymentService validates or processes payment. VendingMachineService initiates dispensing only after the required payment confirmation.
Dispense the selected product after successful paymentDispensingService interacts with the Dispenser interface. The purchase progresses to dispensing only after payment is confirmed.
Return change when cash payment exceeds the product priceChange-handling logic calculates change = amountTendered - price, verifies available denominations, and reserves the required coins/notes before committing the cash transaction.
Update inventory after successful dispensingInventoryService decrements physical stock and clears the reservation only after dispensing is confirmed.
Handle invalid selections, out-of-stock products, and insufficient fundsVendingMachineService, InventoryService, and PaymentService reject invalid codes, unavailable stock, and insufficient payment without proceeding to dispensing.
Allow customers to cancel a purchase and return inserted cash when permittedVendingMachineService validates the purchase state, PaymentService returns uncommitted cash, and InventoryService releases the reservation when dispensing is confirmed not to have occurred.
Support concurrent transactions without overselling inventory or corrupting purchase stateUse atomic stock reservations, per-slot locks or database conditional updates, validated atomic purchase-state transitions, and idempotent operations. Reserve change atomically as well.
Provide admin operations to restock products and collect moneyRestockService adds stock without overwriting active reservations. A cash-management operation records collected amounts and updates the machine's recorded cash balance.
Handle payment failures, timeouts, retries, and uncertain payment outcomesPaymentService records separate Payment attempts and statuses. Unknown outcomes are reconciled with the payment provider before retrying; idempotency keys prevent duplicate charges.
Detect whether exact change is available and manage coin inventoryChangeInventory tracks quantities by denomination. Change-handling logic calculates a valid combination and atomically reserves, commits, or releases those denominations.
Handle dispensing failures after payment, refunds, and transaction recovery after crashesPurchase tracks dispensing and refund states. PaymentService coordinates refunds, while persistent purchase/payment/dispense records and reconciliation recover interrupted transactions. Unknown dispense outcomes are not blindly retried.
Support product expiration and out-of-service slotsTrack expiration on Item or, where batches differ, a StockBatch entity. Add an inventory/slot status such as ACTIVE, OUT_OF_STOCK, OUT_OF_SERVICE, or MAINTENANCE, and reject ineligible selections.
Generate sales, inventory, and revenue reportsA reporting component uses durable records of completed sales, payments, refunds, restocking, and cash collection. Observer-style events may decouple reporting and notifications from the core purchase workflow.
PreviousDesign a Parking LotNextD : Dependency Inversion
CONTENTS
Core requirements — must implementExtended requirements — discuss if time permitsNon-functional requirementsExplicit assumptionsSolutionEntitiesServices — application workflowsExtension pointsDesign PatternsConcurrencyVerfication