Object-Oriented Programming

No Change
adopt
First Added:June 24, 2026 Updated: July 1, 2026

Object-oriented programming (OOP) organizes code around objects that bundle data with the behavior that operates on it. We adopt it as the default mental model for domain modeling in object-capable languages (Java, C#, Python, TypeScript, and similar). Use Design Pattern names after the shape is clear, not as a starting checklist. Keep modules narrow with Single Responsibility Principle and favor composition over deep inheritance trees.

Blurb

Object-oriented programming (OOP) is a programming paradigm based on the concept of “objects”, which can contain data and code: data in the form of fields (often known as attributes or properties), and code in the form of procedures (often known as methods).

Summary

What it is: A paradigm where state and behavior live together in objects, usually behind interfaces or classes. Objects collaborate through messages (method calls) rather than shared mutable globals.

Core ideas: encapsulation (hide internals), abstraction (expose a stable surface), inheritance or subtyping (reuse and polymorphism), and polymorphism (one interface, many implementations). Modern style stresses composition over inheritance and small objects with clear contracts.

Discipline: OOP pairs naturally with indirect control flow. Factories, interfaces, and dependency injection move callers away from concrete types. Treat Dependency Inversion Principle as required when objects collaborate across module boundaries.

OOP is not one shape: Languages implement objects differently. Classical OOP uses explicit classes and encapsulation (the Java and Python mental model). Composable or duck-typed OOP accepts substitutes when behavior matches (GoLang, Ruby). Prototypal OOP chains objects through prototypes rather than class templates (JavaScript).

When to use: Business domains with rich entities, UI models, SDKs, and services where boundaries map naturally to nouns and lifecycles. Strong fit when the language and ecosystem assume OOP (Spring, .NET, enterprise Java).

When to pull back: Pipelines, ETL, and data transforms often read clearer as functions over immutable data. Infrastructure glue and one-off scripts rarely need class hierarchies. If a Design Pattern adds layers without removing duplication, simplify first.

Garden links: First Principles for architecture reviews before pattern shopping. Design Pattern for named structural choices after constraints are clear. Dependency Inversion Principle for stable boundaries between layers.

Details

Pillars (Practical Reading)

PillarPractice
EncapsulationExpose behavior; keep invariants inside the object
AbstractionDepend on interfaces, not concrete types, at boundaries
PolymorphismSwap implementations without rewriting callers
CompositionPrefer has-a over is-a when behavior mixes

OOP Flavors

StyleMechanismTypical languages
ClassicalClasses, encapsulation, inheritanceJava, Python
ComposableStructs or objects plus interfaces; duck typingGoLang, Ruby
PrototypalPrototype chains; instances inherit from objectsJavaScript

Classical OOP is what most teams picture first. Composable styles still use objects but swap implementations when behavior fits, without a shared class hierarchy. In prototypal JavaScript, built-ins such as Array are constructor functions. Literal arrays are instances whose prototype chain includes Array.prototype.

Common Failure Modes

  • God objects that know every subsystem
  • Deep inheritance chains that encode business rules in parent classes
  • Anemic models (data bags with logic scattered in services)
  • Pattern-first design (factories and abstract factories before a second use case exists)
  • Skipping Dependency Inversion Principle and wiring callers directly to concrete types

Language Notes

  • Java / C# / TypeScript: OOP is the default idiom; lean on interfaces and small classes.
  • Python: OOP is available but optional; use classes when they clarify state, not by reflex.
  • Go: Structs and interfaces favor composition; avoid forcing Java-style hierarchies.
  • Ruby: Duck typing and modules mix behavior without deep inheritance trees.
  • JavaScript: Prototypal inheritance and object literals; prefer composition and factory functions over class sprawl when ES classes are not required.

Related Garden Items