Object-Oriented Programming and Design
Principles
CS 202: Object-Oriented Software Design & Design Patterns | Course Study Notes
Computer Science & Software Engineering Academic
Student Reference Material & Comprehensive Study Guide
Student Reference Material
Chapter 1: Evolution of Programming Paradigms
1.1 Procedural vs. Object-Oriented Architecture
Procedural programming structures applications around procedural functions operating on standalone external
data structures. Object-Oriented Programming (OOP) binds data structures together with the methods
operating on them into modular, self-contained entities called objects.
In-Depth Student Note: When studying chapter 1: evolution of programming paradigms, it is essential to trace
how data flows through system memory and CPU registers. Real-world applications require careful
consideration of both computational time complexity and space overhead. Practicing these concepts with
hands-on code examples ensures a deep mastery of the underlying engineering principles.
Key Concept: OOP enhances software maintainability, scalability, and code reuse by establishing clear
module boundaries, interface abstraction, and strict data encapsulation.
Key Takeaway: Always double check edge cases, error conditions, and resource cleanup when writing
production software. Clean, self-documenting code with clear variable names is always preferred over clever,
unreadable single-liners.
Chapter 1 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 2: Encapsulation and Data Hiding
2.1 Access Control and Information Hiding
Encapsulation hides an object's internal state variables from external code, requiring all interactions to occur
through public methods or property interfaces. This prevents illegal data state mutations.
In-Depth Student Note: When studying chapter 2: encapsulation and data hiding, it is essential to trace how
data flows through system memory and CPU registers. Real-world applications require careful consideration of
both computational time complexity and space overhead. Practicing these concepts with hands-on code
examples ensures a deep mastery of the underlying engineering principles.
Computer Science & Software Engineering Page 2 of 12
Student Reference Material
# Encapsulation in Python via Private Attributes & Properties
class BankAccount:
def __init__(self, account_holder: str, balance: float = 0.0):
self.account_holder = account_holder
self.__balance = max(0.0, balance) # Double underscore private field
@property
def balance(self) -> float:
return self.__balance
def deposit(self, amount: float) -> bool:
if amount <= 0:
return False
self.__balance += amount
return True
def withdraw(self, amount: float) -> bool:
if 0 < amount <= self.__balance:
self.__balance -= amount
return True
return False
Code Walkthrough & Execution Step: Notice how the code snippet above encapsulates the core logic cleanly.
In class assignments, try running this snippet in your local Python environment or IDE, stepping through each
line with a debugger to observe variable state changes in real time.
Chapter 2 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 3: Abstraction and Interface Contracts
3.1 Abstract Base Classes (ABCs)
Abstraction simplifies complex system architectures by exposing clean abstract interfaces while hiding
underlying concrete implementations. Abstract Base Classes define contract methods that derived subclasses
must implement.
In-Depth Student Note: When studying chapter 3: abstraction and interface contracts, it is essential to trace how
data flows through system memory and CPU registers. Real-world applications require careful consideration of
both computational time complexity and space overhead. Practicing these concepts with hands-on code
examples ensures a deep mastery of the underlying engineering principles.
Computer Science & Software Engineering Page 3 of 12
Student Reference Material
from abc import ABC, abstractmethod
class PaymentGateway(ABC):
@abstractmethod
def process_payment(self, amount: float) -> bool:
pass
@abstractmethod
def refund_payment(self, transaction_id: str) -> bool:
pass
class PayPalGateway(PaymentGateway):
def process_payment(self, amount: float) -> bool:
print(f'[PayPal] Charged ${amount:.2f}')
return True
def refund_payment(self, transaction_id: str) -> bool:
print(f'[PayPal] Refunded transaction {transaction_id}')
return True
Code Walkthrough & Execution Step: Notice how the code snippet above encapsulates the core logic cleanly.
In class assignments, try running this snippet in your local Python environment or IDE, stepping through each
line with a debugger to observe variable state changes in real time.
Chapter 3 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 4: Inheritance and Class Hierarchies
4.1 Is-A Relationships vs Has-A Composition
Inheritance models an 'Is-A' relationship where a derived subclass inherits fields and behavior from a parent
base class. Composition models a 'Has-A' relationship where a parent class contains instances of component
objects.
In-Depth Student Note: When studying chapter 4: inheritance and class hierarchies, it is essential to trace how
data flows through system memory and CPU registers. Real-world applications require careful consideration of
both computational time complexity and space overhead. Practicing these concepts with hands-on code
examples ensures a deep mastery of the underlying engineering principles.
Key Concept: Software Architecture Principle: Favor Composition over Inheritance! Overusing deep
inheritance hierarchies leads to fragile base classes and tight coupling.
Key Takeaway: Always double check edge cases, error conditions, and resource cleanup when writing
production software. Clean, self-documenting code with clear variable names is always preferred over clever,
unreadable single-liners.
Computer Science & Software Engineering Page 4 of 12
Student Reference Material
Chapter 4 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 5: Polymorphism and Dynamic Dispatch
5.1 Duck Typing and Virtual Method Dispatch
Polymorphism allows objects of different classes to respond to identical interface calls. In Python, duck typing
evaluates objects based on method presence rather than formal class inheritance.
In-Depth Student Note: When studying chapter 5: polymorphism and dynamic dispatch, it is essential to trace
how data flows through system memory and CPU registers. Real-world applications require careful
consideration of both computational time complexity and space overhead. Practicing these concepts with
hands-on code examples ensures a deep mastery of the underlying engineering principles.
# Polymorphic Duck Typing Example
class Circle:
def draw(self):
print('Rendering Circle shape')
class Square:
def draw(self):
print('Rendering Square shape')
class Triangle:
def draw(self):
print('Rendering Triangle shape')
def render_graphics_scene(shapes):
for shape in shapes:
[Link]() # Dynamic polymorphic method dispatch
Code Walkthrough & Execution Step: Notice how the code snippet above encapsulates the core logic cleanly.
In class assignments, try running this snippet in your local Python environment or IDE, stepping through each
line with a debugger to observe variable state changes in real time.
Chapter 5 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 6: The SOLID Principles: Single Responsibility and
Open/Closed
Computer Science & Software Engineering Page 5 of 12
Student Reference Material
6.1 Single Responsibility Principle (SRP)
A class should have only one reason to change, meaning it should encapsulate a single specific responsibility
or feature set.
In-Depth Student Note: When studying chapter 6: the solid principles: single responsibility and open/closed, it is
essential to trace how data flows through system memory and CPU registers. Real-world applications require
careful consideration of both computational time complexity and space overhead. Practicing these concepts
with hands-on code examples ensures a deep mastery of the underlying engineering principles.
6.2 Open/Closed Principle (OCP)
Software entities should be open for extension but closed for modification.
In-Depth Student Note: When studying chapter 6: the solid principles: single responsibility and open/closed, it is
essential to trace how data flows through system memory and CPU registers. Real-world applications require
careful consideration of both computational time complexity and space overhead. Practicing these concepts
with hands-on code examples ensures a deep mastery of the underlying engineering principles.
Chapter 6 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 7: The SOLID Principles: LSP, ISP, and Dependency
Inversion
7.1 Complete SOLID Matrix
Letter Principle Name Core Rule Architectural Goal
S Single Responsibility A class should have only High Cohesion
one reason to change.
O Open/Closed Software entities should be Extensibility
open for extension, closed
for modification.
L Liskov Substitution Subtypes must be Correct Subtyping
substitutable for base types
without breaking code.
I Interface Segregation Clients should not be forced Low Coupling
to depend on interfaces they
don't use.
D Dependency Inversion Depend on abstractions, not Flexibility
concrete implementations.
Computer Science & Software Engineering Page 6 of 12
Student Reference Material
# Dependency Inversion Principle Example
class NotificationService(ABC):
@abstractmethod
def send(self, recipient: str, message: str):
pass
class EmailNotifier(NotificationService):
def send(self, recipient: str, message: str):
print(f'Emailing {recipient}: {message}')
class UserManager:
def __init__(self, notifier: NotificationService):
[Link] = notifier # Injected abstraction
def register_user(self, email: str):
print(f'User registered: {email}')
[Link](email, 'Welcome to Class Study Platform!')
Code Walkthrough & Execution Step: Notice how the code snippet above encapsulates the core logic cleanly.
In class assignments, try running this snippet in your local Python environment or IDE, stepping through each
line with a debugger to observe variable state changes in real time.
Chapter 7 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 8: Creational Design Patterns
8.1 Singleton, Factory Method, and Builder Patterns
Creational patterns abstract the object instantiation process, ensuring systems remain independent of object
creation mechanics.
In-Depth Student Note: When studying chapter 8: creational design patterns, it is essential to trace how data
flows through system memory and CPU registers. Real-world applications require careful consideration of both
computational time complexity and space overhead. Practicing these concepts with hands-on code examples
ensures a deep mastery of the underlying engineering principles.
Computer Science & Software Engineering Page 7 of 12
Student Reference Material
# Thread-Safe Singleton Pattern
import threading
class DatabaseConnectionPool:
_instance = None
_lock = [Link]()
def __new__(cls, *args, **kwargs):
with cls._lock:
if not cls._instance:
cls._instance = super().__new__(cls)
cls._instance._init_pool()
return cls._instance
def _init_pool(self):
print('Initializing DB Connection Pool...')
Code Walkthrough & Execution Step: Notice how the code snippet above encapsulates the core logic cleanly.
In class assignments, try running this snippet in your local Python environment or IDE, stepping through each
line with a debugger to observe variable state changes in real time.
Chapter 8 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 9: Structural Design Patterns
9.1 Adapter, Decorator, and Facade Patterns
Structural design patterns focus on assembling objects and classes into larger flexible structures.
In-Depth Student Note: When studying chapter 9: structural design patterns, it is essential to trace how data
flows through system memory and CPU registers. Real-world applications require careful consideration of both
computational time complexity and space overhead. Practicing these concepts with hands-on code examples
ensures a deep mastery of the underlying engineering principles.
Computer Science & Software Engineering Page 8 of 12
Student Reference Material
# Structural Adapter Pattern
class LegacyJSONLogger:
def log_json(self, json_payload):
print(f'[LEGACY LOG]: {json_payload}')
class TargetLogger(ABC):
@abstractmethod
def log(self, message: str):
pass
class LoggerAdapter(TargetLogger):
def __init__(self, legacy_logger: LegacyJSONLogger):
self.legacy_logger = legacy_logger
def log(self, message: str):
payload = {'msg': message, 'status': 'info'}
self.legacy_logger.log_json(payload)
Code Walkthrough & Execution Step: Notice how the code snippet above encapsulates the core logic cleanly.
In class assignments, try running this snippet in your local Python environment or IDE, stepping through each
line with a debugger to observe variable state changes in real time.
Chapter 9 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 10: Behavioral Design Patterns
10.1 Observer, Strategy, and Command Patterns
Behavioral patterns manage algorithms, responsibilities, and communication between objects.
In-Depth Student Note: When studying chapter 10: behavioral design patterns, it is essential to trace how data
flows through system memory and CPU registers. Real-world applications require careful consideration of both
computational time complexity and space overhead. Practicing these concepts with hands-on code examples
ensures a deep mastery of the underlying engineering principles.
Computer Science & Software Engineering Page 9 of 12
Student Reference Material
# Behavioral Strategy Pattern
class SortingStrategy(ABC):
@abstractmethod
def sort(self, data: list) -> list:
pass
class QuickSortStrategy(SortingStrategy):
def sort(self, data: list) -> list:
return sorted(data)
class DataSorter:
def __init__(self, strategy: SortingStrategy):
[Link] = strategy
def execute_sort(self, data: list) -> list:
return [Link](data)
Code Walkthrough & Execution Step: Notice how the code snippet above encapsulates the core logic cleanly.
In class assignments, try running this snippet in your local Python environment or IDE, stepping through each
line with a debugger to observe variable state changes in real time.
Chapter 10 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 11: Architectural Patterns: MVC, MVP, and Layered
Architecture
11.1 Model-View-Controller Architecture
Architectural design patterns establish top-level system structure, decoupling data storage (Model),
presentation logic (View), and input processing (Controller).
In-Depth Student Note: When studying chapter 11: architectural patterns: mvc, mvp, and layered architecture, it
is essential to trace how data flows through system memory and CPU registers. Real-world applications require
careful consideration of both computational time complexity and space overhead. Practicing these concepts
with hands-on code examples ensures a deep mastery of the underlying engineering principles.
Chapter 11 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 12: Code Refactoring and Code Smells
Computer Science & Software Engineering Page 10 of 12
Student Reference Material
12.1 Identifying and Fixing Code Smells
• God Object: A class doing too many things. Solution: Decompose into single-responsibility classes.
• Feature Envy: A method that constantly accesses data in another class. Solution: Move method to the
target class.
• Primitive Obsession: Using raw primitive values instead of value objects. Solution: Create dedicated
domain classes.
Chapter 12 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 13: Unified Modeling Language (UML) Guide
13.1 UML Class Diagrams
UML class diagrams visualize class structures, attributes (+ public, - private, # protected), and relationships
(Inheritance, Aggregation, Composition).
In-Depth Student Note: When studying chapter 13: unified modeling language (uml) guide, it is essential to
trace how data flows through system memory and CPU registers. Real-world applications require careful
consideration of both computational time complexity and space overhead. Practicing these concepts with
hands-on code examples ensures a deep mastery of the underlying engineering principles.
Chapter 13 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Chapter 14: Unit Testing and Dependency Injection
14.1 Testable Code and Mocking
Writing code with dependency injection makes unit testing straightforward by allowing mock objects to be
injected during test runs.
In-Depth Student Note: When studying chapter 14: unit testing and dependency injection, it is essential to trace
how data flows through system memory and CPU registers. Real-world applications require careful
consideration of both computational time complexity and space overhead. Practicing these concepts with
hands-on code examples ensures a deep mastery of the underlying engineering principles.
Chapter 14 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Computer Science & Software Engineering Page 11 of 12
Student Reference Material
Chapter 15: System Case Study: E-Commerce System
Architecture
15.1 Complete E-Commerce Domain Model Implementation
# Complete E-Commerce Domain Model
class OrderItem:
def __init__(self, product_name: str, price: float, quantity: int):
self.product_name = product_name
[Link] = price
[Link] = quantity
def total_cost(self) -> float:
return [Link] * [Link]
class Order:
def __init__(self, order_id: str):
self.order_id = order_id
[Link] = []
self.payment_gateway = None
def add_item(self, item: OrderItem):
[Link](item)
def total_amount(self) -> float:
return sum(item.total_cost() for item in [Link])
Code Walkthrough & Execution Step: Notice how the code snippet above encapsulates the core logic cleanly.
In class assignments, try running this snippet in your local Python environment or IDE, stepping through each
line with a debugger to observe variable state changes in real time.
Chapter 15 Summary & Review Checklist
• Review core theoretical concepts and definitions covered in this chapter.
• Practice executing and modifying the code examples locally.
• Complete end-of-unit review exercises to reinforce problem-solving skills.
Computer Science & Software Engineering Page 12 of 12