1. The problem OOP was trying to solve
In the late 1950s and early 1960s, programs were written as long sequences of procedures operating on shared global data. As programs grew, this broke down:
- Any function could change any data, so bugs spread across the whole codebase.
- Real-world things (a ship, a customer, a bank account) had no single home in the code; their data and behaviour were scattered.
- Reusing code meant copy-paste.
Researchers wanted a way to model the world as a set of self-contained things that talk to each other. That idea became object-oriented programming.
2. Timeline: how OOP was invented
Year Milestone Who Why it matters 1963 Sketchpad Ivan Sutherland (MIT) Graphics system with “master” drawings and “instances” — an early form of class/object. 1962–1967 Simula I → Simula 67 Ole-Johan Dahl & Kristen Nygaard (Norwegian Computing Center, Oslo) The first OOP language. Built for simulations (ships, queues, traffic). Simula 67 introduced classes, objects, inheritance, subclasses, and virtual methods. ~1966–67 The term “object-oriented” Alan Kay Kay coined the phrase, inspired by Sketchpad, Simula, and biology (cells communicating via messages). 1972–1980 Smalltalk (72, 76, 80) Alan Kay, Dan Ingalls, Adele Goldberg (Xerox PARC) Made OOP “pure”: everything is an object, objects communicate by sending messages. Also gave us the GUI, windows, and MVC. 1979 → 1983 “C with Classes” → C++ Bjarne Stroustrup (Bell Labs) Brought Simula’s ideas to C’s performance. Took OOP into mainstream industry. 1984 Objective-C Brad Cox & Tom Love Smalltalk-style messaging on C; later the basis of NeXT and Apple’s platforms. 1994 “Design Patterns” (Gang of Four) Gamma, Helm, Johnson, Vlissides Catalogued 23 reusable OOP design solutions. Turned OOP into a design discipline. 1995 Java James Gosling (Sun) “Write once, run anywhere”; made class-based OOP the default for enterprise software. 2000s SOLID principles Popularised by Robert C. Martin Rules for building maintainable OO systems. 2001 / 2003 Turing Awards Dahl & Nygaard (2001), Alan Kay (2003) Recognition of OOP as a foundational idea in computing.Two schools of OOP
- Simula / C++ / Java school — OOP as classes and inheritance: define types, build hierarchies.
- Smalltalk / Alan Kay school — OOP as objects sending messages: independent actors hiding their state.
Kay later said the big idea was messaging, not classes. That view is surprisingly close to modern microservices and actor systems (Erlang, Akka).
3. The four pillars
3.1 Encapsulation — hide state, expose behaviour
class BankAccount {
#balance = 0; // private: nobody outside can touch it directly
deposit(amount: number) {
if (amount <= 0) throw new Error("Invalid amount");
this.#balance += amount;
}
getBalance() {
return this.#balance;
}
}
Enter fullscreen mode Exit fullscreen mode
Invariants (balance never goes invalid) are enforced in one place.
3.2 Abstraction — expose what, hide how
interface PaymentGateway {
charge(userId: string, amount: number): Promise<string>;
}
Enter fullscreen mode Exit fullscreen mode
Callers depend on the contract, not on Razorpay/Stripe details.
3.3 Inheritance — reuse and specialise
class Notification {
constructor(protected to: string) {}
send() { /* common logging, retries */ }
}
class EmailNotification extends Notification {
override send() { /* SMTP */ super.send(); }
}
Enter fullscreen mode Exit fullscreen mode
Useful, but easy to overuse (see “composition over inheritance” below).
3.4 Polymorphism — one interface, many implementations
const channels: Notification[] = [new EmailNotification("[email protected]"), new SmsNotification("+91...")];
channels.forEach(c => c.send()); // each does its own thing
Enter fullscreen mode Exit fullscreen mode
The caller doesn’t need if/else on type — new types plug in without changing old code.
4. Why OOP is a building block of system design
System design has two levels:
- High-Level Design (HLD): services, databases, queues, caches, load balancers.
- Low-Level Design (LLD): classes, interfaces, relationships, and patterns inside each service.
OOP is the language of LLD, and its ideas scale up to HLD.
4.1 Objects map to domain concepts
Designing a parking lot, Uber, or an LMS starts with nouns → classes:
User, Driver, Ride, Payment, Location
Course, Module, Lesson, Quiz, Attempt, Progress
Enter fullscreen mode Exit fullscreen mode
Verbs → methods: ride.start(), quiz.submit(), payment.refund().
4.2 Relationships define structure
Relationship Meaning Example Association uses / knows aboutDriver — Ride
Aggregation
has-a, can live independently
Course has Students
Composition
owns, dies with parent
Order owns OrderItems
Inheritance
is-a
AdminUser is a User
Dependency
temporarily uses
ReportService uses PdfGenerator
4.3 SOLID — the rules that keep systems changeable
Principle One-line meaning System-design payoff S — Single Responsibility A class has one reason to change Small, testable units; mirrors “one service, one job” O — Open/Closed Open for extension, closed for modification Add a new payment method without touching old code L — Liskov Substitution Subtypes must be usable as their base type Safe polymorphism; no surprise breakages I — Interface Segregation Many small interfaces > one fat one Clients depend only on what they use D — Dependency Inversion Depend on abstractions, not concretions Swap DB/queue/vendor easily; easy mocking in tests// Dependency Inversion in practice
class OrderService {
constructor(
private repo: OrderRepository, // interface, not MongoRepo
private payments: PaymentGateway, // interface, not StripeClient
) {}
}
Enter fullscreen mode Exit fullscreen mode
4.4 Composition over inheritance
Deep inheritance trees become rigid. Modern design prefers composing behaviour:
class Car {
constructor(private engine: Engine, private gps: Navigator) {}
}
Enter fullscreen mode Exit fullscreen mode
Swap PetrolEngine for ElectricEngine without a new subclass.
4.5 Design patterns — reusable OOP solutions
Category Pattern Typical use Creational Factory, Builder, Singleton Creating notification channels, building complex queries, one DB pool Structural Adapter, Decorator, Facade Wrapping a third-party API, adding caching/logging, simplifying a subsystem Behavioural Strategy, Observer, State, Command Pricing/ranking algorithms, event listeners, order lifecycle, undo/queue jobs4.6 The same ideas scale to HLD
OOP concept Distributed-system equivalent Object Microservice / actor Encapsulation Service owns its own database Interface API contract (REST, gRPC, OpenAPI) Message passing (Kay) Events, queues (Kafka, RabbitMQ) Polymorphism Multiple implementations behind one API / load balancer Dependency Inversion Service discovery, config-driven adapters Observer pattern Pub/SubThis is why interviewers ask LLD questions (parking lot, elevator, BookMyShow) — they test whether you can think in objects, contracts, and responsibilities, which is the same thinking HLD requires.
5. Criticism and balance
- Over-engineering: too many layers, factories, and abstract classes for simple problems.
- Inheritance misuse: fragile base classes, deep hierarchies.
- Shared mutable state: objects still mutate state; concurrency gets hard.
- Functional programming (immutability, pure functions) has pushed back on this, and most modern code (TypeScript, Kotlin, Rust, Swift) is multi-paradigm: objects for structure, functions for transformations.
Rule of thumb: use OOP to draw boundaries and contracts; keep logic inside those boundaries simple.
6. Quick LLD recipe
- Clarify requirements and use cases.
- Extract nouns → candidate classes; verbs → methods.
- Define interfaces at boundaries (storage, payment, notification).
- Draw relationships (class diagram).
- Apply SOLID; pick patterns only where they remove real complexity.
- Handle concurrency, errors, and extensibility.
- Walk through one use case end to end.
7. Summary
- Invented: Simula 67 (1967) by Dahl & Nygaard in Norway was the first OOP language; Alan Kay coined “object-oriented” and built Smalltalk at Xerox PARC in the 1970s; C++ (1983) and Java (1995) made it mainstream.
- Core ideas: encapsulation, abstraction, inheritance, polymorphism.
- Why it matters for system design: OOP gives you the vocabulary of components with responsibilities that communicate through contracts — exactly what both low-level and high-level design are about.