Syllabus software engineering (1)
Tổng quan các giai đoạn
| Giai đoạn | Tên | Số tuần | Ngày | Ghi chú |
|---|---|---|---|---|
| 0 | Foundations for OOP | 5 | 1–35 | |
| 1 | Object Oriented Programming | 9 | 36–98 | |
| 2 | Refactoring & Code Smells | 4 | 99–126 | |
| 3 | Design Patterns | 9 | 127–189 | |
| 4 | Testing & Quality Engineering | 4 | 190–217 | |
| 5 | Concurrency | 7 | 218–266 | |
| 6 | Networking & OS I/O | 4 | 267–294 | |
| 7 | Domain Driven Design | 8 | 295–350 | |
| 8 | Architecture Patterns | 11 | 351–427 | |
| 9 | Security & API Design | 4 | 428–455 | |
| 10 | Framework Internals | 18 | 456–581 | |
| 11 | Database Internals | 9 | 582–644 | |
| 12 | Distributed Systems | 11 | 645–721 | |
| 13 | DevOps/Infra & Observability | 6 | 722–763 | |
| 14 | Runtime Internals | 20 | 764–903 | |
| 15 | Source Code Reading (sprint có cấu trúc) | 8 | 904–959 | Nên duy trì tiếp tục sau mốc này |
| 16 | System Design Practice | 6 | 960–1001 | |
| 17 | Framework Engineering (Capstone) | 14 | 1002–1099 |
Giai đoạn 0 - Foundations for OOP (Ngày 1–35)
Mục tiêu chung: hiểu những thứ OOP đang che giấu bên dưới - phần cứng, bộ nhớ, cách hàm được gọi.
Nhóm 1: Computer Architecture (Ngày 1–7)
Ngày 1: CPU & Chu kỳ thực thi lệnh
Mục tiêu: Hiểu CPU thực thi một lệnh máy như thế nào.
Lý thuyết: Fetch–Decode–Execute cycle, Instruction Set, ALU, Control Unit.
Thực hành: Viết pseudo-trace cho 1 đoạn C đơn giản, mô tả từng bước CPU xử lý.
Ngày 2: Cache (L1/L2/L3)
Mục tiêu: Hiểu vì sao cache tồn tại và ảnh hưởng đến performance.
Lý thuyết: Cache line, cache hit/miss, spatial vs temporal locality.
Thực hành: Viết 2 vòng lặp duyệt mảng 2D theo row-major và column-major, đo thời gian chạy khác nhau.
Ngày 3: Register & Memory Hierarchy
Mục tiêu: Nắm được thứ bậc tốc độ Register → Cache → RAM → Disk.
Lý thuyết: Register file, độ trễ truy cập từng tầng, nguyên lý đánh đổi tốc độ/dung lượng.
Thực hành: Vẽ sơ đồ memory hierarchy kèm số liệu latency thực tế (ns) cho từng tầng.
Ngày 4: Virtual Memory
Mục tiêu: Hiểu vì sao mỗi process "thấy" toàn bộ không gian địa chỉ riêng.
Lý thuyết: Paging, Page Table, TLB, Page Fault.
Thực hành: Dùng
/proc/[pid]/maps(Linux) xem address space của một chương trình C đang chạy.
Ngày 5: Context Switch & Process vs Thread
Mục tiêu: Phân biệt process và thread ở tầng OS.
Lý thuyết: Process Control Block, thread stack riêng - heap chung, chi phí context switch.
Thực hành: Viết chương trình đo thời gian context switch bằng cách tạo nhiều thread/process.
Ngày 6: Lab tổng hợp Computer Architecture
Mục tiêu: Thấy tác động thực tế của cache/memory lên hiệu năng code.
Lý thuyết: Ôn lại cache miss, false sharing.
Thực hành: Benchmark một hàm xử lý mảng lớn trước/sau khi tối ưu locality, ghi lại số liệu.
Ngày 7: Review & Quiz Computer Architecture
Mục tiêu: Củng cố kiến thức tuần 1.
Lý thuyết: Tự tổng hợp lại bằng sơ đồ tư duy (CPU – Cache – Register – Memory – Context switch).
Thực hành: Tự đặt và trả lời 10 câu hỏi giải thích "tại sao" (không phải "là gì").
Nhóm 2: Data Structures - tự cài đặt bằng C++ (Ngày 8–17)
Ngày 8: Dynamic Array - Lý thuyết & khởi tạo
Mục tiêu: Hiểu cơ chế mảng động hoạt động bên dưới
std::vector.Lý thuyết: Contiguous memory, capacity vs size.
Thực hành: Khởi tạo class
DynamicArray<T>với constructor cấp phát bộ nhớ thô.
Ngày 9: Dynamic Array - Resize & Amortized Complexity
Mục tiêu: Hiểu vì sao
push_backlà O(1) amortized.Lý thuyết: Growth factor (x1.5 vs x2), amortized analysis.
Thực hành: Cài
push_backvới resize, in ra số lần cấp phát lại khi thêm 10,000 phần tử.
Ngày 10: Singly Linked List
Mục tiêu: Cài đặt cấu trúc con trỏ nối tiếp cơ bản.
Lý thuyết: Node, head/tail pointer, trade-off vs array.
Thực hành: Cài insert đầu/cuối, delete, traverse cho Singly Linked List.
Ngày 11: Doubly Linked List
Mục tiêu: Mở rộng thêm khả năng duyệt ngược.
Lý thuyết: Prev/next pointer, chi phí bộ nhớ tăng thêm.
Thực hành: Cài Doubly Linked List, so sánh chi phí insert/delete giữa vị trí đầu/giữa/cuối với Singly.
Ngày 12: Stack
Mục tiêu: Hiểu 2 cách cài Stack và ưu nhược điểm.
Lý thuyết: LIFO, array-based vs linked-based stack.
Thực hành: Cài
Stack<T>bằng cả 2 cách, viết test push/pop/peek.
Ngày 13: Queue
Mục tiêu: Cài Queue hiệu quả bằng circular buffer.
Lý thuyết: FIFO, circular buffer, vấn đề "wasted space" của queue mảng thường.
Thực hành: Cài
CircularQueue<T>với enqueue/dequeue O(1).
Ngày 14: Hash Table - Collision Resolution
Mục tiêu: Hiểu 2 chiến lược xử lý va chạm hash.
Lý thuyết: Separate chaining vs open addressing (linear/quadratic probing).
Thực hành: Cài
HashMap<K,V>bằng separate chaining.
Ngày 15: Hash Table - Load Factor & Resize
Mục tiêu: Hiểu khi nào và tại sao hash table cần resize.
Lý thuyết: Load factor, rehashing, hàm hash tốt vs xấu.
Thực hành: Thêm cơ chế auto-resize khi load factor > 0.75, benchmark trước/sau.
Ngày 16: Binary Search Tree
Mục tiêu: Cài đặt cấu trúc cây tìm kiếm nhị phân cơ bản.
Lý thuyết: BST property, insert/delete/search, traversal (in-order, pre-order, post-order).
Thực hành: Cài
BST<T>đầy đủ insert/delete/search + in-order traversal.
Ngày 17: Heap (Binary Heap)
Mục tiêu: Hiểu cấu trúc dùng cho priority queue.
Lý thuyết: Min-heap/max-heap, heapify up/down, array representation của heap.
Thực hành: Cài
MinHeap<T>với insert và extract-min.
Nhóm 3: Memory Model - So sánh C++/Java/Python (Ngày 18–24)
Ngày 18: C++ - Stack vs Heap
Mục tiêu: Phân biệt rõ vùng nhớ stack và heap trong C++.
Lý thuyết: Lifetime,
new/delete, con trỏ vs giá trị.Thực hành: Viết chương trình in địa chỉ biến stack và biến heap, quan sát khác biệt.
Ngày 19: C++ - RAII
Mục tiêu: Hiểu nguyên lý quản lý tài nguyên gắn với lifetime object.
Lý thuyết: RAII, destructor tự động, vì sao C++ không cần GC.
Thực hành: Viết một class
FileGuardtự đóng file trong destructor.
Ngày 20: Java - Heap, Stack & Object Allocation
Mục tiêu: Hiểu Java quản lý object khác C++ thế nào.
Lý thuyết: Mọi object nằm trên heap, stack chỉ chứa reference & primitive.
Thực hành: Dùng JVM flag in ra thông tin heap khi chạy 1 chương trình Java đơn giản.
Ngày 21: Java - Garbage Collector tổng quan
Mục tiêu: Hiểu ý tưởng generational GC.
Lý thuyết: Young/Old generation, Minor GC vs Major GC, GC roots.
Thực hành: Bật GC log, quan sát các lần GC chạy khi tạo nhiều object tạm.
Ngày 22: Python - Object Reference & Reference Counting
Mục tiêu: Hiểu mô hình biến trong Python là reference, không phải giá trị.
Lý thuyết: Mọi thứ là object, refcount tăng/giảm khi gán/xóa biến.
Thực hành: Dùng
sys.getrefcount()quan sát refcount thay đổi qua các thao tác gán.
Ngày 23: Python - Garbage Collector (Cycle Detector)
Mục tiêu: Hiểu vì sao refcounting không đủ, cần thêm cycle collector.
Lý thuyết: Reference cycle, generational GC của CPython,
gcmodule.Thực hành: Tạo 1 cycle tham chiếu vòng, quan sát
gc.collect()dọn nó.
Ngày 24: Tổng hợp so sánh 3 memory model
Mục tiêu: Có bảng so sánh rõ ràng để dùng về sau.
Lý thuyết: Tự lập bảng: cơ chế cấp phát, cơ chế giải phóng, ai chịu trách nhiệm, chi phí.
Thực hành: Viết cùng 1 bài toán (linked list có cycle) bằng cả 3 ngôn ngữ, so sánh cách mỗi ngôn ngữ xử lý bộ nhớ.
Nhóm 4: Function Call Internals (Ngày 25–29)
Ngày 25: Call Stack & Stack Frame
Mục tiêu: Hiểu cấu trúc 1 stack frame khi gọi hàm.
Lý thuyết: Return address, saved registers, local variables, stack pointer/base pointer.
Thực hành: Vẽ sơ đồ stack frame cho 1 hàm C có tham số và biến local.
Ngày 26: Recursion & Stack Depth
Mục tiêu: Hiểu giới hạn thực tế của đệ quy.
Lý thuyết: Stack overflow, tail call, vì sao không phải ngôn ngữ nào cũng tối ưu tail call.
Thực hành: Viết hàm đệ quy tính giai thừa, tìm độ sâu tối đa trước khi stack overflow.
Ngày 27: Calling Convention
Mục tiêu: Hiểu quy ước truyền tham số ở tầng thấp.
Lý thuyết: cdecl, stdcall, System V AMD64 ABI (truyền qua register vs stack).
Thực hành: Đọc tài liệu System V ABI, tóm tắt cách 6 tham số đầu được truyền qua register nào.
Ngày 28: Nhìn Function Call ở tầng Assembly
Mục tiêu: Thấy tận mắt lời gọi hàm biến thành assembly.
Lý thuyết:
call/retinstruction,push/popcho stack frame.Thực hành: Dùng
objdump -dhoặcgdbdisassemble một hàm C đơn giản, chỉ ra đoạn prologue/epilogue.
Ngày 29: Ôn tập Function Call Internals
Mục tiêu: Củng cố nhóm kiến thức tuần.
Lý thuyết: Tổng hợp lại toàn bộ pipeline: gọi hàm → tạo stack frame → thực thi → return → dọn stack frame.
Thực hành: Tự vẽ full diagram từ lúc gọi hàm đến khi return, áp cho ví dụ đệ quy 2 tầng.
Nhóm 5: Project - Tự viết vector/hashmap/linked_list (Ngày 30–35)
Ngày 30: Setup Project & Vector Skeleton
Mục tiêu: Khởi động project tổng hợp, thiết kế API cho
vector<T>.Lý thuyết: Thiết kế interface trước khi implement (push_back, size, operator[], iterator).
Thực hành: Tạo repo, viết header
vector.hppvới skeleton class + test framework cơ bản (catch2 hoặc tự viết assert).
Ngày 31: Hoàn thiện Vector
Mục tiêu: Vector chạy đúng và hiệu năng chấp nhận được.
Lý thuyết: Copy constructor, move semantics, iterator invalidation.
Thực hành: Hoàn thiện
push_back,resize, iterator; viết test so sánh hành vi vớistd::vector.
Ngày 32: Viết HashMap
Mục tiêu: Áp dụng kiến thức Ngày 14–15 vào 1 implementation hoàn chỉnh.
Lý thuyết: Chọn hash function, thiết kế bucket array.
Thực hành: Viết
hashmap.hppvới insert/get/erase cơ bản.
Ngày 33: Hoàn thiện HashMap
Mục tiêu: Xử lý các edge case còn thiếu.
Lý thuyết: Xử lý collision khi bucket đầy, resize khi load factor cao.
Thực hành: Thêm auto-resize + test với 100,000 key ngẫu nhiên, đo thời gian insert/lookup.
Ngày 34: Viết Linked List
Mục tiêu: Hoàn thiện thành phần thứ 3 của project.
Lý thuyết: Ôn lại thiết kế node-based structure, chọn singly hay doubly cho project này.
Thực hành: Viết
linked_list.hppvới insert/delete tại vị trí bất kỳ, iterator hỗ trợ range-based for.
Ngày 35: Test & Benchmark tổng kết Giai đoạn 0
Mục tiêu: Đánh giá lại toàn bộ 3 cấu trúc dữ liệu đã viết.
Lý thuyết: Big-O thực tế vs lý thuyết, ảnh hưởng của cache locality lên kết quả benchmark.
Thực hành: Viết benchmark suite so sánh
vector/hashmap/linked_listtự viết với thư viện chuẩn (std::vector,std::unordered_map,std::list), ghi báo cáo kết quả và giải thích chênh lệch.
Giai đoạn 1 - Object Oriented Programming (Ngày 36–98)
Module 1: Object Model (Ngày 36–40)
Ngày 36: Class, Object, Instance
Mục tiêu: Phân biệt rạch ròi 3 khái niệm hay bị dùng lẫn lộn.
Lý thuyết: Class là blueprint, Object là thực thể trong bộ nhớ, Instance là quan hệ giữa object và class nó thuộc về.
Thực hành: Viết 1 class
Carbằng cả Java/C++/Python, tạo 3 instance, in địa chỉ/id để thấy chúng là các object riêng biệt.
Ngày 37: State & Behavior
Mục tiêu: Thiết kế class tách bạch trạng thái và hành vi hợp lý.
Lý thuyết: State (fields/attributes) mô tả dữ liệu, Behavior (methods) mô tả hành vi tác động lên state.
Thực hành: Thiết kế class
TrafficLightvới state (màu hiện tại) và behavior (chuyển màu theo quy tắc).
Ngày 38: Java Object Model
Mục tiêu: Hiểu mọi thứ trong Java đều kế thừa từ
Object.Lý thuyết: Reference type,
Objectclass (equals, hashCode, toString), object luôn nằm trên heap.Thực hành: Override
equals/hashCode/toStringcho classCar, giải thích vì sao cần override đồng thời cả 2 hàm đầu.
Ngày 39: C++ Object Model
Mục tiêu: Hiểu C++ có value semantics, khác Java/Python.
Lý thuyết: Object có thể nằm trên stack hoặc heap, copy semantics mặc định, không có "mọi thứ kế thừa 1 root class".
Thực hành: Viết ví dụ minh hoạ copy-by-value khi truyền object C++ vào hàm, so với truyền reference (Java) cho cùng logic.
Ngày 40: Python Object Model & So sánh tổng hợp
Mục tiêu: Hiểu "everything is an object" trong Python, kể cả class.
Lý thuyết: Class cũng là instance của
type, mọi biến là reference tới object.Thực hành: Lập bảng so sánh Object Model Java vs C++ vs Python (nơi lưu trữ, semantics khi gán, root class).
Module 2: Encapsulation (Ngày 41–46)
Ngày 41: Access Control
Mục tiêu: Hiểu cơ chế kiểm soát truy cập ở 3 ngôn ngữ.
Lý thuyết: public/private/protected (Java, C++) vs quy ước
_/__(Python - "consenting adults").Thực hành: Viết cùng 1 class với field private, thử truy cập trái phép để thấy compiler/runtime phản ứng khác nhau.
Ngày 42: Invariants
Mục tiêu: Hiểu vì sao encapsulation tồn tại là để bảo vệ invariant.
Lý thuyết: Invariant là điều kiện luôn đúng trong suốt vòng đời object; setter/method phải giữ invariant đó.
Thực hành: Liệt kê invariant cho 1 class
Temperature(ví dụ: không dưới -273.15°C), viết validate trong setter.
Ngày 43: Information Hiding
Mục tiêu: Hiểu lợi ích của việc giấu chi tiết implementation.
Lý thuyết: Giảm coupling, cho phép thay đổi implementation mà không phá vỡ client code.
Thực hành: Refactor 1 class đang expose field trực tiếp thành encapsulated, đổi implementation bên trong mà không đổi API.
Ngày 44: Lab - BankAccount
Mục tiêu: Áp dụng encapsulation vào bài toán tài chính có invariant chặt.
Lý thuyết: Invariant "số dư không âm", "giao dịch phải atomic".
Thực hành: Viết class
BankAccountvới deposit/withdraw đảm bảo invariant, viết test cho trường hợp withdraw quá số dư.
Ngày 45: Lab - Wallet
Mục tiêu: Thực hành composition + encapsulation.
Lý thuyết: Wallet chứa nhiều BankAccount, quản lý qua interface thống nhất.
Thực hành: Viết class
Walletchứa listBankAccount, thêm method tổng số dư, chuyển tiền giữa 2 account trong cùng wallet.
Ngày 46: Lab - Money (Value Object)
Mục tiêu: Làm quen với khái niệm value object (sẽ gặp lại ở DDD).
Lý thuyết: Value object bất biến (immutable), so sánh bằng giá trị chứ không bằng identity.
Thực hành: Viết class
Money(amount + currency) immutable, override equals theo giá trị, không cho phép cộng 2 currency khác nhau.
Module 3: Constructors & Lifecycle (Ngày 47–54)
Ngày 47: Java Constructor
Mục tiêu: Hiểu constructor overloading và constructor chaining.
Lý thuyết: Nhiều constructor cùng class,
this(...)gọi constructor khác.Thực hành: Viết class
Rectanglevới 3 constructor overload (không tham số, 1 tham số cho hình vuông, 2 tham số).
Ngày 48: Java Lifecycle & GC liên hệ
Mục tiêu: Hiểu object Java "chết" như thế nào (không có destructor tường minh).
Lý thuyết: Không còn reference trỏ tới → eligible for GC;
finalize()đã deprecated, vì sao nên tránh.Thực hành: Viết ví dụ object mất hết reference, dùng
-Xlog:gcquan sát khi nó được thu hồi.
Ngày 49: C++ Constructor
Mục tiêu: Nắm các loại constructor trong C++.
Lý thuyết: Default constructor, parameterized constructor, copy constructor.
Thực hành: Viết class
Pointvới đủ 3 loại constructor, trace khi nào mỗi loại được gọi.
Ngày 50: C++ Destructor & RAII Lifecycle
Mục tiêu: Hiểu vòng đời object C++ gắn liền với scope.
Lý thuyết: Destructor gọi tự động khi object ra khỏi scope, RAII cho resource management.
Thực hành: Viết class
ScopedTimerin ra thời gian sống khi destructor được gọi.
Ngày 51: C++ Rule of Three/Five
Mục tiêu: Hiểu vì sao cần định nghĩa đồng thời copy constructor, copy assignment, destructor (và move variants).
Lý thuyết: Rule of Three (C++98), Rule of Five (C++11 thêm move constructor/move assignment).
Thực hành: Viết class quản lý raw pointer, cố tình bỏ qua Rule of Three để thấy lỗi double-free, sau đó sửa đúng.
Ngày 52: Python new vs init
Mục tiêu: Phân biệt 2 bước tạo object trong Python.
Lý thuyết:
__new__tạo instance (allocate),__init__khởi tạo state (configure) trên instance đã tồn tại.Thực hành: Override
__new__để implement Singleton pattern đơn giản, giải thích vì sao không nên dùng__init__cho việc này.
Ngày 53: Python del
Mục tiêu: Hiểu finalizer trong Python và các cạm bẫy.
Lý thuyết:
__del__không đảm bảo thời điểm gọi (phụ thuộc GC), không nên dùng cho resource cleanup quan trọng - dùng context manager thay thế.Thực hành: So sánh dọn resource bằng
__del__vs bằngwith+__enter__/__exit__.
Ngày 54: So sánh Lifecycle 3 ngôn ngữ
Mục tiêu: Tổng hợp toàn bộ Module 3.
Lý thuyết: Lập bảng: thời điểm tạo, thời điểm huỷ, ai kiểm soát, cơ chế dọn resource.
Thực hành: Làm quiz tự đặt 10 câu hỏi tình huống (VD: "Object này bị leak ở ngôn ngữ nào, tại sao?").
Module 4: Inheritance (Ngày 55–60)
Ngày 55: IS-A Relationship
Mục tiêu: Hiểu khi nào quan hệ kế thừa thực sự hợp lý.
Lý thuyết: Liskov Substitution Principle sơ khởi - subclass phải thay thế được superclass mà không phá vỡ hành vi.
Thực hành: Đánh giá 3 ví dụ quan hệ (Square-Rectangle, Dog-Animal, Circle-Ellipse), chỉ ra ví dụ nào IS-A giả.
Ngày 56: Reuse qua Inheritance
Mục tiêu: Hiểu lợi ích tái sử dụng code qua kế thừa, và giới hạn của nó.
Lý thuyết: Code reuse vs coupling chặt giữa base và derived class.
Thực hành: Viết 1 hierarchy 2 tầng (
Shape→Circle/Square) chia sẻ logic chung ở base class.
Ngày 57: Polymorphism qua Inheritance (preview)
Mục tiêu: Thấy trước lợi ích lớn nhất của inheritance là polymorphism.
Lý thuyết: Base class reference có thể trỏ tới derived object, gọi method đúng phiên bản derived.
Thực hành: Viết hàm
printArea(Shape s)nhận bất kỳ subclass nào củaShape.
Ngày 58: Anti-pattern - Fragile Base Class
Mục tiêu: Nhận diện vấn đề khi sửa base class làm vỡ subclass.
Lý thuyết: Fragile Base Class Problem - thay đổi tưởng chừng vô hại ở base phá vỡ hành vi ở derived.
Thực hành: Tạo ví dụ minh hoạ: sửa 1 method ở base class làm subclass hoạt động sai, phân tích nguyên nhân.
Ngày 59: Anti-pattern - Deep Inheritance Hierarchy
Mục tiêu: Nhận diện vấn đề khi hierarchy quá sâu.
Lý thuyết: Khó hiểu, khó test, khó thay đổi khi hierarchy có 5-6 tầng.
Thực hành: Vẽ sơ đồ 1 hierarchy 5 tầng giả định, chỉ ra vấn đề khi cần thêm behavior mới ở tầng giữa.
Ngày 60: Lab - Refactor Inheritance sai thành đúng
Mục tiêu: Áp dụng kiến thức cả tuần vào 1 case thực tế.
Lý thuyết: Ôn lại Liskov Substitution Principle.
Thực hành: Lấy ví dụ Square kế thừa Rectangle (vi phạm LSP), refactor lại thiết kế đúng.
Module 5: Polymorphism (Ngày 61–66)
Ngày 61: Dynamic Dispatch
Mục tiêu: Hiểu cơ chế chọn đúng phiên bản method lúc runtime.
Lý thuyết: Dynamic dispatch vs static dispatch, tại sao polymorphism cần dynamic dispatch.
Thực hành: Viết ví dụ 3 class kế thừa cùng override 1 method, gọi qua base reference, quan sát method nào thực thi.
Ngày 62: Late Binding vs Early Binding
Mục tiêu: Phân biệt thời điểm quyết định method nào được gọi.
Lý thuyết: Early binding (compile-time, VD: overloading) vs Late binding (runtime, VD: overriding).
Thực hành: Viết ví dụ minh hoạ cả 2 loại binding trong cùng 1 class, chỉ rõ cái nào xảy ra lúc nào.
Ngày 63: Runtime Polymorphism trong Java
Mục tiêu: Hiểu Java mặc định virtual (trừ static/final/private).
Lý thuyết: Mọi method instance trong Java là virtual by default.
Thực hành: Viết ví dụ override method, thử đánh dấu
finalđể thấy compiler chặn override.
Ngày 64: Runtime Polymorphism trong C++
Mục tiêu: Hiểu C++ cần khai báo
virtualtường minh.Lý thuyết: Không có
virtual→ static binding (khác Java); vtable sẽ học sâu ở Module 8.Thực hành: Viết ví dụ base class không có
virtual, gọi qua pointer, so sánh kết quả khi thêmvirtual.
Ngày 65: Duck Typing trong Python
Mục tiêu: Hiểu polymorphism không cần inheritance trong Python.
Lý thuyết: "If it walks like a duck and quacks like a duck..." - chỉ cần có đúng method là dùng được.
Thực hành: Viết hàm nhận bất kỳ object nào có method
.quack(), không cần base class chung.
Ngày 66: Lab - Payment Gateway
Mục tiêu: Áp dụng polymorphism vào bài toán thực tế.
Lý thuyết: Ôn lại toàn bộ Module 5.
Thực hành: Thiết kế
PaymentMethod(abstract) vớiCreditCard/Paypal/BankTransfer, viết hàm xử lý thanh toán generic qua interface chung.
Module 6: Abstraction (Ngày 67–72)
Ngày 67: Interface vs Abstract Class
Mục tiêu: Phân biệt 2 công cụ abstraction chính.
Lý thuyết: Interface = pure contract (không implementation), Abstract class = contract + có thể có implementation chung.
Thực hành: Lập bảng khi nào dùng interface, khi nào dùng abstract class.
Ngày 68: Interface trong Java
Mục tiêu: Thực hành interface Java, bao gồm default method.
Lý thuyết:
interfacekeyword, multiple interface implementation, default method (Java 8+).Thực hành: Viết interface
Drivablevới default method, 2 class implement.
Ngày 69: Abstract Class trong C++
Mục tiêu: Thực hành pure virtual function.
Lý thuyết:
virtual ... = 0, abstract class không thể instantiate.Thực hành: Viết abstract class
Shapevới pure virtualarea(), 2 class con implement.
Ngày 70: Duck Typing / Protocol trong Python
Mục tiêu: Hiểu cách Python formalize abstraction qua
abcmodule.Lý thuyết:
ABC,@abstractmethod, Protocol (structural typing, PEP 544).Thực hành: Viết abstract base class bằng
ABC, so sánh với dùngProtocol(không cần kế thừa).
Ngày 71: Contract - Design by Contract
Mục tiêu: Hiểu khái niệm hợp đồng giữa method và caller.
Lý thuyết: Precondition, postcondition, class invariant (Bertrand Meyer's Design by Contract).
Thực hành: Viết precondition/postcondition dạng assertion cho 1 method
withdraw(amount).
Ngày 72: Lab - Storage Abstraction
Mục tiêu: Áp dụng abstraction vào bài toán thực tế thường gặp production.
Lý thuyết: Ôn lại Module 6.
Thực hành: Thiết kế interface
StoragevớiS3/Local/GCSimplementation, viết code client không phụ thuộc implementation cụ thể.
Module 7: Composition (Ngày 73–77)
Ngày 73: HAS-A Relationship
Mục tiêu: Hiểu quan hệ "chứa" khác với "là" (inheritance) thế nào.
Lý thuyết: Composition = object này chứa object khác như 1 field.
Thực hành: Viết ví dụ
CarHAS-AEngine, so sánh với thiết kế saiCarIS-AEngine.
Ngày 74: Delegation
Mục tiêu: Hiểu cách object A "nhờ" object B thực hiện hành vi.
Lý thuyết: Delegation pattern, forwarding method calls.
Thực hành: Viết class
Cardelegate methodstart()choEngine.start().
Ngày 75: Composition over Inheritance
Mục tiêu: Hiểu nguyên lý thiết kế nổi tiếng này thực sự nghĩa là gì.
Lý thuyết: Composition linh hoạt hơn, tránh Fragile Base Class, dễ thay đổi hành vi lúc runtime.
Thực hành: So sánh 2 thiết kế cho cùng bài toán (VD: Character trong game) - 1 bản dùng inheritance sâu, 1 bản dùng composition.
Ngày 76: Refactor Inheritance Tree → Composition
Mục tiêu: Thực hành refactor thực tế.
Lý thuyết: Ôn lại kỹ thuật Extract Interface, Replace Inheritance with Delegation.
Thực hành: Lấy hierarchy
Bird→FlyingBird/SwimmingBird/Penguin(vốn có vấn đề), refactor sang composition dùngFlyBehavior/SwimBehavior.
Ngày 77: Lab hoàn thiện Composition
Mục tiêu: Chốt lại Module 7 bằng review.
Lý thuyết: Tổng hợp lại khi nào composition thắng inheritance, khi nào không.
Thực hành: Viết report ngắn (1 trang) so sánh ưu nhược 2 cách tiếp cận dựa trên các lab đã làm.
Module 8: Object Internals (Ngày 78–86)
Ngày 78: C++ vtable
Mục tiêu: Hiểu cơ chế bảng ảo đứng sau
virtualfunction.Lý thuyết: Virtual table (vtable) là mảng con trỏ hàm, mỗi class có polymorphic behavior sẽ có 1 vtable riêng.
Thực hành: Vẽ sơ đồ vtable cho 1 hierarchy 2 tầng có override.
Ngày 79: C++ vptr & Object Layout
Mục tiêu: Hiểu object polymorphic có thêm 1 con trỏ ẩn.
Lý thuyết: vptr (virtual pointer) nằm đầu object, trỏ tới vtable của class thực sự.
Thực hành: Dùng
sizeof()so sánh kích thước object có và không có virtual function, giải thích chênh lệch.
Ngày 80: C++ Multiple Inheritance & vtable phức tạp
Mục tiêu: Hiểu vtable trở nên phức tạp thế nào khi đa kế thừa.
Lý thuyết: Nhiều vptr trong 1 object, vấn đề diamond inheritance.
Thực hành: Viết ví dụ diamond inheritance với
virtualbase class, giải thích cách C++ giải quyết bằng virtual inheritance.
Ngày 81: Java invokevirtual
Mục tiêu: Hiểu bytecode Java thực hiện dynamic dispatch ra sao.
Lý thuyết: JVM bytecode instruction
invokevirtual- lookup method table dựa trên runtime class.Thực hành: Compile 1 class Java đơn giản, dùng
javap -cxem bytecode, tìm instructioninvokevirtual.
Ngày 82: Java invokeinterface
Mục tiêu: Hiểu vì sao gọi qua interface cần instruction riêng.
Lý thuyết:
invokeinterfacekhácinvokevirtualvì lookup phức tạp hơn (object có thể implement nhiều interface).Thực hành: Viết ví dụ gọi method qua interface reference, dùng
javap -cso sánh bytecode với gọi qua class reference.
Ngày 83: Java Method Dispatch Table
Mục tiêu: Hiểu JVM tổ chức method table tương đương vtable ra sao.
Lý thuyết: Method table trong class metadata của JVM, so sánh khái niệm với vtable C++.
Thực hành: Lập bảng so sánh cơ chế dispatch Java vs C++ (điểm giống và khác).
Ngày 84: Python MRO
Mục tiêu: Hiểu Python giải quyết đa kế thừa bằng thuật toán tuyến tính hoá.
Lý thuyết: Method Resolution Order, thuật toán C3 linearization.
Thực hành: Viết 1 ví dụ đa kế thừa (diamond) trong Python, in
ClassName.__mro__, giải thích thứ tự.
Ngày 85: Python Descriptor Protocol
Mục tiêu: Hiểu cơ chế đứng sau
property, method binding.Lý thuyết:
__get__/__set__/__delete__, descriptor là nền tảng củaproperty,staticmethod,classmethod.Thực hành: Tự viết 1 descriptor đơn giản validate giá trị khi gán (tương tự property có validation).
Ngày 86: Tổng hợp Object Internals
Mục tiêu: Chốt lại toàn bộ Module 8.
Lý thuyết: So sánh 3 cơ chế dispatch: vtable (C++) vs method table (JVM) vs MRO + descriptor (Python).
Thực hành: Viết bài tổng hợp (dạng bảng) so sánh chi phí runtime của mỗi cơ chế dispatch.
Project: Plugin System (Ngày 87–98)
Ngày 87: Thiết kế kiến trúc Plugin System
Mục tiêu: Lên thiết kế tổng thể trước khi code.
Lý thuyết: Plugin architecture cần: contract (interface), discovery mechanism, lifecycle management.
Thực hành: Vẽ sơ đồ kiến trúc Plugin System sẽ xây (chọn 1 ngôn ngữ chính, khuyến nghị Java hoặc Python).
Ngày 88: Định nghĩa Plugin Interface
Mục tiêu: Thiết kế contract chuẩn cho mọi plugin.
Lý thuyết: Interface tối thiểu cần có (VD:
name(),execute(),init(config)).Thực hành: Viết interface/abstract class
Plugin.
Ngày 89: Plugin Registry
Mục tiêu: Xây nơi lưu trữ và tra cứu plugin đã đăng ký.
Lý thuyết: Registry pattern - trung tâm quản lý các instance plugin.
Thực hành: Viết class
PluginRegistryvớiregister()/get()/getAll().
Ngày 90: Plugin Loader - Load động
Mục tiêu: Load plugin không cần hard-code trong source.
Lý thuyết: Java dùng reflection (
Class.forName), Python dùngimportlib, C++ dùngdlopen.Thực hành: Viết
PluginLoaderload class plugin từ tên string cấu hình, khởi tạo qua reflection/importlib.
Ngày 91: Plugin mẫu 1 - Logging Plugin
Mục tiêu: Có plugin thực tế đầu tiên chạy qua hệ thống.
Lý thuyết: Ôn lại interface đã định nghĩa Ngày 88.
Thực hành: Viết
LoggingPluginimplement interface, đăng ký và chạy qua registry.
Ngày 92: Plugin mẫu 2 - Validation Plugin
Mục tiêu: Thêm plugin thứ 2 để kiểm tra tính mở rộng.
Lý thuyết: Đảm bảo thêm plugin mới không cần sửa code core.
Thực hành: Viết
ValidationPlugin, verify Open/Closed Principle được giữ vững.
Ngày 93: Plugin mẫu 3 - Notification Plugin
Mục tiêu: Có đủ 3 plugin để test hệ thống chạy nhiều plugin cùng lúc.
Lý thuyết: Thứ tự thực thi plugin, có cần priority không.
Thực hành: Viết
NotificationPlugin, chạy pipeline cả 3 plugin tuần tự.
Ngày 94: Plugin Lifecycle
Mục tiêu: Thêm quản lý vòng đời cho plugin.
Lý thuyết: init → start → stop, tương tự lifecycle của framework thật (Spring bean lifecycle sẽ gặp lại sau).
Thực hành: Thêm method
init()/start()/stop()vào interface, cập nhật cả 3 plugin mẫu.
Ngày 95: Plugin Configuration
Mục tiêu: Cho phép mỗi plugin có config riêng.
Lý thuyết: Configuration injection - mỗi plugin nhận 1 config object/map lúc init.
Thực hành: Thêm file config (JSON/YAML) chứa cấu hình riêng từng plugin, load và inject vào
init().
Ngày 96: Error Handling & Isolation
Mục tiêu: Đảm bảo 1 plugin lỗi không kéo sập cả hệ thống.
Lý thuyết: Fault isolation, try/catch quanh từng plugin execution, logging lỗi riêng biệt.
Thực hành: Cố tình viết 1 plugin lỗi (throw exception), verify hệ thống vẫn chạy tiếp các plugin khác.
Ngày 97: Test toàn bộ Plugin System
Mục tiêu: Đảm bảo hệ thống hoạt động đúng ở nhiều kịch bản.
Lý thuyết: Ôn lại toàn bộ thiết kế đã xây.
Thực hành: Viết test suite: load nhiều plugin, plugin lỗi, plugin config sai, thứ tự thực thi.
Ngày 98: Review & Retrospective Giai đoạn 1
Mục tiêu: Tổng kết toàn bộ giai đoạn OOP.
Lý thuyết: Nhìn lại 8 module đã học, liên hệ chúng với Plugin System vừa xây (module nào được dùng ở đâu).
Thực hành: Viết báo cáo retrospective: những gì khó nhất, những gì áp dụng được ngay vào công việc hiện tại.
Giai đoạn 2 - Refactoring & Code Smells (Ngày 99–126)
Tài liệu chính: Refactoring (Martin Fowler). Mục tiêu: nhìn ra code "xấu" và có kỹ thuật sửa nó an toàn, có hệ thống - không phải sửa cảm tính.
Nhóm 1: Code Smells (Ngày 99–108)
Ngày 99: Giới thiệu Code Smells
Mục tiêu: Hiểu khái niệm code smell và vì sao nó quan trọng hơn "code sai".
Lý thuyết: Code smell không phải bug - là dấu hiệu cảnh báo thiết kế có vấn đề, dễ dẫn tới bug/khó bảo trì về sau.
Thực hành: Đọc lại 1 đoạn code cũ của chính bạn (dự án cũ), liệt kê cảm giác "khó chịu" khi đọc - đó chính là smell.
Ngày 100: Long Method
Mục tiêu: Nhận diện và hiểu tác hại của method quá dài.
Lý thuyết: Method dài thường làm nhiều việc, khó test, khó đặt tên rõ nghĩa.
Thực hành: Tìm 1 method > 50 dòng trong codebase thật, liệt kê các "đoạn logic con" có thể tách ra.
Ngày 101: God Object (God Class)
Mục tiêu: Nhận diện class ôm quá nhiều trách nhiệm.
Lý thuyết: Vi phạm Single Responsibility Principle, thường là class kiểu
Manager/Utils/Helperphình to dần.Thực hành: Tìm 1 class có > 10 method không liên quan nhau, phân nhóm các method theo trách nhiệm.
Ngày 102: Shotgun Surgery
Mục tiêu: Nhận diện khi 1 thay đổi nhỏ buộc phải sửa ở rất nhiều nơi.
Lý thuyết: Logic liên quan bị rải rác thay vì tập trung - ngược lại với Divergent Change.
Thực hành: Giả lập 1 thay đổi yêu cầu (VD: đổi định dạng ngày tháng) trên 1 codebase, đếm số file phải sửa.
Ngày 103: Feature Envy
Mục tiêu: Nhận diện method "ganh tị" dữ liệu của class khác.
Lý thuyết: Method dùng dữ liệu của class khác nhiều hơn dữ liệu của chính class nó - dấu hiệu đặt sai vị trí.
Thực hành: Tìm 1 method truy cập field của object khác nhiều lần liên tiếp, đánh giá xem có nên move sang class kia không.
Ngày 104: Data Clumps
Mục tiêu: Nhận diện nhóm dữ liệu hay đi chung nhưng chưa được gom thành object.
Lý thuyết: VD:
street, city, zipcodeluôn xuất hiện cùng nhau ở nhiều method → nên là 1 classAddress.Thực hành: Tìm 3 method có cùng nhóm tham số lặp lại, đề xuất object gom nhóm.
Ngày 105: Duplicate Code
Mục tiêu: Nhận diện logic trùng lặp - smell phổ biến và nguy hiểm nhất.
Lý thuyết: Duplicate code làm tăng chi phí bảo trì gấp N lần (N = số chỗ trùng); "Rule of Three" khi nào nên trừu tượng hoá.
Thực hành: Dùng công cụ phát hiện duplicate code (hoặc tìm thủ công) trên 1 project, liệt kê top 3 đoạn trùng lặp nhiều nhất.
Ngày 106: Primitive Obsession
Mục tiêu: Nhận diện lạm dụng kiểu nguyên thuỷ thay vì object có ý nghĩa.
Lý thuyết: VD: dùng
Stringcho email/phone/currency thay vì class riêng - mất khả năng validate và mất ý nghĩa domain.Thực hành: Tìm 3 chỗ dùng
String/intcho khái niệm domain có quy tắc riêng, đề xuất value object thay thế.
Ngày 107: Switch Statements / Conditional Complexity
Mục tiêu: Nhận diện switch/if-else phình to lặp lại nhiều nơi theo cùng 1 loại điều kiện.
Lý thuyết: Khi cùng 1 switch trên "loại" xuất hiện ở nhiều method → dấu hiệu cần polymorphism (sẽ học kỹ thuật sửa ở Ngày 111).
Thực hành: Tìm 1 switch/if-else theo
type/enumxuất hiện ở ít nhất 2 nơi trong codebase.
Ngày 108: Lab tổng hợp - Phát hiện Code Smells
Mục tiêu: Luyện khả năng "ngửi" smell trên codebase thật, chưa sửa vội.
Lý thuyết: Ôn lại toàn bộ 8 smell đã học.
Thực hành: Chọn 1 open-source project vừa (hoặc project cũ của bạn), viết báo cáo liệt kê ít nhất 10 smell tìm thấy, phân loại theo từng nhóm.
Nhóm 2: Refactoring Techniques (Ngày 109–118)
Ngày 109: Extract Method
Mục tiêu: Học kỹ thuật cơ bản nhất, dùng để sửa Long Method.
Lý thuyết: Tách 1 đoạn logic thành method riêng có tên rõ nghĩa, giữ nguyên hành vi.
Thực hành: Áp dụng Extract Method lên method dài đã tìm ở Ngày 100.
Ngày 110: Introduce Parameter Object
Mục tiêu: Học kỹ thuật sửa Data Clumps.
Lý thuyết: Gom nhóm tham số hay đi cùng nhau thành 1 object truyền vào.
Thực hành: Áp dụng lên nhóm tham số đã tìm ở Ngày 104, tạo class
Address/tương tự.
Ngày 111: Replace Conditional with Polymorphism
Mục tiêu: Học kỹ thuật sửa Switch Statements - liên hệ trực tiếp Module 5 (Polymorphism) đã học.
Lý thuyết: Thay switch theo type bằng cách để mỗi type override 1 method riêng.
Thực hành: Áp dụng lên switch đã tìm ở Ngày 107, tạo hierarchy/interface thay thế.
Ngày 112: Move Method
Mục tiêu: Học kỹ thuật sửa Feature Envy.
Lý thuyết: Chuyển method sang class mà nó thực sự "quan tâm" dữ liệu nhiều nhất.
Thực hành: Áp dụng lên method đã tìm ở Ngày 103.
Ngày 113: Extract Class
Mục tiêu: Học kỹ thuật sửa God Object.
Lý thuyết: Tách 1 nhóm field + method liên quan thành class mới, giữ lại quan hệ composition với class gốc.
Thực hành: Áp dụng lên God Class đã tìm ở Ngày 101, tách thành 2-3 class có trách nhiệm rõ ràng.
Ngày 114: Replace Temp with Query
Mục tiêu: Học kỹ thuật giảm biến tạm, tăng khả năng Extract Method sau này.
Lý thuyết: Biến tạm chỉ dùng 1 lần nên thay bằng method trả về giá trị đó - dễ tách nhỏ hơn.
Thực hành: Tìm 1 method có biến tạm tính toán phức tạp, thay bằng method riêng.
Ngày 115: Inline Method & Inline Class
Mục tiêu: Học kỹ thuật ngược lại Extract - đôi khi gộp lại mới là refactor đúng.
Lý thuyết: Khi 1 method/class quá nhỏ và không còn ý nghĩa tách riêng, nên gộp lại để giảm indirection thừa.
Thực hành: Tìm 1 ví dụ over-engineered (quá nhiều lớp indirection cho logic đơn giản), áp dụng Inline.
Ngày 116: Encapsulate Field & Encapsulate Collection
Mục tiêu: Học kỹ thuật bảo vệ state khỏi bị sửa trực tiếp từ bên ngoài.
Lý thuyết: Field/collection public dễ bị mutate không kiểm soát - bọc qua getter trả về bản sao/view bất biến.
Thực hành: Tìm 1 class expose
Listtrực tiếp, sửa lại để trả về unmodifiable view.
Ngày 117: Lab - Áp dụng chuỗi kỹ thuật liên tiếp
Mục tiêu: Luyện phản xạ chọn đúng kỹ thuật cho đúng smell, áp dụng nối tiếp nhau.
Lý thuyết: Refactoring thường là chuỗi bước nhỏ (baby steps), không phải 1 lần sửa lớn.
Thực hành: Lấy 1 method vừa dài vừa có switch vừa có data clump, áp dụng liên tiếp Extract Method → Replace Conditional with Polymorphism → Introduce Parameter Object.
Ngày 118: Ôn tập Refactoring Techniques
Mục tiêu: Củng cố toàn bộ nhóm kỹ thuật.
Lý thuyết: Lập bảng "Smell → Technique tương ứng" để dùng làm cheat-sheet về sau.
Thực hành: Tự làm quiz: cho 5 đoạn code có smell khác nhau, chọn đúng kỹ thuật sửa cho từng đoạn.
Nhóm 3: Project - Refactor hệ thống E-commerce (Ngày 119–126)
Ngày 119: Phân tích codebase E-commerce xấu
Mục tiêu: Có bức tranh tổng thể trước khi sửa.
Lý thuyết: Luôn phân tích/lập bản đồ smell trước khi refactor, tránh sửa tuỳ hứng.
Thực hành: Chuẩn bị (hoặc viết sẵn) 1 codebase E-commerce nhỏ có chủ đích chứa nhiều smell (Order, Product, Payment, Customer), liệt kê toàn bộ smell tìm thấy theo từng module.
Ngày 120: Refactor Order Module
Mục tiêu: Áp dụng kỹ thuật vào module đầu tiên.
Lý thuyết: Ôn lại Extract Method, Extract Class cho God Object.
Thực hành: Refactor class
Order/OrderServiceđang ôm quá nhiều logic (tính tiền, validate, gửi email...) thành các class tách bạch.
Ngày 121: Refactor Product/Inventory Module
Mục tiêu: Xử lý smell Data Clumps và Primitive Obsession thường gặp ở module này.
Lý thuyết: Ôn lại Introduce Parameter Object, value object cho
Price/SKU.Thực hành: Refactor
Productclass, gom nhóm dữ liệu rời rạc thành value object.
Ngày 122: Refactor Payment Module
Mục tiêu: Xử lý switch statement điển hình theo loại phương thức thanh toán.
Lý thuyết: Ôn lại Replace Conditional with Polymorphism (đã làm ở Lab OOP Ngày 66 - liên hệ lại).
Thực hành: Refactor logic xử lý payment đang if-else theo type thành hierarchy polymorphism.
Ngày 123: Refactor Customer/User Module
Mục tiêu: Xử lý Feature Envy và Shotgun Surgery thường gặp ở module quản lý user.
Lý thuyết: Ôn lại Move Method.
Thực hành: Refactor các method đang truy cập chéo dữ liệu giữa
CustomervàOrdervề đúng vị trí.
Ngày 124: Characterization Tests
Mục tiêu: Đảm bảo refactor không phá vỡ hành vi cũ.
Lý thuyết: Characterization test - viết test ghi lại hành vi hiện tại của code (kể cả khi chưa chắc đúng) trước khi refactor, để có lưới an toàn.
Thực hành: Viết bộ test bao phủ toàn bộ 4 module trước khi refactor (nếu chưa làm), verify test vẫn pass sau khi đã refactor ở các ngày trước.
Ngày 125: Đo lường cải thiện
Mục tiêu: Định lượng kết quả refactor, không chỉ cảm tính "sạch hơn".
Lý thuyết: Cyclomatic complexity, coupling giữa class, số dòng/method trung bình - công cụ đo (VD: SonarQube, hoặc thủ công).
Thực hành: Đo các chỉ số trên trước/sau refactor cho cả 4 module, lập bảng so sánh.
Ngày 126: Review & Retrospective Giai đoạn 2
Mục tiêu: Tổng kết toàn bộ giai đoạn Refactoring.
Lý thuyết: Nhìn lại mối liên hệ Smell → Technique → Kết quả đo lường được.
Thực hành: Viết báo cáo retrospective, đề xuất quy trình refactor bạn sẽ áp dụng cho công việc thực tế (VD: mỗi PR nên kèm 1 refactor nhỏ, definition of done bao gồm "không còn smell rõ ràng").