Object-Oriented Programming

Disciplines
Software Engineering
Object-Oriented Programming
Java
Architecture
Author

Marcos M. Raimundo

Published

September 18, 2026

This course explores the foundations of Object-Oriented Programming (OOP) through a rigorous software engineering and memory management lens. Students will learn how to design, connect, and scale objects, treating each class not merely as a data structure, but as a robust state machine with explicit behavioral contracts, memory lifecycle rules, and quantifiable coupling metrics.

Final Objectives

The goal is to provide a deep understanding of how object-oriented systems are designed, validated, and maintained. By the end of this course, students will be able to bridge syntax concepts like classes, inheritance, and interfaces with their theoretical architectural roots, including the Single Responsibility Principle, the Liskov Substitution Principle, invariant protection, and structural design patterns.

Course Content

Click on each lesson to access its detailed planning and study materials.

Part 1: Foundations of State and the Isolated Object

  • Lesson 1: The Object-Oriented Paradigm and the Java Machine
    • OOP Concept: The Java ecosystem (JVM, Bytecode, JIT), Stack vs. Heap memory, garbage collection and reachability, and the anatomical structure of a class (attributes, constructors, accessors, public interface vs. private implementation).
    • Design Concept: Abstracting the real world into state, behavior and identity; the physical difference between the class (the blueprint) and the object (the instance in memory); encapsulation as an engineering strategy (Information Hiding), not a security feature; the mechanics of parameter passing (primitives vs. references).
    • Objectives: Understand the physical constraints of the execution environment, how to translate real-world entities into code blueprints, and why every design choice in this lesson traces back to keeping the cost of change low (the TRUE acronym).
    • Expected Competencies: Ability to define a class, instantiate objects in the Heap, explain why an object’s state must stay private, and predict the outcome of passing a primitive vs. an object reference into a method.
  • Lesson 2: The Object as a Finite State Machine
    • OOP Concept: The anemic domain model anti-pattern; Command-Query Separation (CQS); Design by Contract (pre/post-conditions); the standard exception kit (IllegalArgumentException, IllegalStateException, NullPointerException); the equals()/hashCode() contract.
    • Design Concept: The object as a Deterministic Finite Automaton — attributes as state, methods as the only authorized transitions. Class invariants as the generalization of loop invariants. The constructor as the inductive base of a proof of validity; Fail-Fast to prevent “zombie objects”.
    • Objectives: Treat encapsulation not as a security feature, but as the mechanism that keeps a state machine inside its valid region, and treat the constructor as mathematically different from every other method.
    • Expected Competencies: Ability to design strict, Fail-Fast constructors, separate commands from queries, write methods with explicit pre/post-conditions, and correctly override equals()/hashCode() together.
  • Lesson 3: Composing Systems — Contracts and Stability
    • OOP Concept: Collaborating specialist objects (Produto/ItemCarrinho/Carrinho); the Interface vs. Implementation boundary; the Law of Demeter; programming to interfaces for Plug-and-Play extensibility.
    • Design Concept: Moving from the anatomy of a single object to the architecture of a system of objects; low coupling through delegation instead of “intimate” knowledge of a collaborator’s internals; Tell, Don’t Ask as the technical cure for “train wreck” code chains.
    • Objectives: Recognize a system as a network of specialists communicating through stable contracts, not a pile of classes exposing their data to each other.
    • Expected Competencies: Ability to design low-coupling collaborations, diagnose Law-of-Demeter violations, and program against an interface so new implementations plug in without recompiling existing code.

Part 2: Composition and Contracts (Connecting Objects)

  • Lesson 4: Decomposition and Responsibility
    • OOP Concept: The three association types — Dependency (“uses-a”), Aggregation (“has-a”), and Composition (“is-part-of”); Dependency Injection via constructor.
    • Design Concept: The Single Responsibility Principle (SRP) and the “AND test” for diagnosing God Classes; cohesion and coupling as the two quality metrics; Robert Martin’s Actor theory and the LCOM metric; the opposite failure modes of over-fragmentation (Shotgun Surgery) and the Anemic Domain Model; Delegation as the mechanism that makes composition as powerful as inheritance.
    • Objectives: Learn to decompose a God Class into small, specialized, highly cohesive units — without swinging to the opposite extreme of fragmenting a domain concept into meaningless pieces.
    • Expected Competencies: Ability to diagnose SRP violations with the “AND test”, choose the correct association type for a relationship, and refactor tangled responsibilities into an orchestrator that delegates to injected specialists.
  • Lesson 5: Coupling and Contracts
    • OOP Concept: Quantitative and qualitative coupling metrics — CBO (Coupling Between Object Classes) and the Myers coupling scale (Content, Common, Stamp, Data); the GRASP Information Expert pattern; the Dependency Inversion Principle (DIP).
    • Design Concept: Why passing a dependency through the constructor does not, by itself, guarantee logical decoupling — Feature Envy as the classic counter-example; why coupling to concrete classes eventually caps what composition alone can achieve, and how inverting the dependency onto an abstraction breaks that ceiling.
    • Objectives: Move from intuition (“this feels coupled”) to measurement and diagnosis, and recognize the point where composition needs an abstraction to keep growing safely.
    • Expected Competencies: Ability to diagnose Feature Envy, reason about a class’s CBO, classify a dependency on the Myers scale, assign responsibility via Information Expert, and invert a dependency onto an interface to satisfy the Open/Closed Principle.
  • Lesson 6: Interfaces and the Contract of Behavior
    • OOP Concept: Interfaces as pure behavioral contracts; modern interfaces (default/static/private methods) and the “Blind Mutator” pattern; exceptions as the enforcers of business rules the type system cannot express.
    • Design Concept: An interface says what an object does, never what it is or how; the boundary between an interface and an abstract class is state, not behavior; a type is defined by the messages an object answers, not by what it stores.
    • Objectives: Treat interfaces as behavioral promises the compiler enforces, and exceptions as the runtime enforcement of promises the compiler cannot check.
    • Expected Competencies: Ability to design a pure interface, use default/static/private methods without breaking the interface’s statelessness, choose between an interface and an abstract class, and guard a contract’s business rules with Fail-Fast exceptions.

Part 3: Abstraction and Polymorphism (Cautious Reuse)

  • Lesson 7: Polymorphism, Binding, and Generics
    • OOP Concept: Late Binding (Dynamic Dispatch); the Cardelli–Wegner taxonomy of polymorphism (Universal: Inclusion and Parametric; Ad-hoc: Overloading and Coercion); Generics as a compile-time safety net for collections.
    • Design Concept: The compiler only checks that a method exists on the declared type; the JVM decides, at runtime, which implementation actually runs — the mechanism that makes the Open/Closed Principle achievable in practice, ending “type if chains” for good.
    • Objectives: Distinguish polymorphism that truly decouples (Inclusion) from polymorphism that merely organizes syntax (Overloading), and see Generics as parametric polymorphism in action.
    • Expected Competencies: Ability to explain Late Binding, classify a given polymorphism instance in the Cardelli–Wegner taxonomy, refactor a type-if chain into polymorphic dispatch, and use Generics to move a type error from runtime to compile time.
  • Lesson 8: Inheritance — DNA, Fragility, and Template Method
    • OOP Concept: extends mechanics and state inheritance as physical incorporation; the Fragile Base Class problem; abstract classes as a “semi-finished machine”; the Template Method pattern.
    • Design Concept: Inheritance defines what an object is (the strongest coupling in OOP), not just what it does; a legitimate specialization needs shared DNA and the need for polymorphic treatment — reuse alone is not a reason to inherit; invisible invariants (ordering assumptions, return semantics, a skipped super call) are what make base classes fragile.
    • Objectives: Recognize when inheritance is the right tool versus when composition should be used instead, and see the base class as the guardian of an algorithm’s structure via Template Method.
    • Expected Competencies: Ability to diagnose a Fragile Base Class scenario, decide between inheritance and composition for a given relationship, design an abstract class with private state and protected hooks, and write a Template Method with a locked skeleton.
  • Lesson 9: Substitutability and Failure — The Liskov Principle and Exception Taxonomy
    • OOP Concept: Late Binding and VTable dispatch mechanics; the Liskov Substitution Principle (LSP) — pre-condition, post-condition and invariant rules, plus exception-contract stability; the Throwable-style domain hierarchy, polymorphic catch, and exception translation (wrapping).
    • Design Concept: “Same signature” is not “same contract” — @Override only checks the former; the Circle-Ellipse paradox showing that real-world taxonomy does not guarantee valid software subtyping under mutation; distinguishing unrecoverable programming bugs (Unchecked, Fail-Fast) from expected external contingencies (Checked, with a recovery plan).
    • Objectives: Formalize when a subtype can safely replace its base type, and treat error handling as a structured, contract-driven part of design rather than an afterthought.
    • Expected Competencies: Ability to explain the VTable dispatch protocol, diagnose an LSP violation (pre/post-condition, invariant, or exception contract), recognize the Circle-Ellipse fallacy, design a semantic exception hierarchy with polymorphic catch, and choose correctly between Checked and Unchecked exceptions.

Part 4: Patterns and Architecture (Consolidation)

  • Lesson 10: The Collapse of Inheritance and the Rise of Composition — the Strategy Pattern
    • OOP Concept: Combinatorial explosion when class inheritance is forced to model independent, orthogonal business axes at once; Java’s prohibition on multiple class inheritance (the Diamond Problem); Aggregation vs. Association; the Strategy pattern (interface, dependency injection, delegation).
    • Design Concept: “Favor object composition over class inheritance” (GoF); the shift from is-a to has-a; Herbert Simon’s near-decomposability theory of stable complex systems; the Open/Closed Principle achieved through an interchangeable, injected algorithm instead of a rigid type hierarchy.
    • Objectives: Recognize the exact moment independent axes of variation make inheritance structurally unworkable, and resolve that failure by delegating behavior to a composed, swappable strategy instead of a conditional maze or a failed subclass hierarchy.
    • Expected Competencies: Ability to diagnose a combinatorial-explosion scenario, explain why Java forbids multiple class inheritance, classify a relationship as Aggregation or Association, and design a Strategy pattern (Context/Strategy/ConcreteStrategy) that satisfies the OCP.
  • Lesson 11: Design Pattern Vocabulary, Immutability, and Safe Object Genesis
    • OOP Concept: The historical origin of Design Patterns and the 1994 GoF catalog; what a Design Pattern is not (not a framework, not a structural algorithm, no cure for procedural code); the three pattern families — Creational, Structural, and Behavioral; the Value Object pattern (identity by attribute, absolute immutability, Primitive Obsession); the Builder pattern (fluent interface, cross-field validation at build()); the Factory Method pattern and Dependency Inversion applied to object creation.
    • Design Concept: Patterns as a shared, ubiquitous language that condenses complex structural discussions into a single word, with Strategy (Lesson 10) placed as the first concrete example within the broader taxonomy of 23 patterns; mutable shared references as the root cause of aliasing bugs, and immutability as the structural cure; the “Dirty Constructor” problem and why genesis deserves the same engineering rigor as behavior; the new operator as the tightest coupling in the language, and how a factory pushes that decision to the system’s periphery.
    • Objectives: See the GoF catalog as a map of the design space before studying any pattern individually, and treat the object’s data and its birth as two more surfaces that need explicit protection, alongside the behavior already secured by Strategy.
    • Expected Competencies: Ability to explain the historical origin of Design Patterns, classify a given pattern into its correct GoF family, distinguish an Entity from a Value Object, implement a Value Object with correct equals()/hashCode() and defensive copying, build a fluent Builder with cross-field validation, and design a Factory Method that satisfies the Dependency Inversion Principle.
  • Lesson 12: The State Pattern and the Adapter — Internal Flow, External Boundary
    • OOP Concept: The status-as-primitive anti-pattern (a String/int field checked at the top of every method) and its evolution fragility; the State pattern (Context/State/ConcreteState) as its cure; the Adapter pattern (Object Adapter vs. Class Adapter) as a translation layer at the boundary with an incompatible, unmodifiable external interface.
    • Design Concept: State and Strategy share nearly identical class topology yet solve different architectural intentions — “an interchangeable algorithm injected from outside” vs. “self-mutating behavior driven by the object’s own life cycle”; where transition logic should physically live (inside states vs. centralized in the Context); composition over inheritance again, now applied to Adapter, and why the industry favors the Object Adapter for testability and forward compatibility with future subclasses of the legacy type.
    • Objectives: Complete the “stability triptych” (protected data, safe genesis, and now safe flow) opened in Lessons 10–11, and treat a system’s external boundary with incompatible third-party code as a design problem with the same rigor as its internal structure.
    • Expected Competencies: Ability to design a State pattern, decide where transition logic should live, articulate precisely why State is not “Strategy with a different name”, implement an Object Adapter for an incompatible legacy interface, and explain why composition beats inheritance for that specific role.
  • Lesson 13: The Decorator and Observer Patterns — Dynamic Composition and Event Decoupling
    • OOP Concept: The Decorator pattern — wrapping an object dynamically, in layers sharing the same interface, to add cumulative responsibilities without the subclass explosion inheritance would require; the Observer pattern — a publisher/subscriber model (Subject/Observer, registration, broadcast) that decouples a core domain object from a variable number of peripheral subsystems reacting to its state changes.
    • Design Concept: Decorator as composition’s answer to the same combinatorial-explosion problem inheritance created (Lesson 10), now solved at runtime via a dual is-a/has-a relationship instead of at compile time; Observer as the mechanism that lets a core domain object broadcast an event without knowing who — or how many — are listening, including the Push vs. Pull data-traffic trade-off and the generalization from an in-memory listener to a distributed Event-Driven Architecture (Kafka/RabbitMQ-style).
    • Objectives: Recognize when responsibilities are optional, cumulative, and decided at runtime — the signal that inheritance will fail and a Decorator is needed — and diagnose direct, cascading dependencies on peripheral services as an OCP violation that an Observer resolves through inversion of control.
    • Expected Competencies: Ability to design a Decorator (abstract decorator with pass-through, concrete decorators accumulating behavior via super), explain why a Decorator requires both an is-a and a has-a relationship to the same interface, design an Observer (Subject/Observer, registration, broadcast), compare the Push and Pull data-traffic strategies, and map a local Observer’s topology onto a distributed Event-Driven Architecture.
  • Lesson 14: Architectural Synthesis — Stable Core, Volatile Periphery, and Course Closure
    • OOP Concept: A comparative decision matrix consolidating the four structural/behavioral patterns covered in this course (Strategy, Adapter, Decorator, Observer) — their intent, when to apply each, and the specific type of coupling each one eliminates (conditional, syntactic, taxonomic, and temporal/identity, respectively).
    • Design Concept: The architectural boundary between a system’s stable core (contracts, interfaces, rarely-changing business rules) and its volatile periphery (concrete implementations, third-party SDKs, infrastructure detail that changes under market pressure) — the “Golden Rule” that stable code must never depend on volatile code, generalizing the DIP (Lesson 5) and the OCP (Lesson 10) already covered separately; the closing lens that reframes every pattern studied so far as boundary-drawing engineering, not merely a coding trick.
    • Objectives: Consolidate the four already-learned patterns under a single architectural vocabulary, and close the course by reconnecting that vocabulary to the original cost-of-change problem and the TRUE acronym opened in Lesson 1.
    • Expected Competencies: Ability to classify a dependency as pointing toward the stable core or the volatile periphery, apply the Golden Rule to diagnose an inverted dependency, place a new design scenario correctly on the four-pattern decision matrix, and articulate which specific coupling type (conditional, syntactic, taxonomic, or temporal/identity) a given pattern eliminates.

This is the final lesson of the course.

References

  • Weisfeld, M. The Object-Oriented Thought Process. 5th ed. Pearson Education.
  • Bloch, J. Effective Java. 3rd ed. Addison-Wesley Professional.
  • Metz, S. Practical Object-Oriented Design in Ruby: An Agile Primer. Pearson Education.
  • Arnold, K., Gosling, J. & Holmes, D. The Java Programming Language. 4th ed. Addison-Wesley.
  • Eckel, B. Thinking in Java. 4th ed. Prentice Hall Professional.