លំហសិក្សាកម្ពុជា
V1.0
This report summarizes the eight lessons of the Advanced OOP course, covering the progression from core Python OOP foundations (classes, dataclasses, special methods, abstraction/composition) through design patterns (Factory, Decorators, SOLID, Strategy/Template/Command), all built around a shared Role-Based Access Control (RBAC) case study.
Advanced
Object-Oriented Programming
Python
+ Flask
Lesson
Summary Report (Lessons 01–08)
|
Field |
Details |
|
Course / Class |
Advanced Object-Oriented Programming |
|
Lecturer |
SEK SOCHEAT |
|
University |
University of Technology & Entrepreneurship |
|
Coverage |
Lesson 01 through Lesson 08 |
|
Submission Type |
Lesson Summary Report |
This report summarizes the eight
lessons of the Advanced OOP course, covering the progression from core Python
OOP foundations (classes, dataclasses, special methods,
abstraction/composition) through design patterns (Factory, Decorators, SOLID,
Strategy/Template/Command), all built around a shared Role-Based Access Control
(RBAC) case study.
Introduces core OOP
vocabulary and builds the first version of the RBAC domain model.
|
Field |
Details |
|
Focus |
Classes, objects, self, constructors, instance vs. class
attributes |
|
Case Study |
RBAC: User, Role, Permission |
|
Deliverable |
Package-based project (models/ + main.py) |
●
Course roadmap: OOP core (Ch.1-4) → Patterns (Ch.5-9) →
Project (Ch.10-12)
●
Procedural vs. object-oriented thinking
●
Core vocabulary: class, object, attribute, method,
self, responsibility
●
RBAC mini-domain: a user has roles, a role has
permissions
●
__init__() and self; instance attributes vs. class
attributes
●
Three method types: instance, @classmethod,
@staticmethod
●
@classmethod as a simple factory (from_username)
●
Project structure: modules, packages, and imports
●
Built User, Role, and Permission classes with
composition (User has Role, Role has Permission)
●
has_permission() checks a permission across a user's
roles
● Clean code habits: type hints, docstrings, PascalCase/snake_case naming
Strengthens the Python object
model using @dataclass and @property before moving into design patterns.
|
Field |
Details |
|
Focus |
Dataclasses, safe defaults, __post_init__, properties |
|
Case Study |
RBAC rebuilt: Permission (dataclass), Role (dataclass),
User (regular class) |
|
Deliverable |
lesson02_smart_models/ package |
●
Data-centric vs. behavior-centric classes
●
The boilerplate problem solved by @dataclass (auto
__init__, __repr__, __eq__)
●
Field order rules: required fields before default
fields
●
The mutable default trap and field(default_factory=...)
●
Useful field() options: init=False, repr=False,
compare=False, metadata
●
Object creation lifecycle and __post_init__() for
normalization/validation
●
ClassVar vs. InitVar
●
frozen, slots, and kw_only dataclass options
●
Equality (__eq__) and ordering (order=True) in
dataclasses
●
@property: getters, validating setters, and
read-only/computed properties
●
Decision guide: public field vs. property vs. method
●
Permission as a frozen, slotted, ordered dataclass with
a derived `resource` property
●
Role as a dataclass with default_factory list and
add_permission()/has_permission() behavior
●
User as a behavior-rich regular class with validated
properties (username, email) and role assignment
● Composition diagram: User → Role → Permission
Explores how objects
communicate meaning to Python via identity, representation, equality,
containers, operators, and context managers.
|
Field |
Details |
|
Focus |
Special/dunder methods and Python protocols |
|
Case Study |
RBAC objects extended with __str__, __eq__, __hash__,
__len__, __iter__, and an AuditSession context manager |
|
Deliverable |
Mini-project applying multiple object protocols with unit
tests |
●
Python object model: identity, type, and value (id(),
type(), isinstance())
●
Identity vs. equality: `is` vs. `==`, and aliasing
●
Inspection tools: id(), type(), vars(), dir() (for
debugging, not public API)
●
Namespaces and attribute lookup order (instance → class
→ base classes → AttributeError)
●
Syntax-to-protocol map: print()→__str__/__repr__,
len()→__len__, in→__contains__, obj[i]→__getitem__, |→__or__,
with→__enter__/__exit__
●
Representation checklist: meaningful __repr__ and
__str__
●
Equality: default identity-based behavior vs. domain
equality via __eq__
●
NotImplemented as a design signal in comparison methods
●
The hashing contract and hashing risk with mutable
objects
●
Container protocols: __len__, __iter__, __contains__,
__getitem__
●
Operator overloading and its design rules (only when it
preserves domain meaning)
●
Context managers: __enter__/__exit__, resource
lifecycle, exception flow inside `with`
●
UserDirectory supporting len(), iteration, membership,
and indexing
● AuditSession as a context manager that records audit actions and handles exceptions on exit
Covers ways to organize
relationships between classes without over-relying on inheritance.
|
Field |
Details |
|
Focus |
Abstract Base Classes, composition, mixins, and structural
typing (Protocol) |
|
Case Study |
Multi-channel notification system (Email/SMS/Push senders) |
|
Deliverable |
Practical mini-project: Multi-Channel Notification System |
●
Opening problem: one class trying to know/do everything
●
Four lenses for object relationships: is-a, has-a,
uses-a, behaves-like
●
Abstraction: exposing only the essential contract
●
Abstract Base Classes (ABC): nominal contracts and
enforcement — incomplete subclasses stay abstract
●
Abstract properties combined with shared concrete
behavior
●
Inheritance: strong meaning but strong coupling — use
carefully
●
Composition: building behavior by connecting objects
instead of inheriting
●
Refactoring example: replacing false inheritance with
composition
●
Constructor injection to make dependencies explicit and
testable
●
Composition makes unit tests smaller and easier to
isolate
●
Mixins: small, focused, optional behavior (e.g., a
RetryMixin)
●
Method Resolution Order (MRO) when combining mixins
with a base contract
●
Mixin design checklist (single responsibility, no state
conflicts)
●
Structural subtyping with typing.Protocol —
compatibility by behavior, not declared inheritance
●
An unrelated class can satisfy a Protocol without
inheriting from it
●
ABC vs. Protocol: choosing the smallest tool that fits
the problem
●
Defined a Sender Protocol so EmailSender/SMSSender are
interchangeable without a shared base class
● Applied a RetryMixin to add retry behavior to senders without duplicating logic
Separates object creation
from object usage using Simple Factory, Factory Method, Registry Factory, and
Abstract Factory.
|
Field |
Details |
|
Focus |
Creational design patterns |
|
Case Study |
NotifierFactory (Email/SMS/Console/Push), ReportService
family, UIFactory (Light/Dark), UserFactory (admin defaults) |
|
Deliverable |
Guided Lab: Factory-Based Notification Project (8 steps) |
●
The object creation problem: high coupling, repeated
modification, harder testing from if/elif chains
●
What is a factory: centralizes creation decisions and
returns objects via a common contract
●
Simple Factory: a function/static method that selects
and returns a concrete product
●
Factory as a class (e.g., NotifierFactory.create())
●
Factory Method pattern: a base creator (ReportService)
defines a creation point; subclasses (PDFReportService, CSVReportService)
decide the product
●
@classmethod as a factory method (alternative
constructors: from_username, from_dict)
●
Registry-Based Factory: replaces long if/elif with a
name→class map; open for extension, closed for modification (OCP)
●
Abstract Factory: creates a family of related,
consistent products (UIFactory → Light/Dark Button+Dialog)
●
Factory + Dependency Injection: factories create
dependencies; services receive them
●
When to use a factory: runtime selection, complex
setup, loose coupling — vs. no variation/overengineering
●
Practical RBAC factory: UserFactory.create_admin()
bundles a default Administrator role with read/create/delete permissions
● Pattern comparison table: Simple Factory, Factory Method, Registry Factory, Abstract Factory
Uses Python decorators to add
reusable behavior (logging, timing, validation, RBAC checks) around core
business logic.
|
Field |
Details |
|
Focus |
First-class functions, closures, decorators, cross-cutting
concerns |
|
Case Study |
UserService methods protected by @log_action,
@require_login, @require_permission() |
|
Deliverable |
Decorated UserService: list_users, create_user,
update_user, delete_user |
●
Big idea: decorators wrap core logic (Request →
Decorator → Core Function → Result) without editing the function body
●
Functions are first-class objects; higher-order
functions take/return functions
●
Closures: an inner function remembers outer values
(e.g., multiplier(factor))
●
Building a basic decorator (function in, wrapper out)
with @simple_decorator syntax
●
Professional decorator template: *args, **kwargs,
return result, and functools.wraps
●
Reusable cross-cutting concerns: @log_action
(start/success/failure) and timing decorators
●
Parameterized decorators need three layers: decorator
factory → decorator → wrapper (e.g., require_permission(code))
●
Authentication (who are you? 401) vs. Authorization
(what can you do? 403)
●
Decorator order matters: stacked decorators form a
pipeline, @A above @B means function = A(B(function))
●
Class decorators: registering a class into a factory
registry at definition time (bridges to Chapter 5)
●
log_action, measure_time, require_login,
require_permission(code), validate_positive_id, audit_action(name)
● Recommended project structure: decorators/, models/, services/ folders kept separate
Applies the five SOLID
principles to identify code smells and refactor a large class into focused,
testable services.
|
Field |
Details |
|
Focus |
SRP, OCP, LSP, ISP, DIP, and a disciplined refactoring
workflow |
|
Case Study |
Refactoring a monolithic UserManager into UserValidator,
PasswordHasher, UserRepository, Notifier, AuditLogger, and a coordinating
UserService |
|
Deliverable |
Guided Lab: Refactor BadUserManager |
●
Why SOLID matters: working code → growing requirements
→ maintainable design
●
Code smells: giant class, long method, duplicate code,
too many if/elif, tight coupling, hidden dependencies, large interface,
unexpected subclass behavior
●
S — Single Responsibility: a class should have one
reason to change; split UserManager into 5 focused classes
●
O — Open/Closed: open for extension, closed for
modification; depend on a Notifier Protocol instead of if/elif
●
OCP with Protocol + Strategy-like design supports
Dependency Injection
●
L — Liskov Substitution: a subtype must safely replace
its base type (good vs. bad substitution examples)
●
I — Interface Segregation: split a large SystemService
interface into focused contracts (EmailSender, ReportGenerator, BackupService)
●
D — Dependency Inversion: high-level UserService
depends on a UserRepository abstraction, not SQLiteUserRepository directly
●
Refactoring workflow: write/confirm tests → refactor
small step → run tests → review design → repeat
●
Testing benefit: FakeUserRepository allows testing
business rules without a real database
● Before/after example of UserManager.create_user() split into UserValidator, PasswordHasher, UserRepository, EmailNotifier, AuditLogger, coordinated by UserService
Covers three behavioral
design patterns for flexible business logic and workflow design, applied to a
task-management project.
|
Field |
Details |
|
Focus |
Strategy, Template Method, and Command patterns |
|
Case Study |
DiscountStrategy/CheckoutService, ReportExporter
(CSV/JSON), RenameTaskCommand + CommandManager |
|
Deliverable |
Guided Lab: task-management app using all three patterns |
●
Why behavioral patterns: replace large if/elif chains,
hard-coded algorithms, rigid workflows, and UI-coupled actions
●
Strategy Pattern: encapsulates interchangeable
algorithms behind one contract; Context (CheckoutService) delegates to a
strategy object (Student/VIP/No Discount)
●
Strategy at runtime: behavior can change without
rewriting the Context (e.g., swapping payment methods)
●
Template Method Pattern: a base class owns a stable
workflow (load→validate→format→save→hook); subclasses customize only selected
steps (e.g., CSVExporter, JSONExporter)
●
Strategy vs. Template Method: composition + runtime
switch vs. inheritance + stable process with variation
●
Command Pattern: turns a request/action into an object
with execute()/undo(); Client → Command → Receiver → Result
●
Command example: RenameTaskCommand stores old/new state
to support undo()
●
Command History and Undo: a CommandManager maintains
executed commands and can undo_last()
●
Pattern comparison table: Strategy (which behavior?),
Template Method (which steps vary?), Command (how to represent a request?)
●
Integrated project architecture: Command organizes
actions, Strategy organizes algorithms, Template Method organizes workflows —
used together
●
DiscountStrategy Protocol with
StudentDiscount/VIPDiscount implementations used by CheckoutService
●
ReportExporter(ABC) template with
CSVExporter/JSONExporter subclasses
● Command Protocol (execute/undo) implemented by RenameTaskCommand against a task service
|
Lesson |
Title |
Core Idea |
|
01 |
Foundations and Project Setup |
Classes, objects, self, method types, modules/packages;
built the base RBAC model. |
|
02 |
Smart Class Design |
@dataclass, field(default_factory), __post_init__,
@property; safer, more concise domain models. |
|
03 |
Python Object Model & Special Methods |
Identity vs equality, __str__/__repr__/__eq__/__hash__,
container protocols, operator overloading, context managers. |
|
04 |
Abstraction, Composition, Mixins, Protocols |
ABCs, is-a/has-a/uses-a/behaves-like, composition over
inheritance, mixins, structural typing. |
|
05 |
Factory Method & Abstract Factory |
Simple/Method/Registry/Abstract Factory patterns to
decouple object creation from usage. |
|
06 |
Decorators & Cross-Cutting Concerns |
Closures, decorator template with functools.wraps,
logging/timing/RBAC decorators. |
|
07 |
SOLID Principles & Refactoring |
SRP/OCP/LSP/ISP/DIP applied to refactor a monolithic class
into testable services. |
|
08 |
Strategy, Template Method & Command |
Three behavioral patterns for swappable algorithms, stable
workflows, and undoable actions. |
Throughout the course, one
shared RBAC (Role-Based Access Control) case study — User, Role, and Permission
— is progressively refined: from basic classes (Lesson 1), to dataclasses and
properties (Lesson 2), to full Python object protocols (Lesson 3), to
abstraction and composition (Lesson 4), and finally used as the substrate for
design-pattern exercises in Lessons 5–8, preparing students for the Flask
web-project phase of the course.
មតិយោបល់ 0