Design an ATM Machine: OOD Concepts in Practice

In this article, we will explore how to design an ATM machine using Object-Oriented Design (OOD) principles. This exercise is commonly used in technical interviews to assess a candidate's understanding of OOD concepts such as encapsulation, inheritance, and polymorphism.

Requirements Analysis

Before diving into the design, we need to outline the basic functionalities of an ATM machine:

  • Authenticate User: Verify the user's identity using a card and PIN.
  • Check Balance: Allow users to view their account balance.
  • Withdraw Cash: Enable users to withdraw a specified amount of cash.
  • Deposit Cash: Allow users to deposit cash into their account.
  • Transfer Funds: Enable users to transfer funds between accounts.

Identifying Classes and Objects

Based on the requirements, we can identify the following key classes:

  1. ATM: Represents the ATM machine itself.
  2. User: Represents the user of the ATM.
  3. Account: Represents a bank account associated with the user.
  4. Transaction: Represents a transaction performed by the user.

Class Design

Now, let's define the classes and their relationships:

1. ATM Class

class ATM:
    def __init__(self):
        self.current_user = None
        self.accounts = {}  # Dictionary to hold user accounts

    def authenticate_user(self, card_number, pin):
        # Logic to authenticate user
        pass

    def check_balance(self):
        # Logic to check balance
        pass

    def withdraw_cash(self, amount):
        # Logic to withdraw cash
        pass

    def deposit_cash(self, amount):
        # Logic to deposit cash
        pass

    def transfer_funds(self, target_account, amount):
        # Logic to transfer funds
        pass

2. User Class

class User:
    def __init__(self, name, card_number, pin):
        self.name = name
        self.card_number = card_number
        self.pin = pin
        self.account = None  # Associated account

    def set_account(self, account):
        self.account = account

3. Account Class

class Account:
    def __init__(self, account_number, balance=0):
        self.account_number = account_number
        self.balance = balance

    def get_balance(self):
        return self.balance

    def deposit(self, amount):
        self.balance += amount

    def withdraw(self, amount):
        if amount <= self.balance:
            self.balance -= amount
            return True
        return False

4. Transaction Class

class Transaction:
    def __init__(self, user, amount, transaction_type):
        self.user = user
        self.amount = amount
        self.transaction_type = transaction_type
        self.timestamp = datetime.now()

OOD Principles in Action

Encapsulation

Each class encapsulates its data and methods, providing a clear interface for interaction. For example, the Account class manages its balance internally and exposes methods for deposit and withdrawal.

Inheritance

In a more complex design, we could introduce subclasses for different types of accounts (e.g., SavingsAccount, CheckingAccount) that inherit from the Account class, allowing for specialized behavior.

Polymorphism

We can implement polymorphism by defining a common interface for transactions. For instance, different transaction types (withdrawal, deposit, transfer) can be handled through a common method that takes a transaction object as input.

Conclusion

Designing an ATM machine is a practical exercise that showcases the application of Object-Oriented Design principles. By understanding how to structure classes and their interactions, you can effectively tackle similar design problems in technical interviews. Practice this design and refine your understanding of OOD concepts to excel in your interview preparation.