Systems Design
Low-level and high-level design at campus depth: SOLID with clean code, the six GoF patterns they ask, four classic LLD problems, the HLD blocks behind every system, and full walkthroughs.
S — Single Responsibility
One class, one reason to change.
Violated: UserService validates input, computes billing, emails users and writes audit logs — every new requirement edits the same class, and a bug anywhere breaks everything.
Applied: Split by reason-to-change: UserValidator, InvoiceCalculator, Mailer, AuditLog — each evolves independently and tests in isolation.
// Java
interface Mailer { void send(String to, String body); }
class SmtpMailer implements Mailer {
public void send(String to, String body) { /* SMTP logic */ }
}
class UserService {
private final Mailer mailer;
UserService(Mailer m) { this.mailer = m; }
void register(User u) {
// validation + persistence only
mailer.send(u.email(), "Welcome!");
}
}O — Open/Closed
Open for extension, closed for modification — add new behaviour by adding code, not editing proven code.
Violated: An `if (type == "credit") ... else if (type == "debit")` chain grows every payment season, forcing retests of the whole switch.
Applied: Define a PaymentMethod interface; new methods register as new classes. Existing flow untouched.
# Python
class PaymentMethod(Protocol):
def charge(self, amount: int) -> str: ...
class Upi:
def charge(self, amount): return f"UPI {amount}"
class Card:
def charge(self, amount): return f"CARD {amount}"
def checkout(method: PaymentMethod, amount: int):
return method.charge(amount) # new types plug in without editsL — Liskov Substitution
Any subclass must be usable wherever its parent is expected — without surprising behaviour.
Violated: A `Square extends Rectangle` that forces width == height breaks every method that sets them independently; a `Penguin extends Bird` that throws in fly() violates callers' expectations.
Applied: Model the real contract: `FlyingBird` vs `Bird`, or prefer composition. Subclasses strengthen, never weaken, pre/post-conditions.
class Bird {
public:
virtual ~Bird() = default;
virtual void eat() = 0; // all birds eat
};
class FlyingBird : public Bird {
public:
virtual void fly() = 0; // only flyers fly
};
class Penguin : public Bird {
void eat() override { /* fish */ }
// no fly() to break — hierarchy models reality
};I — Interface Segregation
Many small, client-specific interfaces beat one fat interface.
Violated: `Worker` with work(), eat(), sleep() forces a RobotWorker to implement eat() and sleep().
Applied: Split into Workable and Restable; robots implement only Workable.
interface Workable { void work(); }
interface Restable { void rest(); }
class Human implements Workable, Restable {
public void work() { /* ... */ }
public void rest() { /* ... */ }
}
class Robot implements Workable {
public void work() { /* 24/7 */ }
}D — Dependency Inversion
High-level policy depends on abstractions, not concrete low-level details.
Violated: OrderService news up MySQLDatabase directly — switching to Postgres means editing business logic.
Applied: OrderService depends on a Repository interface; a factory/DI container injects the implementation. Tests inject an in-memory repo.
class Repo(Protocol):
def save(self, order): ...
class PostgresRepo:
def save(self, order): print("pg save", order)
class OrderService:
def __init__(self, repo: Repo): # depends on abstraction
self.repo = repo
def place(self, order): self.repo.save(order)