🏧
Machine & Device Design

ATM Machine

State, Security Aur Cash Dispensing
💡 ATM EK BEHAD SHAKKI CASHIER hai — pehle card dekhta hai, phir PIN poochta hai, phir balance check karta hai, aur tab kahin jaakar note nikaalta hai. Har step par "nahi" bol sakta hai.

ATM bhi State machine hai — IDLE → CARD_INSERTED → AUTHENTICATED → TRANSACTION → DISPENSING. Vending machine se farak ye hai ki yahan AUTHENTICATION aur ATOMICITY critical hain: paise account se katne chahiye SIRF tab jab note actually nikal jaayein.

Cash dispensing ke liye Chain of Responsibility pattern classic answer hai — ₹2000 handler pehle koshish karta hai, bacha hua amount ₹500 handler ko, phir ₹100 handler ko. Ye naye denomination add karna trivial bana deta hai aur interviewer ko pattern ka natural use dikhta hai.

abstract class CashDispenser {
  private final int denomination;
  private CashDispenser next;

  void dispense(int amount) {
    int notes = amount / denomination;
    int remaining = amount % denomination;
    if (notes > 0) inventory.deduct(denomination, notes);
    if (remaining > 0 && next != null) next.dispense(remaining);
    else if (remaining > 0) throw new InsufficientNotesException();
  }
}
// Chain: 2000 -> 500 -> 200 -> 100
🏧
ATM EK BEHAD SHAKKI CASHIER hai — pehle card dekhta hai, phir PIN poochta hai, phir balance check karta hai, aur tab kahin jaakar note nikaalta hai. Har step par "nahi" bol sakta hai.
1 / 2
⚡ Quick Recap
  • States: IDLE → CARD_INSERTED → AUTHENTICATED → TRANSACTION → DISPENSING
  • Cash dispensing ke liye Chain of Responsibility — denomination chain
  • Debit aur dispense atomic rakho, failure par rollback
Is page mein (2 subtopics)

ATM ka sabse critical invariant hai: paisa account se katna aur note nikalna EK SAATH hona chahiye. Agar debit ho gaya par note atak gaya, to customer ka paisa gaya aur wo sabse mehnga bug hai.

Practical approach: pehle amount HOLD karo (reserve), phir dispense karo, dispense confirm hone par hold ko actual debit banao. Dispense fail hone par hold release kar do. Ye two-phase approach hi real ATMs use karte hain.

void withdraw(Account acc, int amount) {
  String holdId = ledger.hold(acc, amount);        // 1. reserve
  try {
    dispenser.dispense(amount);                    // 2. physical
    ledger.commit(holdId);                         // 3. confirm
  } catch (DispenseException e) {
    ledger.release(holdId);                        // rollback
    throw e;
  }
}

PIN kabhi plain text mein store nahi hota — hash (salt ke saath) hota hai. Teen galat attempt par card block. Session ka timeout hona chahiye: user card daalkar chala jaaye to machine apne aap IDLE par wapas aa jaaye aur card eject kar de.

Ye batana ki "card retain kar lena ya eject karna" ek business decision hai, aur dono ke apne trade-off hain — ye domain thinking dikhata hai.

💡Tip: Har transaction ka AUDIT LOG immutable hona chahiye — financial systems mein ye compliance requirement hai, optional feature nahi.