# Syllabus học C++

# NGÀY 0 (MỚI): THIẾT LẬP CÔNG CỤ

#### CMake

*   Cấu trúc `CMakeLists.txt` tối giản: `cmake_minimum_required`, `project()`, `set(CMAKE_CXX_STANDARD 23)`, `add_executable()`.
    
*   CMake sinh ra Makefile/Ninja - bản chất là trình sinh build system, không tự build.
    
*   Out-of-source build: build trong thư mục `build/` riêng, không build ngay trong source.
    
*   Flags cảnh báo bắt buộc dùng suốt lộ trình: `-Wall -Wextra -Wpedantic`.
    

#### Sanitizers

*   `-fsanitize=address` (ASan): phát hiện buffer overflow, use-after-free, double-free - nhanh hơn Valgrind 2-20 lần.
    
*   `-fsanitize=undefined` (UBSan): phát hiện Undefined Behavior - tràn số, biến chưa khởi tạo, chia 0.
    
*   `-fsanitize=thread` (TSan): phát hiện Race Condition - dùng lại ở phần Concurrency.
    
*   Valgrind vẫn hữu ích cho Massif/Cachegrind (phân tích heap chi tiết), nhưng ASan/UBSan là bước kiểm tra đầu tiên.
    

#### vcpkg

*   Cài vcpkg, khởi tạo `vcpkg.json` (manifest mode).
    
*   Tích hợp CMake qua `CMAKE_TOOLCHAIN_FILE`.
    
*   Cài thử `fmt` để kiểm chứng pipeline.
    

#### Google Test

*   Thêm qua vcpkg hoặc `FetchContent`.
    
*   Viết 1 test rỗng xác nhận `enable_testing()` + `add_test()` chạy qua `ctest`.
    

**LAB NGÀY 0**

1.  Tạo project CMake in "Hello, Modern C++", build bằng `cmake --build build`.
    
2.  Viết hàm đọc ngoài mảng 1 phần tử, build với `-fsanitize=address`, so sánh thông báo với Valgrind trên cùng lỗi.
    
3.  Cài `fmt` qua vcpkg, thay `std::cout` bằng `fmt::print()`.
    
4.  Viết 1 test rỗng bằng Google Test, chạy `ctest` thành công.
    

**Câu hỏi:**

1.  Tại sao debug với sanitizer nên build `-O0 -g`, còn benchmark (`<chrono>`, sẽ gặp ở Ngày 7) phải `-O2`/`-O3`? Trộn lẫn thì hậu quả gì?
    
2.  File build system CMake sinh ra đóng vai trò gì trong 4 bước Pipeline Biên dịch (Ngày 1)?
    

**Quy tắc áp dụng từ đây:** mọi bài build bằng CMake; mọi Lab bộ nhớ chạy kèm ASan/UBSan song song Valgrind; từ Ngày 5.5 mọi Lab có test Google Test.

# PHẦN 1: 65 NGÀY - NỀN TẢNG C++ & TỐI ƯU HÓA

## Phần 1a: Kiến thức nền tảng

### Ngày 1: Cơ chế biên dịch, liên kết và vòng đời của một chương trình C++

*   **Pipeline Biên dịch**
    
    *   **Preprocessing:** Cách `#include`, `#define`, `#ifdef` hoạt động. Hiểu "Translation Unit".
        
    *   **Compilation:** Parsing, Code Generation. Cách trình biên dịch chuyển mã nguồn thành Assembly.
        
    *   **Assembling:** Chuyển Assembly thành mã máy (Object file `.o`/`.obj`). Cấu trúc Object file.
        
    *   **Linking:** Static vs dynamic linking (DLL/SO). Symbol table và lỗi `undefined reference`.
        
*   **Thực hành và quan sát**
    
    *   CLI: biên dịch tay với `g++`/`clang++` (flag `E`, `S`, `c` để xem từng bước).
        
    *   Tách chương trình thành nhiều `.cpp`/`.h`. Tự tạo thư viện tĩnh (`.a`/`.lib`) và liên kết.
        
*   **Advanced concepts & optimization**
    
    *   **One Definition Rule (ODR):** tại sao quan trọng để tránh lỗi liên kết.
        
    *   **Link-Time Optimization (LTO):** tối ưu hóa xuyên file.
        

*(Ghi chú: từ ngày này, build bằng CMake đã thiết lập Ngày 0, không gõ* `g++` *tay nữa.)*

### Ngày 2: Hệ thống kiểu dữ liệu tĩnh, type safety và kiến trúc bộ nhớ

*   **Hệ thống kiểu dữ liệu**
    
    *   Fundamental types: `int`, `char`, `float`, `double`, `bool`. Size và range.
        
    *   Memory alignment & padding: tại sao struct 1 `char` + 1 `int` tốn 8 bytes thay vì 5.
        
    *   Static vs dynamic typing: tại sao kiểm tra kiểu lúc biên dịch giúp C++ nhanh hơn ngôn ngữ thông dịch.
        
*   **Type safety & initialization**
    
    *   `=` vs `{}` (uniform initialization). `{}` ngăn "narrowing conversion".
        
    *   Implicit vs explicit cast. Sự nguy hiểm của C-style cast.
        
    *   Const-correctness: dùng `const` mọi nơi có thể, giúp compiler tối ưu tốt hơn.
        
*   **Nghiên cứu**
    
    *   Xem giá trị biến dạng hexadecimal qua debugger.
        
    *   Undefined behavior (UB): tràn số, biến chưa khởi tạo.
        

### Ngày 3: Object, value và L-value vs R-value

*   **Objects và values:** object = vùng nhớ có tên, kiểu, tuổi thọ. L-value có địa chỉ cố định; R-value là giá trị tạm thời.
    
*   **Tham chiếu:** `T&` (bí danh); `T&&` (sơ lược - chiếm đoạt tài nguyên tạm thời); `const T&` là tiêu chuẩn vàng cho đối tượng lớn.
    
*   **Optimization mindset:** Copy elision & RVO. Bài tập viết hàm swap, quan sát di chuyển dữ liệu.
    

*Tổng kết sau 3 ngày: giải thích chính xác chuyện gì xảy ra từ Build đến Run; biết sắp xếp struct để tốn ít RAM; phân biệt ngay L/R-value; luôn dùng* `{}` *và* `const`*.*

### Ngày 4: Biểu thức (expressions) & toán tử

*   **Toán tử và thứ tự ưu tiên:** Bitwise (`&`,`|`,`^`,`~`,`<<`,`>>`) - chìa khóa optimization. Short-circuit evaluation. Type promotion (usual arithmetic conversions).
    
*   **Biểu thức hằng và tối ưu hóa:** `++i` vs `i++` về hiệu năng. `constexpr` - ép compiler tính trước.
    
*   **Thực hành:** Nhân/chia bằng dịch bit, so sánh tốc độ. Operator precedence tránh bug logic.
    

**Phụ lục:** Sau khi học `constexpr`, đọc thêm: một hàm có thể "không có gì để trả" (ví dụ tìm số chia hết đầu, không thấy) - dùng sentinel (`-1`) là thói quen xấu vì `-1` có thể hợp lệ. Đây là lý do `std::optional<int>` tồn tại - học đầy đủ ở Ngày 50.9. Ghi nhớ vấn đề này.

### Ngày 5: Luồng điều khiển & bộ điều phối nhánh (branch predictor)

*   **Câu lệnh điều kiện:** If-else vs switch-case (jump tables). Selection statements với initializer (C++17): `if (init; condition)`. Branch prediction: tại sao mảng đã sort nhanh hơn.
    
*   **Vòng lặp:** For/While/Do-while khác biệt mã máy. Range-for qua Iterators. Loop unrolling.
    
*   **Thực hành:** Tìm kiếm trên mảng lớn, đo thời gian sort vs chưa sort. `[[likely]]`/`[[unlikely]]` (C++20).
    

### Ngày 6: Hàm (functions)

*   **Khai báo, định nghĩa, overloading:** Function signature. Overload resolution. Default arguments ở mức mã máy.
    
*   **Cơ chế truyền tham số:** Pass-by-value (kiểu nhỏ); `T&` (tránh copy); `const T&` (tiêu chuẩn vàng cho object lớn); `T*` (khi nào dùng con trỏ thay tham chiếu).
    
*   **Phân tích:** So sánh trả về object lớn kiểu truyền thống vs qua tham số. Copy elision & RVO.
    

### Ngày 7: Call stack, inlining và recursion optimization

*   **Call stack:** Stack frame khi gọi hàm. Stack overflow. Calling conventions (`__cdecl`, `__stdcall`, `__fastcall`).
    
*   **Inlining và đệ quy:** `inline` và tại sao compiler có thể lờ nó. Recursion vs Iteration. Tail call optimization (TCO).
    
*   **Tổng kết:** Fibonacci 3 cách (đệ quy thường/đuôi/vòng lặp). Dùng godbolt.org xem Assembly.
    

**Chiến lược (4 ngày tới):** godbolt.org là công cụ phải dùng; luôn đo bằng `<chrono>`; chú ý Cache Locality (row-major vs column-major).

### Ngày 8: Con trỏ & sự phân mảnh bộ nhớ

*Mục tiêu: hiểu con trỏ dưới góc độ vật lý và chi phí truy xuất.*

*   **Lý thuyết địa chỉ:** Virtual address space. `int*` và `double*` cùng size (8-byte/64-bit) nhưng giải mã khác. Const pointers: 4 tổ hợp `const`+pointer; `const` giúp constant folding.
    
*   **Indirection & overhead:** Pointer chasing - chi phí CPU "nhảy" từ địa chỉ con trỏ đến dữ liệu. `void*`/`reinterpret_cast`.
    
*   **Lab:** Đo thời gian truy cập biến trực tiếp vs qua 3 tầng con trỏ (triple pointer).
    

### Ngày 9: Mảng kiểu C, cache line & memory locality

*Mục tiêu: hiểu tại sao Mảng nhanh nhất nhờ cơ chế Cache.*

*   **Mảng & CPU cache:** Cache line 64 byte - cache hit khi duyệt mảng. Spatial locality. False sharing (đa nhân).
    
*   **Mảng đa chiều:** Row-major order. Challenge: duyệt theo hàng vs cột.
    
*   **Rủi ro:** Buffer overflow - tự viết chương trình gây tràn để hiểu cách phòng tránh.
    

### NGÀY 10: Phép toán con trỏ (Arithmetic) & Alignment

*Mục tiêu: thao tác dữ liệu tốc độ cao, tối ưu kích thước struct.*

*   **Pointer arithmetic:** `ptr++` khác nhau theo `sizeof`. Duyệt bằng con trỏ vs `[i]` - phân tích Assembly.
    
*   **Data alignment & padding:** Địa chỉ chia hết 4/8 nhanh hơn. Struct padding - đặt biến lớn trước.
    
*   **Thực hành:** `alignof`/`offsetof`. Thiết kế struct 5 kiểu dữ liệu sao cho tổng size nhỏ nhất.
    

### NGÀY 11: Quản lý vùng nhớ tự do (Free Store) & Raw Memory

*Mục tiêu: kiểm soát tuyệt đối cấp phát/thu hồi.*

*   **Heap allocation:** `new`/`delete` - bảng quản lý bộ nhớ OS. Memory fragmentation.
    
*   **Resource management:** Placement new (memory pool nâng cao). Dangling pointers, wild pointers, memory leaks.
    
*   **Lab:** `SlowCopy` vs `FastCopy` (cache line + pointer arithmetic). Tại sao `vector` vượt trội `list`.
    

**Phụ lục- Sanitizer song song Valgrind:** Từ ngày này, mỗi lần Valgrind chạy, chạy thêm 1 lần với `-fsanitize=address,undefined` (thiết lập Ngày 0), so sánh tốc độ và độ chi tiết. Từ Ngày 13, coi ASan là công cụ kiểm tra đầu tiên, Valgrind là công cụ thứ hai (đặc biệt cho Massif/Cachegrind).

**Chiến lược:** Dùng Memory View của debugger; benchmark 1 triệu phần tử với `chrono`; đọc thêm "Data-Oriented Design".

### NGÀY 12: Stack vs Heap

*Mục tiêu: hiểu bản chất vật lý và tại sao Stack luôn nhanh hơn.*

*   **Stack (automatic storage):** Stack pointer tăng/giảm. Scope & lifetime - "unwinding the stack". Cache hit gần 100%.
    
*   **Heap (free store):** Malloc/free vs new/delete - freelist, bitmaps. Overhead: heap tốn hàng trăm chu kỳ CPU, stack tốn 1.
    
*   **Thực hành:** Đo chênh lệch khởi tạo 1 triệu object trên stack vs heap.
    

**Câu hỏi:** Mảng 1000 `int` - đặt trong hàm (Stack) hay `new` (Heap) ít nguy cơ "stack overflow" hơn? Tại sao?

### NGÀY 13: New, Delete và Memory Leaks

*Mục tiêu: học quản lý thủ công để hiểu tại sao cần tự động hóa.*

*   **Các lỗi kinh điển:** Memory leaks (quên `delete`) - Valgrind/Diagnostic Tools. Dangling pointers. Double free.
    
*   **Mảng trên heap & exception:** `new[]`/`delete[]` dùng sai cặp gây lỗi nghiêm trọng. Exception safety: `new` thành công nhưng hàm sau crash → leak dù có `delete`.
    
*   **Lab:** Gây fragmentation cố ý, quan sát hiệu năng giảm.
    

**Phụ lục:** Từ đây, ASan là công cụ kiểm tra đầu tiên, Valgrind là thứ hai.

### NGÀY 14: std::vector và std::string

*Mục tiêu: hiểu container chuẩn quản lý bộ nhớ thông minh thế nào để bắt chước.*

*   **Reallocation & capacity:** Size vs capacity. Amortized complexity - tại sao nhân đôi khi đầy. Data locality: vector "vô đối" so với list.
    
*   **Small String Optimization (SSO):** Chuỗi ngắn lưu trên Stack, không Heap. Kiểm tra ngưỡng SSO trình biên dịch.
    
*   **Lab:** `reserve()` - so sánh tốc độ có/không có.
    

### NGÀY 15: Mini Project - Smart Pointer (My\_Unique\_Ptr)

*Mục tiêu: tổng hợp Pointer, Heap, Destructor để tạo công cụ quản lý bộ nhớ tự động.*

*   **Thiết kế Wrapper:** Template cho mọi kiểu dữ liệu. Destructor tự `delete` (RAII).
    
*   **Chống copy & move:** Tại sao `unique_ptr` không copy được. Transfer of ownership.
    
*   **Kiểm chứng:** Dùng `MyUniquePtr` giải quyết leak Ngày 13. Valgrind 0 bytes rò rỉ.
    

**Chiến lược:** Luôn hỏi "Ai là chủ sở hữu vùng nhớ này?" - Stack: hệ thống là chủ; Heap: bạn là chủ (hay quên); Smart pointer: đối tượng là chủ.

## Phần 1b: Trừu tượng hóa & quản lý tài nguyên

### NGÀY 16: Interface vs. Implementation

*Mục tiêu: tách "cái gì" và "làm thế nào" để tối ưu bảo trì & compile.*

*   **Tính đóng gói:** `public`/`private`/`protected` - ranh giới cho compiler. Invariants: Constructor đảm bảo trạng thái hợp lệ, nếu không → throw. Struct vs class.
    
*   **Che dấu thông tin:** Interface class (pure virtual, sơ lược). Pimpl idiom - giảm thời gian biên dịch, che chi tiết.
    
*   **Thực hành:** Thiết kế lớp `Date` (PPP) với Invariants chống ngày 32/13.
    

### NGÀY 17: Constructors & Destructors

*   **Constructor:** Default/parameterized/delegating. Member initializer list (tối ưu - tránh gọi default rồi gán lại). Explicit constructors.
    
*   **Destructors & vòng đời:** Thứ tự khởi tạo/hủy. Resource cleanup (file, memory, socket).
    
*   **Optimization Insight:** Static objects, thread-local storage. Hạn chế biến toàn cục phức tạp.
    

### NGÀY 18: Copy Semantics

*Mục tiêu: deep vs shallow copy - sai là "giết chết" hiệu năng.*

*   **Copy constructor & assignment:** Member-wise copy mặc định. Khi nào cần tự viết (quản lý con trỏ). Deep copy.
    
*   **Rule of Three:** Destructor/copy constructor/copy assignment liên hệ mật thiết. Self-assignment protection (`if(this==&other)`).
    
*   **Thực hành:** Nâng cấp `My_Vector` (Ngày 11) hỗ trợ deep copy hoàn chỉnh.
    

### NGÀY 19: Move Semantics

*   **R-value & std::move:** Move constructor - O(1) thay vì O(n). Move assignment.
    
*   **Rule of five & rule of zero:** Bộ 5 hoàn thiện. Rule of zero - dùng smart pointer/STL để không cần tự viết gì.
    
*   **Lab:** So sánh copy vs move khi truyền `vector` 100MB.
    

### NGÀY 20: Tổng kết thiết kế lớp & dự án mini

*   **Kỹ thuật bổ trợ:** Const member functions. Friend functions/classes (khi nào phá vỡ đóng gói có kiểm soát).
    
*   **Dự án Mini "high-performance string class":** Viết `MyString` (deep copy, move, SSO cơ bản), không leak, tốc độ tiệm cận `std::string`.
    

**Chiến lược:** Luôn hỏi "tại sao move nhanh hơn?"; xem Assembly move vs copy; tư duy ownership.

### NGÀY 21: Kế thừa (Inheritance) & phân cấp đối tượng

*   **Kế thừa:** Quan hệ "Is-a". `protected`/`public`/`private` inheritance. Thứ tự constructor/destructor.
    
*   **Memory layout:** Object con trong RAM. Object slicing - nguy hiểm của pass-by-value cho base class.
    
*   **Thực hành:** Hệ thống `Shape` (Circle, Triangle từ PPP), vẽ sơ đồ bộ nhớ.
    

### NGÀY 22: Đa hình (Polymorphism) & Hàm ảo

*Mục tiêu: hiểu Runtime Binding.*

*   **Cơ chế Virtual:** `virtual`, cần con trỏ/tham chiếu để kích hoạt. Virtual destructor - thiếu gây leak nghiêm trọng.
    
*   `override` **&** `final`**:** override ép kiểm tra chữ ký. `final` → devirtualization (tăng tốc).
    
*   **Lab:** Ví dụ gây lỗi khi thiếu `virtual` destructor.
    

### NGÀY 23: Deep Dive - V-Table & V-Ptr

*Mục tiêu: hiểu kỹ thuật tại sao đa hình có chi phí hiệu năng.*

*   **V-Table:** Mảng con trỏ hàm cho mỗi class có hàm ảo. **V-Ptr:** con trỏ ẩn mỗi đối tượng, tốn thêm 8-byte (64-bit).
    
*   **Chi phí runtime lookup:** `Object → V-Ptr → V-Table → Function Address → Execute`. Hàm ảo không thể `inline` thông thường. Ảnh hưởng CPU pipeline & branch prediction.
    
*   **Lab:** `sizeof` so sánh có/không hàm ảo. godbolt.org xem Assembly lời gọi ảo.
    

### NGÀY 24: Abstract Classes & Interface

*Mục tiêu: thiết kế "hợp đồng" cho hệ thống lớn.*

*   **Pure virtual (**`=0`**):** Abstract base class (ABC) - không thể khởi tạo.
    
*   **Interface kiểu C++:** Dùng ABC làm interface. Interface inheritance (public) vs implementation inheritance (private). Plugin system.
    
*   **Thinking:** SOLID Principles (đặc biệt Liskov Substitution) trong C++.
    

### NGÀY 25: Tối ưu hóa thiết kế & dự án mini

*   **Kỹ thuật:** `dynamic_cast` vs `static_cast` - tại sao `dynamic_cast` chậm (RTTI). Tắt RTTI để tối ưu.
    
*   **Dự án Mini "hệ thống quản lý vật phẩm":** `Item` với `use()`, `getPrice()` ảo; 10-20 lớp con; `vector<Item*>`; đánh dấu `final` cho hàm không kế thừa nữa.
    
*   **Review:** "Nếu cần hiệu năng tuyệt đối, có nên dùng hàm ảo? Giải pháp thay thế (template/CRTP)?"
    

**Chiến lược (5 ngày này):** "Virtual = Indirection = Latency". Game engine/HFT thường hạn chế hàm ảo trong hot loops.

**Câu hỏi:** Mảng 1 triệu object gọi hàm ảo trong loop - tại sao chậm hơn nhiều so với hàm thường cùng nội dung?

### NGÀY 26: RAII

*Mục tiêu: mở rộng RAII ra ngoài bộ nhớ (file, mutex, socket, DB connection).*

*   **RAII nâng cao:** Exception làm hỏng `delete` thủ công. Scope-bound resource management. Lab: `FileHandler`, `LockGuard` tự viết.
    
*   **Exception safety levels:** No-throw/strong/basic guarantee. Copy-and-swap idiom.
    
*   **Optimization Insight:** RAII giúp compiler tối ưu tốt hơn nhờ scope rõ ràng.
    

### NGÀY 27: std::unique\_ptr

*   **Unique\_ptr:** Zero-overhead abstraction. Custom deleters (ví dụ `fclose` thay `delete`).
    
*   **Move-only:** Truyền/trả về từ hàm. `std::make_unique` (C++14) an toàn & nhanh hơn `new`.
    
*   **Lab:** Chuyển project "Vật phẩm" (Ngày 25) sang `unique_ptr`.
    

### NGÀY 28: std::shared\_ptr & weak\_ptr

*   **Reference counting:** Control block. Chi phí gấp đôi con trỏ thô. Thread-safety atomic nhưng có chi phí. `make_shared` - 1 lần cấp phát.
    
*   **Circular dependency:** Hai `shared_ptr` trỏ lẫn nhau → leak vĩnh viễn. `weak_ptr` - quan sát không tăng đếm, bẻ gãy vòng lặp.
    
*   **Lab:** Đo chi phí copy `shared_ptr` vs `unique_ptr`.
    

### NGÀY 29: Tối ưu hóa quản lý tài nguyên (Advanced RAII)

*   **Đa hình với smart pointers:** `vector<unique_ptr<Base>>` là cách tốt nhất. `static_pointer_cast`/`dynamic_pointer_cast`.
    
*   **Tài nguyên không copy được:** Socket/DB connection pool dựa RAII. Small object optimization.
    

**Phụ lục:** khi làm Lab ngày này, chạy song song ASan/UBSan (Ngày 0) với Valgrind để tự so sánh 2 công cụ trên cùng lỗi.

### NGÀY 30: Dự án hệ thống quản lý tài nguyên

*   **Dự án "Simple memory pool & smart resource manager":** RAII cho mọi thứ; `unique_ptr` mặc định, `shared_ptr` chỉ khi cần chia sẻ; move semantics; custom deleter cho tài nguyên giả lập (`malloc`).
    
*   **Ôn tập:** Từ "Hello World" đến "cache line", "V-table", "move semantics".
    

**Lời khuyên:** `unique_ptr` mặc định (90% trường hợp); Valgrind là bạn thân; tư duy ownership.

## Phần 1c: STL & Generic Programming

### NGÀY 31: Templates & Deduction

*Mục tiêu: hiểu cơ chế "Instantiation" - trình biên dịch viết code hộ bạn.*

*   **Function templates:** Cú pháp, template parameters/arguments. Template argument deduction. Overload resolution với template vs hàm thường. Optimization: template nhanh hơn `void*`/đa hình vì không chi phí hàm ảo, compiler `inline` hoàn hảo.
    
*   **Class templates:** Container tổng quát (giống `vector<T>`). Default template arguments. Member function templates.
    
*   **Thực hành:** Viết lại `swap` và `Stack<T>` thủ công. godbolt.org xem 2 hàm sinh ra hoàn toàn khác cho `int`/`double`.
    

### NGÀY 32: Template Specialization

*   **Full specialization:** Tại sao cần (ví dụ `vector<bool>` tối ưu bộ nhớ khác). Cú pháp `template<> class MyClass<specific_type>`.
    
*   **Partial specialization:** Chuyên biệt cho `T*`, `T&`. Class template cho phép partial, function template không (phải overload).
    
*   **Lab:** Hàm `copy` tổng quát - specialization dùng `memcpy` cho POD thay vì loop `for`.
    

### NGÀY 33: Variadic Templates

*   **Parameter packs:** Cú pháp `...`. Đệ quy template giải nén đối số. Typesafe printf.
    
*   **Fold expressions (C++17):** Rút gọn 10 dòng xuống 1. Unary/binary fold.
    
*   **Thực hành:** Hàm `sum(a,b,c,d...)` nhận số lượng bất kỳ, cộng tại compile-time.
    

### NGÀY 34: Non-type Template Parameters & Compile-time Logic

*   **Non-type parameters:** Truyền hằng số (`int`, `size_t`). `std::array<T,N>` nhanh hơn `vector` (size cố định trên stack).
    
*   **Template Metaprogramming (TMP):** Tính giai thừa/Fibonacci lúc biên dịch.
    
*   **Lab:** `Matrix<T, Rows, Cols>` - so sánh với Matrix con trỏ động.
    

### NGÀY 35: Đóng gói thư viện Template

*   `typename` **vs** `class`**, dependent names:** Lỗi `expected 'typename' before...`. Nested templates.
    
*   **Tách file:** Tại sao không tách `.h`/`.cpp` như hàm thường. "Inclusion model" và `extern template` (C++11).
    
*   **Dự án Mini:** `EventSystem` (Signal/Slot) dùng variadic templates, an toàn kiểu tại compile-time.
    

**Chiến lược:** Hiểu Code Bloat (mỗi kiểu mới sinh mã mới); đừng hoảng khi lỗi template dài; dùng `static_assert` (C++11).

### NGÀY 36: Sequence Containers & bộ nhớ liên tục

*Mục tiêu: hiểu vì sao* `vector` *là "ông vua" hiệu năng.*

*   **Vector & deque:** Reallocation, growth factor. Deque - segmented buffer, không liên tục như vector. `reserve()` triệt tiêu chi phí copy.
    
*   **List & forward\_list:** Node và chi phí `next/prev`. "The slow truth" - list chậm hơn vector ngay cả khi chèn giữa (cache miss).
    
*   **Lab:** Đo thời gian duyệt 1 triệu phần tử vector vs list.
    

### NGÀY 37: Associative Containers - cây nhị phân & sắp xếp

*   **Set & map:** Red-black tree. O(log n). Key luôn `const`.
    
*   **Multi-containers & comparators:** `multimap`/`multiset`. Custom comparators (lambda).
    
*   **Lab:** Chi phí bộ nhớ mỗi node `map` so với `vector<pair>`.
    

### NGÀY 38: Unordered Containers - bảng băm

*   **unordered\_map/set:** Buckets, load factor, rehash. Hash functions & collision resolution.
    
*   **Tối ưu:** Khi nào `unordered_map` chậm hơn `map` (nhiều xung đột O(n)). Custom hash cho user-defined types.
    
*   **Thực hành:** Từ điển đơn giản, so sánh `map` vs `unordered_map` với 500,000 từ.
    

### NGÀY 39: Độ phức tạp thuật toán (Big O) & CPU Cache (Deep Optimization)

*   **Big O:** Complexity của toàn bộ STL containers. "Lý thuyết" vs "thực tế".
    
*   **Kiến trúc Cache & locality:** Spatial locality. Cache line 64 bytes. Pointer chasing (`list`/`map` phải đợi RAM).
    
*   **Research:** Data-Oriented Design - "flat maps" trong Game thay `map` truyền thống.
    

### NGÀY 40: Tổng kết & chọn lựa Container

*   **Container adaptors & views (C++20):** `stack`, `queue`, `priority_queue`. `std::span` - truy cập liên tục an toàn không copy.
    
*   **Dự án Mini "high-performance log processor":** Thống kê IP (`unordered_map`), sort theo count (`vector` + `sort`), tối ưu bộ nhớ với `string_view`.
    
*   **Review:** Sơ đồ quyết định "khi nào dùng container nào".
    

**Chiến lược:** "By default, use vector" (Stroustrup).

### NGÀY 41: Iterators

*   **Phân loại:** Input/output (1 lần). Forward/bidirectional. Random access (sức mạnh `vector`). Contiguous (C++20).
    
*   **Iterator adapters:** `advance`, `distance`, `next`, `prev`. `back_inserter`/`front_inserter`. Stream iterators.
    
*   **Lab:** `my_find` chạy trên cả `list` và `vector` - phân tích chênh lệch di chuyển iterator.
    

### NGÀY 42: Function Objects (Functors) & Lambdas

*   **Functors:** Nạp chồng `operator()`. Nhanh hơn function pointer (compiler `inline` dễ). `less`/`greater`/`plus`.
    
*   **Lambda (C++11-20):** Capture clause, mutable lambda. Generic lambda (`auto` trong param, C++14). Capturing `this` - vấn đề vòng đời trong lập trình bất đối xứng.
    
*   **Lab:** So sánh Assembly lambda vs `std::function`.
    

### NGÀY 43: STL Algorithms - thay thế vòng lặp thủ công (Phần 1)

*   **Non-modifying & modifying:** `for_each`, `find`, `count`, `all_of/any_of`. `transform`, `copy`, `move`, `replace`.
    
*   **Tại sao tốt hơn vòng lặp:** compiler hiểu "ý định" → loop unrolling. Tránh off-by-one.
    
*   **Thực hành:** Chuyển vòng lặp lồng nhau sang `transform`/`find_if`.
    

### NGÀY 44: Sorting, Searching & Partitioning (Phần 2)

*   **Sort & partition:** `sort` vs `stable_sort` vs `partial_sort`. `partition`/`nth_element` (K-th nhanh không cần sort cả mảng).
    
*   **Binary search & merge:** `lower_bound`, `upper_bound`, `equal_range`. Set operations (`set_intersection`, `set_union`).
    
*   **Lab:** Benchmark `find` O(n) vs `binary_search` O(log n) trên 10 triệu phần tử.
    

### NGÀY 45: Tối ưu hóa thuật toán & song song hóa (Parallel STL)

*   **Execution policies (C++17):** `seq`/`par`/`par_unseq`.
    
*   **Dự án Mini "image processor":** `transform` parallel (độ sáng), `partition` (tách nhiễu), lambdas (filters).
    
*   **Tổng kết:** SIMD - cách STL Algorithms tận dụng.
    

**Chiến lược:** Hỏi "Complexity? Có mất stability?"; sort 1 lần + search nhiều lần → `vector`+`sort`+`lower_bound` (tận dụng cache line).

## Phần 1d: Advanced Topics cổ điển

### NGÀY 46: constexpr

*   **Sức mạnh:** `constexpr` var vs `const` var. Điều kiện hàm chạy compile-time. C++14/17/20 nới lỏng (loop, condition).
    
*   **Constexpr containers:** `std::array` và cấu trúc tĩnh. Tìm kiếm trên mảng hằng lúc biên dịch.
    
*   **Lab:** Factorial/sin/cos bằng `constexpr`, `static_assert` chứng minh kết quả có sẵn trước runtime.
    

### NGÀY 47: Type Traits

*   `<type_traits>`**:** `is_integral`, `is_floating_point`, `is_pointer`. `remove_reference`, `add_const`, `decay`.
    
*   **Compile-time decisions:** `std::conditional` chọn kiểu lúc biên dịch. Ứng dụng: `Buffer` tự chọn `int`/`long long`.
    
*   **Thực hành:** `static_assert` + type traits chặn kiểu không hợp lệ vào template.
    

### NGÀY 48: SFINAE

*   **Cơ chế:** "Thất bại trong thay thế không phải lỗi". Cách compiler duyệt ứng viên template.
    
*   `std::enable_if`**:** Kích hoạt/vô hiệu hàm template theo điều kiện.
    
*   **Lab:** Giải mã lỗi kinh điển khi SFINAE thất bại.
    

### NGÀY 49: C++20 Concepts

*   **Concepts & constraints:** `requires` clause. Định nghĩa concept (`concept Hashable = ...`).
    
*   **Refactoring:** Thay `enable_if` phức tạp bằng concepts - error message ngắn gọn hơn hẳn.
    
*   **Lab:** Concepts tạo hàm đa hình lúc compile-time (static polymorphism).
    

### NGÀY 50: Tổng kết Metaprogramming

*   **Dự án "compile-time unit converter":** Chuyển đổi đơn vị hoàn toàn lúc biên dịch. Cộng "mét" với "giây" → lỗi ngay bằng `static_assert`/concepts. `constexpr` đảm bảo 0 chu kỳ CPU runtime.
    
*   **Meta-cognition:** Metaprogramming (compile-time) vs đa hình (runtime) - đánh đổi thời gian thực thi vs thời gian biên dịch.
    

**Câu hỏi thử thách:** Tại sao tính `Sin(45°)` bằng `constexpr` tiết kiệm pin thiết bị di động hơn tính lúc runtime?

## NGÀY 50.5 – 50.9 - MODERN C++ (C++20/23)

### NGÀY 50.5: C++20 Modules

*Mục tiêu: hiểu tại sao Modules thay thế* `#include`*, và nó thay đổi Translation Unit (Ngày 1) thế nào.*

#### Vấn đề của Header - nhìn lại Ngày 1

*   `#include` là **chép dán văn bản**. Mỗi `.cpp` include header phải parse lại toàn bộ, dù header không đổi.
    
*   Hệ quả: thời gian biên dịch tăng theo số include; include guard chỉ ngăn include trùng trong 1 Translation Unit, không ngăn parse lại ở TU khác.
    
*   Macro không có scope - `#define` ở header A ảnh hưởng header B include sau, khác với biến có scope rõ ràng (Ngày 3).
    

#### Module hoạt động thế nào

*   Module interface unit biên dịch **1 lần** thành BMI - file khác `import` dữ liệu đã biên dịch, không parse lại text.
    
    ```cpp
    // math.cppm
    export module Math;
    export int add(int a, int b) { return a + b; }
    ```
    
    ```cpp
    // main.cpp
    import Math;
    int main() { return add(2,3); }
    ```
    
*   Không rò rỉ macro/tên nội bộ - những gì không `export` hoàn toàn vô hình khi `import` - đóng gói mạnh hơn Access Specifiers cấp Translation Unit (Ngày 16).
    
*   Module partitions: chia module lớn (`module Math:details;`) - biết sơ lược.
    
*   C++23: `import std;` thay include hàng chục header chuẩn.
    
*   **Thực tế:** hỗ trợ GCC/Clang/MSVC/CMake còn non - phần lớn codebase 2026 vẫn dùng header. Học để hiểu hướng đi, không kỳ vọng thay hoàn toàn ngay.
    

**LAB:**

1.  Viết module `Geometry` xuất `area(double r)`, dùng qua `import`.
    
2.  Chuyển bài tập hàm Ngày 6 từ header sang module, so sánh thời gian build với 10 file `.cpp` cùng include/import.
    

**Câu hỏi:**

1.  Tại sao Modules giải quyết triệt để "include guard" và macro leakage mà `#pragma once` không giải quyết hoàn toàn?
    
2.  Hàm không `export` trong module thì file khác `import` gọi được không? So với `private` (Ngày 16), khác nhau ở cấp độ nào?
    

### NGÀY 50.6: Ranges Library - Lập trình hàm trên STL

*Mục tiêu: viết lại thuật toán STL (Ngày 43-45) theo phong cách pipe, hiểu lazy evaluation.*

#### Range là gì

*   Tổng quát hóa `begin()/end()` (Ngày 41) - truyền trực tiếp không cần tách iterator tay.
    
*   `std::ranges::sort(v)` thay `std::sort(v.begin(), v.end())` - giảm sai sót.
    

#### Views - Lazy Evaluation

*   `views::filter`, `views::transform` **không tính ngay** - chỉ tính khi duyệt. Cùng họ ý tưởng với Expression Templates (Ngày 57) nhưng ở tầm algorithm.
    
*   Cú pháp pipe:
    
    ```cpp
    auto result = data
        | std::views::filter([](int x){ return x % 2 == 0; })
        | std::views::transform([](int x){ return x * x; });
    ```
    
*   `std::ranges::to<std::vector>(view)` (C++23) - chuyển view lazy thành container thật.
    
*   C++23: `views::zip`, `views::chunk` (liên hệ External Sorting Ngày 10, Phần DSA).
    

#### Cẩn trọng: Dangling View

*   `filter`/`transform` trên container tạm thời (R-value, Ngày 3) có thể trỏ vùng nhớ đã hủy khi duyệt sau - lỗi cực khó phát hiện.
    

**LAB:**

1.  Refactor "log processor" (Ngày 40): lọc + transform + sort IP bằng 1 chuỗi pipe, so với bản `for`+`unordered_map`+`sort` tay.
    
2.  Tạo Dangling View có chủ đích, build với ASan (Ngày 0) quan sát use-after-free.
    

**Câu hỏi:**

1.  Vì sao lazy evaluation của Ranges views nguy hiểm hơn `transform` cũ (eager)?
    
2.  `ranges::sort` nhận trực tiếp `views::filter(...)` không? Nếu không, tại sao? (liên hệ phân loại Iterator Ngày 41).
    

### NGÀY 50.7: Coroutines (Phần 1)

*Mục tiêu: hiểu cơ chế suspend/resume ở tầng compiler trước khi dùng thư viện thực tế.*

#### Vấn đề Coroutine giải quyết

*   Hàm thường (Ngày 7) chạy từ đầu đến cuối, không "tạm dừng giữa đường rồi tiếp tục" mà giữ nguyên biến cục bộ.
    
*   Coroutine cho phép suspend, trả quyền điều khiển, rồi resume đúng vị trí - không callback lồng nhau, không thread riêng.
    

#### 3 từ khóa

*   `co_await` (tạm dừng chờ), `co_yield` (tạm dừng và trả giá trị - generator), `co_return` (kết thúc). Chỉ cần 1 trong 3, compiler tự biến hàm thành coroutine.
    

#### "Dưới nắp capo" - Coroutine Frame trên Heap, không phải Stack

Nối trực tiếp Ngày 7 và Ngày 12:

*   Hàm thường: biến cục bộ trên Stack Frame, giải phóng ngay khi return (Ngày 7).
    
*   Coroutine: có thể suspend rồi resume **sau khi** Stack Frame gốc đã biến mất → compiler cấp phát **Coroutine Frame trên Heap** lưu biến cục bộ + trạng thái dừng.
    
*   Hệ quả: coroutine **không zero-cost** như tinh thần Ngày 27 - mỗi coroutine tốn 1 lần cấp phát Heap (hàng trăm chu kỳ CPU so với 1 chu kỳ Stack, Ngày 12).
    
*   **Promise type:** giao thức compiler dùng để biết cách hoạt động (`get_return_object`, `initial_suspend`, `final_suspend`, `yield_value`) - như Interface (Ngày 24/OOP 12) nhưng compiler gọi ngầm.
    

**LAB:**

1.  Generator `co_yield` sinh vô hạn Fibonacci, lấy 20 số đầu. So bộ nhớ với sinh trước cả dãy vào `vector`.
    
2.  Ước lượng kích thước Coroutine Frame so với Stack Frame của hàm Fibonacci đệ quy thường (Ngày 7).
    

**Câu hỏi:**

1.  Tại sao Coroutine Frame phải nằm trên Heap chứ không trên Stack (Ngày 7)?
    
2.  Generator bị hủy giữa đường (không duyệt hết) - ai giải phóng Coroutine Frame? Liên hệ RAII (Ngày 26).
    

### NGÀY 50.8: Coroutines (Phần 2) - Ứng dụng Async thực tế

*Mục tiêu: nối Coroutine với Ngày 53 (*`async`*/*`future`*) để thấy vì sao Coroutine là bước tiến cho I/O-bound.*

#### So sánh `std::async` (Ngày 53) và Coroutine

*   `std::async` cấp 1 thread thật/task - tốn tài nguyên OS (chi phí context-switch, Ngày 27). 10.000 task I/O-bound → 10.000 thread không khả thi.
    
*   Coroutine không cần thread riêng - hàng ngàn coroutine chạy trên **1 thread**, nhường CPU khi `co_await` chờ I/O. Mô hình web server hiện đại (Node.js, ASIO, Tokio).
    

#### Awaitable - giao thức `co_await`

*   3 hàm: `await_ready()`, `await_suspend()`, `await_resume()` - code trông tuyến tính nhưng chạy bất đối xứng, dễ đọc hơn callback lồng nhau.
    

#### Quyết định thực tế

| Loại workload | Công cụ |
| --- | --- |
| CPU-bound (Matrix multiply Ngày 45) | `std::thread`/Thread Pool (Ngày 55) |
| I/O-bound (file, network, DB) | Coroutine |
| Song song thực trên nhiều core | Thread |
| Hàng ngàn kết nối, ít tính toán mỗi kết nối | Coroutine |

**LAB:**

1.  Coroutine giả lập "tải file" (sleep giả lập I/O qua Awaitable tự viết). 1000 lần trên 1 thread, đo tổng thời gian.
    
2.  Chạy lại bằng 1000 `std::thread` thật, so sánh thời gian + bộ nhớ (mỗi thread OS tốn ~1-8MB Stack, Ngày 12).
    

**Câu hỏi:**

1.  Vì sao 1000 coroutine/1 thread nhanh hơn 1000 thread thật cho I/O-bound, nhưng chậm hơn cho CPU-bound thực sự (không sleep) trên máy đa nhân?
    
2.  Awaitable cần Mutex (Ngày 27) không, nếu mọi coroutine chạy trên đúng 1 thread?
    

### NGÀY 50.9: std::optional, std::variant, std::expected - Thay thế Exception & NULL

*Mục tiêu: nối Ngày 4 (phụ lục), Ngày 26 (Exception Safety) bằng công cụ hiện đại.*

#### `std::optional<T>`

*   Hàm "có thể không có gì trả" (ví dụ `findMin` cây rỗng - Ngày 11 DSA) trước dùng `nullptr`/`-1` - mơ hồ, dễ quên kiểm tra.
    
*   `optional<int> findMin(...)`: `.has_value()`/`if(result)` trước lấy `.value()` - rõ ràng ngay từ chữ ký hàm.
    

#### `std::variant<T1,T2,...>`

*   Nhắc lại `union` thô (Ngày 2): không biết đang giữ kiểu nào, dễ UB. `variant` luôn biết chính xác kiểu tại runtime.
    
*   `std::visit`: chạy đúng hàm theo kiểu đang giữ - "pattern matching" thay `switch` trên enum thủ công.
    

#### `std::expected<T,E>` (C++23)

*   Nối trực tiếp chi phí Exception (Ngày 26): `throw` đắt (Stack Unwinding), nhưng lỗi **mong đợi, thường xảy ra** (input sai, không tìm thấy record) dùng exception là lãng phí.
    
*   `expected` trả về **hoặc** giá trị **hoặc** lỗi - `.has_value()`/`.error()`, không Stack Unwinding, chi phí ngang trả `struct` thường.
    

#### Quy tắc chọn

*   Lỗi mong đợi, thường xảy ra → `optional`/`expected`.
    
*   Lỗi bất thường, phá vỡ tiền đề hệ thống (hết bộ nhớ, vi phạm invariant Ngày 16) → Exception.
    

**LAB:**

1.  Refactor parse số nguyên (Ngày 4) từ throw exception sang `expected<int, ParseError>`.
    
2.  Benchmark 1 triệu lần gọi, 50% input sai - so thời gian exception vs `expected` (`<chrono>`, Ngày 7).
    
3.  `variant<Circle, Square, Triangle>` (Ngày 21) + `std::visit` tính diện tích - so với Polymorphism/`virtual` (Ngày 22).
    

**Câu hỏi:**

1.  `optional` có thay hoàn toàn con trỏ nullable không? Trường hợp nào vẫn cần con trỏ thô/`unique_ptr`?
    
2.  So `variant`+`visit` (static, compile-time) với Polymorphism qua `virtual` (dynamic, V-Table Ngày 23) - khi nào chọn `variant`?
    

## Phần 1e: Metaprogramming & Concurrency cổ điển (Ngày 51–60)

Khi tới Ngày 51 hãy tự đặt câu hỏi đối chiếu: "chỗ này nên dùng Thread hay có thể thay bằng Coroutine?" ở mỗi Lab.

### NGÀY 51: Quản lý luồng (Threads) & dữ liệu chia sẻ

*Mục tiêu: hiểu cách tạo luồng và rủi ro khi nhiều luồng chạm vào một vùng nhớ.*

*   **Lớp** `std::thread`**:** Vòng đời `join()` vs `detach()` - luồng "bơ vơ" gây sập chương trình. Truyền tham số - cẩn thận dangling reference. `std::jthread` (C++20) - tự join, dừng an toàn.
    
*   **Race conditions:** Data race - ít nhất 1 luồng ghi trong khi luồng khác đọc/ghi. `std::mutex`/`recursive_mutex` tạo critical section. RAII cho mutex: `lock_guard`, `unique_lock`, `scoped_lock` (C++17).
    
*   **Lab:** Tăng biến đếm 1 triệu lần bằng 4 luồng không mutex → quan sát sai; dùng mutex sửa.
    

### NGÀY 52: Đồng bộ hóa luồng & Deadlocks

*   **Deadlocks:** Chiếm nhiều mutex sai thứ tự gây treo. `std::lock` khóa nhiều mutex cùng lúc tránh deadlock.
    
*   **Condition variables:** `std::condition_variable` - luồng "ngủ" chờ tín hiệu. Spurious wakeups - luôn dùng `while` khi chờ. Producer-consumer - hàng đợi an toàn đa luồng.
    
*   **Lab:** Lock granularity - cân bằng giữa hiệu năng và đúng dữ liệu.
    

### NGÀY 53: Lập trình bất đối xứng (async, future, promise)

*   `std::async`**/**`future`**:** Tiện hơn `thread` trong nhiều trường hợp. `launch::async` vs `launch::deferred`.
    
*   `std::promise`**/**`packaged_task`**:** "Hứa" trả giá trị, gửi dữ liệu từ luồng con về chính. `shared_future` - nhiều luồng chờ 1 kết quả.
    
*   **Thực hành:** Tính ma trận lớn chia nhỏ thành task `async`.
    

### NGÀY 54: C++ Memory Model & Atomic Operations

*   `std::atomic`**:** Tại sao `atomic<int>` nhanh hơn `int`+`mutex`. `fetch_add`, `exchange`, `compare_exchange_weak/strong` (CAS).
    
*   **Memory ordering:** Instruction reordering. Memory barriers: `relaxed`, `acquire`, `release`, `seq_cst`. `seq_cst` an toàn nhất nhưng chậm nhất.
    
*   **Lab:** False sharing - biến atomic gần nhau trên cùng cache line làm giảm hiệu năng đa nhân.
    

### NGÀY 55: Lập trình không khóa (lock-free) & đa luồng

*   **Dự án "high-performance thread pool":** `ThreadPool` số luồng cố định; luồng chính đẩy task vào hàng đợi an toàn; worker threads tự lấy; `atomic<bool>` quản lý dừng Pool; thử thay mutex bằng spinlock tự viết bằng `atomic_flag`.
    
*   **Review:** "Khi nào lock-free thực sự lợi ích?" - cảnh báo cực khó debug nếu không phải chuyên gia.
    

**Chiến lược:** Đa luồng = "hỗn loạn có kiểm soát". Ưu tiên data parallelism (mỗi luồng làm việc trên vùng nhớ riêng).

### NGÀY 56: Alignment, Padding & Cache-Friendly

*   **Data alignment & padding:** Tại sao `double` (8 bytes) phải nằm địa chỉ chia hết 8. Struct padding - sắp xếp thành viên từ lớn đến nhỏ.
    
*   **Cache-friendly data structures:** AOS vs SOA. Cache line contention. Prefetching.
    
*   **Lab:** `alignas`/`alignof`. Class `Matrix` - đo chênh lệch row-major vs column-major.
    

### NGÀY 57: Expression Templates

*   **Vấn đề nạp chồng toán tử thông thường:** `A+B+C+D` tạo 3 object tạm + 3 loop dư thừa. Chi phí băng thông bộ nhớ.
    
*   **Kỹ thuật:** Lớp Proxy (`VecPlusVec`) trì hoãn tính toán. Lazy evaluation - chỉ tính khi gán vào biến thật. Kết quả: 1 loop duy nhất, hiệu năng ngang C thô.
    
*   **Thực hành:** Skeleton Expression Templates cho cộng vector lớn.
    

*(Ghi chú: đây chính là ý tưởng nền cho Ranges views lazy evaluation đã học ở Ngày 50.6 - nhưng Expression Templates áp dụng ở tầm phép toán số học, Ranges áp dụng ở tầm algorithm/container.)*

### NGÀY 58: Profiling & Debugging

*   **Memory profiling với Valgrind:** Memcheck (leak, use-after-free). Massif (Heap theo thời gian). Cachegrind (cache-miss).
    
*   **Performance profiling & GDB:** `perf`/Visual Studio Profiler tìm Hot spots. GDB Advanced - debug đa luồng, xem Assembly khi chạy.
    
*   **Lab:** Lấy bài tập cũ Giai đoạn 1, profiling, tối ưu tăng tốc ít nhất 2 lần.
    

**Phụ lục - sanitizer song song:** Chạy Lab này song song ASan/UBSan (Ngày 0) với Valgrind/GDB, tự so sánh 2 bộ công cụ trên cùng lỗi.

**Chiến lược:** "Đừng tối ưu hóa khi chưa đo đạc." 80% runtime nằm ở 20% code (loop sâu nhất).

### NGÀY 59-60: Capstone Project - High-Performance Order Book

**1\. Yêu cầu hệ thống:** Quản lý bids/asks; limit order; khớp lệnh tự động; ≥1.000.000 lệnh/giây; không leak, không race condition.

**2\. Kiến trúc kỹ thuật:**

*   Memory pool: Placement New hoặc mảng tĩnh, tránh `new/delete` liên tục.
    
*   Data structures: `map<Price, list<Order>>` hoặc `flat_map` (tối ưu cache); `unordered_map` tra `OrderID`.
    
*   RAII & smart pointers: `unique_ptr` quản lý vòng đời `Order`.
    
*   Move semantics: khi khớp lệnh, move vào trade history thay copy.
    
*   Concurrency: luồng nhận lệnh và khớp lệnh song song (`atomic` + `mutex` tối ưu).
    

**Hướng dẫn chi tiết:**

*   Bước 1: `struct Order` (ID, Price, Quantity, Side) - data alignment (enum char cạnh Quantity). `OrderBook` dùng `unique_ptr`.
    
*   Bước 2: Matching engine - RAII tự dọn lệnh khớp hết; `lower_bound` tìm giá khớp nhanh; `constexpr` cho hằng số phí giao dịch.
    
*   Bước 3: `thread` sinh lệnh giả lập hàng triệu lệnh; lock-free queue (hoặc mutex scope nhỏ nhất); Valgrind đảm bảo 0 bytes leak.
    
*   Bước 4: Đo thời gian xử lý trung bình/lệnh; expression templates nếu có tính khối lượng phức tạp; kiểm tra cache miss - chuyển `list`→buffer liên tục nếu cần.
    

**CHECKLIST:** Move semantics khi chuyển lệnh; không copy dữ liệu thừa; không con trỏ thô quản lý `new`; dữ liệu liên tiếp trong bộ nhớ; Exception safety khi hết bộ nhớ.

**Lời khuyên:** Đọc thêm mã nguồn Boost/LLVM sau dự án này.

# PHẦN 2: 20 NGÀY - CẤU TRÚC DỮ LIỆU & GIẢI THUẬT

## Giai đoạn 1: Độ phức tạp & cấu trúc dữ liệu tuyến tính

### Ngày 1: Phân tích thuật toán & độ phức tạp (Big O)

*   **Tại sao cần Big O:** đo bằng giây vs số bước. Quy tắc cộng/nhân/hằng số (O(2n)=O(n)). Phân loại: O(1), O(log n), O(n), O(n log n), O(n²), O(2ⁿ), O(n!).
    
*   **Memory & Hidden Constants:** Space complexity (đệ quy tốn stack memory). Hidden constants - tại sao O(n) đôi khi chậm hơn O(n²) với data nhỏ. Cache locality: mảng luôn nhanh hơn linked list dù cùng O(n).
    
*   **Thực hành:** `<chrono>` đo tìm max 1 vòng lặp vs 2 vòng lặp; n=10.000 vs 100.000.
    
*   **Thử thách:** Tổng 1→n bằng công thức toán vs vòng lặp khi n=1 tỷ.
    

**Chiến lược:** "Nếu data tăng 10 lần, thời gian tăng bao nhiêu lần?" → 10x=O(n); 100x=O(n²); không tăng=O(1).

### Ngày 2: Danh sách liên kết đơn (SLL)

*   **Cấu trúc & vận hành:** Node (data + next). So với mảng: SLL cấp phát phân tán, chèn/xóa đầu cực nhanh.
    
*   **Cài đặt thủ công:** Insertion (push front O(1), push back O(n), chèn sau node). Deletion (đầu, cuối - cần node áp chót, theo giá trị X). Quản lý bộ nhớ `new`/`delete`.
    
*   **Optimization:** RAII với `unique_ptr` cho `next` - tự động giải phóng chuỗi. Con trỏ `Tail` biến push\_back O(n)→O(1). Memory locality: SLL gây nhiều cache miss hơn mảng.
    

**BÀI TẬP:** SinglyLinkedList (insertHead/Tail, deleteValue, printList, destructor); `reverseList()` 1 lần duyệt O(1) không gian; chuyển sang `unique_ptr` (dùng `std::move()`).

**Câu hỏi:** 1 triệu Node, xóa đệ quy bằng `unique_ptr` → chuyện gì với stack? **Thử thách:** Skeleton code mẫu `unique_ptr`.

### Ngày 3: Danh sách liên kết đôi & vòng

*   **DLL:** Node (data, next, prev). Duyệt ngược. Xóa nhanh khi biết địa chỉ. Insert/delete (Head/Tail/After/Before) - 4 liên kết cần cập nhật (dễ bug nhất).
    
*   **Circular linked list:** Node cuối trỏ đầu. Ứng dụng: round robin OS, playlist lặp. Kỹ thuật dừng vòng lặp bằng con trỏ head.
    
*   **Optimization - pointer chasing:** Vector/array cache hit (liên tiếp); linked list cache miss (rải rác). So sánh 10-50x chậm hơn giữa `list` và `vector` khi duyệt 1 triệu phần tử.
    

**BÀI TẬP:** DLL với smart pointers (`unique_ptr` cho next, raw/`weak_ptr` cho prev - tránh circular reference); Bài toán Josephus (circular list); Benchmark cache vector vs list.

**Chiến lược:** "Vẽ trước, code sau." **Câu hỏi:** Tại sao `std::list` dùng Node Sentinel? **Thử thách:** Giải quyết "sở hữu vòng" với smart pointers trong DLL.

### Ngày 4: Ngăn xếp (Stack) & Hàng đợi (Queue)

*   **Stack (LIFO):** Array-based (biến `top`, cache locality tốt, giới hạn size trừ dùng `vector`). Linked-based (insertHead/deleteHead SLL). Ứng dụng: Undo/Redo, Call Stack.
    
*   **Queue (FIFO):** Vấn đề mảng tuyến tính - lấy đầu phải dịch chuyển O(n). Linked-based: insertTail/deleteHead. Ứng dụng: print queue, BFS.
    
*   **Optimization:** Ring buffer (circular queue) - mảng vòng bằng `%`, 2 con trỏ front/rear, Dequeue O(1). Prefix/Infix/Postfix bằng Stack. Khử đệ quy bằng Stack tự tạo tránh Stack Overflow.
    

**BÀI TẬP:** CircularQueue mảng tĩnh (xử lý đầy/rỗng chính xác); Kiểm tra dấu ngoặc hợp lệ bằng Stack; Postfix Evaluation.

**Chiến lược:** Tư duy "chi phí dịch chuyển" - mọi thao tác thêm/xóa phải O(1). **Câu hỏi:** Tại sao Embedded ưa Ring Buffer hơn Linked List cho Queue?

### Ngày 5: Review & Lab 1

*   **Stack & Queue:** Undo/Redo (2 ngăn xếp). Print Buffer (FIFO, sơ lược Priority Queue).
    
*   **Valgrind:** Cách chạy trên Linux/WSL. "Definitely lost" vs "indirectly lost". Fix leaks Ngày 2-3.
    
*   **Lab 1:** Reverse Queue chỉ bằng Stack hỗ trợ; kiểm tra Palindrome (Stack+Queue).
    

**BÀI TẬP:** Trình soạn thảo mini Undo/Redo (2 stack); Hàng đợi ATM; Tấn công Memory Leak (bỏ destructor SLL, chạy Valgrind, sửa, chạy lại).

**Câu hỏi:** Tại sao `unique_ptr` Linked List đôi khi vẫn cần destructor thủ công xóa bằng `while` thay đệ quy? (Stack Overflow, Ngày 2).

## Giai đoạn 2: Thuật toán sắp xếp & tìm kiếm

### Ngày 6: Tìm kiếm & Sắp xếp cơ bản

*   **Linear Search:** O(n). Sentinel Linear Search tăng 10-15%. **Binary Search:** cần mảng sort. Divide and Conquer O(log n). Lower/upper bound. `mid = left+(right-left)/2` tránh overflow.
    
*   **3 thuật toán kinh điển:** Bubble Sort (biến `swapped` → best case O(n)). Selection Sort (ít swap nhất). Insertion Sort (nhanh nhất khi n<20 hoặc gần sorted - QuickSort/MergeSort chuyển sang nó ở giai đoạn cuối).
    
*   **Phân tích:** Best/Average/Worst case. Stability (Insertion ổn định, Selection không). In-place O(1) phụ.
    

**BÀI TẬP:** Binary Search trả về vị trí đầu tiên khi trùng; Insertion Sort kiểu "Shifting" giảm 1/3 phép gán; Sort trên SLL.

**Câu hỏi:** Tại sao `std::sort` không dùng Bubble/Selection ngay cả mảng nhỏ mà dùng Introsort (Quick+Heap+Insertion)?

### Ngày 7: Sắp xếp nâng cao (Divide and Conquer)

*   **Merge Sort:** Divide/Conquer/Combine. O(n log n) mọi trường hợp. O(n) không gian phụ. Ổn định, tốt cho External Sorting.
    
*   **Quick Sort:** Partitioning (Pivot). Trung bình O(n log n), xấu nhất O(n²) (Pivot sai). O(log n) không gian (Stack đệ quy). Nhanh hơn Merge Sort thực tế (cache-friendly).
    
*   **Optimization:** Random Pivot, Median-of-Three (triệt tiêu worst case trên mảng gần sort). Tail Recursion Optimization. Hybrid Sort - mảng con <15 phần tử chuyển Insertion Sort (`std::sort` làm vậy).
    

**BÀI TẬP:** Merge Sort với `vector` phụ (giải phóng đúng RAII); Quick Sort Median-of-Three (test trên mảng sort tăng 100.000 phần tử - Pivot đầu sẽ treo); Benchmark Merge/Quick(đầu)/Quick(Median)/`std::sort` trên 1 triệu phần tử.

**Câu hỏi:** Tại sao Merge Sort ưu tiên cho Linked List dù cần O(n) phụ? Hệ thống tài chính độ trễ thấp ổn định - chọn Quick hay Merge?

### Ngày 8: Heap Sort & Priority Queue

*   **Binary Heap:** Complete Binary Tree. Max/Min-Heap. Heapify (Shift Up/Down). Array-based Heap: `2i+1`, `2i+2`, `(i-1)/2` - cache tốt hơn Node-based.
    
*   **Heap Sort:** Build-Max-Heap O(n) (chỉ heapify từ non-leaf ngược lên). Extract-Max lặp lại. O(n log n) thời gian, O(1) không gian.
    
*   **Priority Queue:** `insert`, `extractMax`, `increaseKey` O(log n). Ứng dụng: Dijkstra, CPU Scheduling, Huffman.
    

**BÀI TẬP:** Heapify iterative (không đệ quy); MyPriorityQueue template dùng `vector`; "K phần tử lớn nhất" trên data stream bằng Min-Heap size K.

**Câu hỏi:** Tại sao Build-Heap chỉ O(n) không phải O(n log n)? So Heap Sort vs Quick Sort (cùng O(1) phụ, Quick nhanh hơn thực tế vì gì)?

### Ngày 9: Các thuật toán sắp xếp đặc biệt

*   **Shell Sort:** Cải tiến Insertion (gap-sort). Dãy Shell (n/2...), Knuth (3^k-1)/2, Sedgewick. ~O(n^1.25) đến O(n log²n).
    
*   **Radix Sort:** Counting Sort (O(n+k)) làm tiền đề. Sắp theo từng chữ số (LSD), dùng Counting Sort ổn định mỗi bước. O(d×(n+b)) thời gian, O(n+b) không gian. Áp dụng cho số âm, string, số thực.
    
*   **So sánh thực tế:** Nearly sorted → Insertion/Shell "vua". Range nhỏ → Radix/Counting nghiền Quick/Merge. Strings → Radix theo ký tự cuối lên đầu.
    

**BÀI TẬP:** Shell Sort với gap sequence khác nhau; Radix Sort số nguyên 32-bit (kể cả số âm); Sắp tên sinh viên A-Z bằng Radix.

**Câu hỏi:** Radix O(n) lý thuyết - tại sao không thay hoàn toàn `std::sort`? Mảng 1 triệu phần tử chỉ 100 sai vị trí - chọn thuật toán nào?

### Ngày 10: Review & Lab 2

*   **Ma trận quyết định:** n<20→Insertion; lớn+ổn định→Merge; lớn+nhanh+ít bộ nhớ→Quick; real-time worst-case→Heap. Trùng lặp nhiều→cần 3-way partition. In-place vs Out-of-place.
    
*   **Tìm K lớn thứ K:** Min-Heap O(n log k) (data stream) vs Quick Select O(n) trung bình (mảng có sẵn, chỉ đệ quy 1 bên).
    
*   **Lab 2:** Benchmark 3 loại data (random/sorted/reverse) trên mọi thuật toán; ý tưởng External Sorting (1 tỷ số, 2GB RAM); Quick Select.
    

**BÀI TẬP:** Quick Select tự viết Partition Hoare (không dùng `std::sort`); Heap vs Quick Select tìm K=100 lớn nhất trên 1 triệu phần tử; Dutch National Flag (3-way partition) cho mảng trùng lặp nhiều.

**Câu hỏi:** Hệ thống túi khí ô tô - chọn thuật toán nào, tại sao không Quick Sort (worst-case)? Tại sao `std::sort` gọi là Introsort?

## Giai đoạn 3: Cây & Bảng băm

### Ngày 11: Cây nhị phân tìm kiếm (BST)

*   **Kiến trúc:** Mỗi nút ≤2 con. Trái<cha<phải. `unique_ptr<Node> left,right` (an toàn, không sở hữu vòng như DLL). Search O(log n) trung bình.
    
*   **Thêm/Xóa:** Insert vào lá. Delete: lá (trực tiếp), 1 con (nối lên), 2 con (In-order Successor/Predecessor). Worst case: input đã sort → BST suy biến O(n).
    
*   **Duyệt cây (DFS/BFS):** In-order (tăng dần - kiểm tra tính đúng BST), Pre-order (clone tree), Post-order (xóa/destructor, tính biểu thức). Level-order dùng Queue. Iterative traversal bằng Stack tự tạo tối ưu bộ nhớ.
    

**BÀI TẬP:** BST hoàn chỉnh (`unique_ptr`, Valgrind kiểm tra xóa gốc); Level-order traversal (`queue`); findMin/findMax/Height (so chiều cao 1000 random vs 1000 tăng dần).

**Câu hỏi:** Tại sao ưu tiên In-order Successor khi xóa nút 2 con? Cây quá sâu (100.000 nút sợi dây) → destructor mặc định gây Stack Overflow, xử lý sao (Post-order iterative)?

### Ngày 12: Cây cân bằng AVL

*   **Balance Factor:** `BF = height(left)-height(right)`. Mất cân bằng nếu |BF|>1. Lưu `height` trong Node (O(1) thay tính lại O(n)).
    
*   **Rotations:** LL→Right Rotate. RR→Left Rotate. LR→xoay trái con trái rồi xoay phải gốc. RL→ngược lại. Tích hợp `balance()` sau insert/remove.
    
*   **Optimization:** AVL cân bằng chặt hơn Red-Black → đọc nhanh hơn, ghi (xoay nhiều hơn) chậm hơn. `char height` tiết kiệm bộ nhớ nếu cây lớn. 10.000 tăng dần: BST cao 10.000 tầng, AVL cao ~14 tầng.
    

**BÀI TẬP:** `rightRotate`/`leftRotate` (cập nhật height ngay trong hàm); AVL hoàn thiện với `unique_ptr` (remove khó - kiểm tra cân bằng ngược lên gốc); So sánh tìm kiếm AVL 1 triệu phần tử vs Binary Search trên `vector` sorted.

**Câu hỏi:** BF=2 - bao nhiêu khả năng, chọn xoay đơn/kép dựa điều kiện gì? Tại sao Big Data trên đĩa chuyển sang B-Tree thay AVL?

### Ngày 13: Bảng băm (Hash Table)

*   **Hash Function:** Nhanh, phân phối đều, deterministic. Division method (`key%size`), Multiplication method, Polynomial Rolling Hash (string). Table size nên là số nguyên tố.
    
*   **Collision Resolution:** Chaining (list/vector mỗi ô - dễ cài, tốn con trỏ, không cache-friendly). Open Addressing: Linear Probing (dễ Clustering), Quadratic Probing, Double Hashing (tránh Clustering tốt nhất).
    
*   **Load Factor & Rehash:** `alpha=n/m`, ngưỡng 0.7-0.75. Rehash phải duyệt lại toàn bộ (không `memcpy` được vì `key%size_cu`≠`key%size_moi`). `reserve()` tránh rehash nhiều lần.
    

**BÀI TẬP:** MyHashTable Chaining (Polynomial Rolling Hash string, O(1) trung bình); Linear Probing với Delete dùng "Tombstone"; Benchmark `map`/`unordered_map`/MyHashTable với 100.000 string.

**Câu hỏi:** Tại sao hệ thống bảo mật cao dùng Cryptographic Hash (SHA-256) + Salt thay hash đơn giản? Worst case mọi khóa băm cùng vị trí - độ phức tạp bao nhiêu, chống "Hash Flooding" thế nào (Chaining→Balanced BST)?

### Ngày 14: Cây Đỏ-Đen & B-Tree

*   **Red-Black Tree:** 5 quy tắc (mỗi nút đỏ/đen; gốc đen; lá NIL đen; đỏ không liền đỏ; số nút đen mọi đường bằng nhau). Rebalancing: Recoloring (nhanh, không xoay) hoặc Rotation (ít hơn AVL). AVL cân bằng hơn (đọc nhanh hơn chút); Red-Black ít xoay hơn (tốt cho data thay đổi liên tục) - `map`/`set` C++ dùng Red-Black.
    
*   **B-Tree:** Đa nhánh (m-way), cân bằng hoàn hảo, nút vừa khít Disk Block (4KB) - tối ưu Disk I/O. Splitting/Merging nút. SQL/MySQL/NTFS dùng B-Tree/B+.
    
*   **Thực hành:** `map::lower_bound`/`upper_bound`. B-Tree bậc 3 (2-3 Tree). B+ Tree - lá chứa data, nội bộ chỉ khóa điều hướng.
    

**BÀI TẬP:** `map<int,string>` MSSV + `lower_bound` range query, so tốc độ với `unordered_map` (phải duyệt toàn bộ); Vẽ tay chèn Red-Black (10,20,30,15,25); Benchmark truy cập ngẫu nhiên 1 triệu phần tử `map` (Cache Line/Fragmentation).

**Câu hỏi:** Red-Black chiều cao 2log(n+1) vs AVL 1.44log(n+2) - sao vẫn chọn Red-Black cho STL? Bậc B-Tree lớn vô hạn - tại sao không? (chi phí tìm trong 1 nút).

### Ngày 15: Review & Lab

*   **Review:** BST/AVL/Red-Black O(log n) có thứ tự vs Hash Table O(1) không thứ tự (load factor, rehash cost). Vector+Binary Search vs Linked-based Tree - Cache Miss khi duyệt cây.
    
*   **Lab 3 "Dictionary Engine":** 100.000 từ vựng. Version A (`map`) vs B (`unordered_map`). Tìm chính xác, Range Query (A), Auto-complete (tiền tố).
    
*   **Stress Test:** 1 triệu query random, `<chrono>` đo trung bình; phân tích bộ nhớ mỗi cấu trúc.
    

**BÀI TẬP:** Dictionary hoàn thiện (words.txt ~300.000 từ); Hash băm cực tệ cố tình (ASCII ký tự đầu) → quan sát sụp đổ; Phân tích B-Tree/External Hashing cho từ điển 10 triệu từ.

**Câu hỏi:** Cấu trúc nào (Map/Hash) dễ mở rộng Fuzzy Search? Nạp `map` từ file đã sort A-Z ảnh hưởng tốc độ ra sao, AVL/Red-Black giải quyết thế nào?

## Giai đoạn 4: Đồ thị & Tối ưu hóa

### Ngày 16: Đồ thị cơ bản (Graphs)

*   **Thuật ngữ:** Vertex/Edge. Directed/Undirected. Weighted/Unweighted. Degree, Cycle, Connected.
    
*   **Biểu diễn:** Adjacency Matrix (O(1) check nối, O(V²) bộ nhớ - tệ cho đồ thị thưa). Adjacency List (`vector<int> adj[V]`, O(V+E) bộ nhớ, check nối O(bậc)).
    
*   **BFS/DFS:** BFS dùng Queue ("loang" từng lớp - đường ngắn nhất không trọng số). DFS dùng Stack/đệ quy (đi sâu trước - liên thông, chu trình, mê cung). Mảng `visited[]` tránh vòng vô hạn. Cả hai O(V+E) với Adjacency List.
    

**BÀI TẬP:** Chuyển Matrix↔List (khi nào lãng phí); BFS tìm số chặng ít nhất A→B; DFS đếm thành phần liên thông (nhóm mạng xã hội).

**Câu hỏi:** Đồ thị hàng tỷ đỉnh (Web Graph) - Matrix còn khả thi? Dùng Priority Queue thay Queue trong BFS thì sao? (tiền đề Dijkstra).

### Ngày 17: Cây bao trùm tối thiểu (MST)

*   **Spanning Tree:** Chứa mọi đỉnh, liên thông không chu trình, V-1 cạnh.
    
*   **Kruskal (theo cạnh):** Greedy - sort cạnh tăng dần, nhận nếu không tạo chu trình, đủ V-1 cạnh dừng. **DSU:** Path Compression + Union by Rank → gần O(1).
    
*   **Prim (theo đỉnh):** Từ 1 đỉnh, luôn chọn cạnh ngắn nhất nối cây→ngoài cây. Priority Queue (Min-Heap) lấy cạnh nhỏ nhất O(log E). O(E log V).
    
*   **So sánh:** Kruskal tốt đồ thị thưa; Prim tốt đồ thị dày. Ứng dụng: mạng điện, LAN/WAN, Clustering ML.
    

**BÀI TẬP:** DisjointSet với Path Compression; Mạng lưới điện (đồ thị đầy đủ, dùng Prim); So sánh Kruskal/Prim trên 10.000 đỉnh/50.000 cạnh.

**Câu hỏi:** Tại sao Kruskal cần sort cạnh còn Prim không? MST có duy nhất nếu trọng số bằng nhau/khác nhau? Đồ thị không liên thông thì sao (MST Forest)?

### Ngày 18: Đường đi ngắn nhất (Shortest Path)

*   **Dijkstra:** Single Source Shortest Path, trọng số **không âm**. Priority Queue chọn đỉnh gần nhất tạm thời. O((E+V)log V).
    
*   **Bellman-Ford:** Khi có trọng số âm. "Relax" toàn bộ E cạnh trong V-1 lần. Phát hiện Negative Cycle.
    
*   **Lab:** Dijkstra bằng `priority_queue`, tìm đường ngắn nhất bản đồ thành phố.
    

**Thử thách:** Tại sao Dijkstra thất bại hoàn toàn nếu có dù 1 cạnh trọng số âm?

### Ngày 19: Quy hoạch động (DP) cơ bản

*   **2 tính chất DP:** Overlapping Subproblems, Optimal Substructure. Top-down (Memoization) vs Bottom-up (Tabulation). Nhập môn: Fibonacci, Climbing Stairs.
    
*   **Bài toán kinh điển:** 0/1 Knapsack (`dp[i][w]`). LCS (so `s1[i]`/`s2[j]`).
    
*   **Biến thể:** LIS, Coin Change. **Lab:** Knapsack Top-down+Bottom-up, so sánh Space Complexity mảng 2D vs 1D.
    

**BÀI TẬP:** Knapsack thực tế (túi 50kg, 3 món); Edit Distance (kitten→sitting - nền tảng spell check); Tối ưu Fibonacci về O(1) không gian (3 biến a,b,c).

**Câu hỏi:** Tại sao thi đấu ưu tiên Tabulation hơn Memoization (Stack Overflow, hằng số thời gian)? Phân biệt Greedy vs DP (Knapsack phân số vs 0/1)?

### Ngày 20: Tổng kết & Capstone Lab - City Navigator Engine

*   **Yêu cầu:** File data hàng ngàn thành phố+khoảng cách. `unordered_map<string,int>` ánh xạ tên→ID. Adjacency List. Dijkstra tìm đường ngắn nhất 2 thành phố.
    
*   **Final Optimization:** `-O3 -march=native`. `gprof`/`Valgrind --tool=callgrind` tìm bottleneck. Đổi `list`→`vector` (cache locality); `reserve()`; `const&` thay copy.
    
*   **Ma trận giải thuật tổng hợp:** Tìm kiếm nhanh→Hash; Range→AVL/BST; Ưu tiên→Heap; Đường ngắn nhất→Dijkstra/BFS; Tối ưu tài nguyên→DP.
    

**NHIỆM VỤ:** `CityGraph` (unordered\_map + vector + vector<vector<pair<int,int>>>); Benchmark có/không `-O3 -march=native`, thử hash tự viết (Ngày 13); Tóm tắt complexity toàn hệ thống (O(V+E) nạp, O(E log V) truy vấn).

**Tổng kết 20 ngày:** Từ con trỏ/mảng đến AVL/Đồ thị/DP + tối ưu hóa phần cứng. Luôn tự hỏi: Data có thứ tự? Ưu tiên tìm hay ghi? Bộ nhớ có giới hạn?

# PHẦN 3: 33 NGÀY - CLEAN CODE, OOP, SOLID, DESIGN PATTERNS

## Giai đoạn 1: Clean Code

### Ngày 1: Ý nghĩa của Mã sạch & Đặt tên (Meaningful Names)

*   **Tư duy Clean Code:** Chi phí bảo trì tỷ lệ độ "bẩn" code. "Viết code cho người sau đọc, không phải máy chạy."
    
*   **Quy tắc 1-3:** Đặt tên có ý nghĩa (`elapsedTimeInDays` thay `int d`). Tránh gây nhiễu (`accountList` chỉ dùng nếu thực sự là `list`). Phân biệt rõ ràng (tránh `a1,a2,aN`, tránh noise word `Info`/`Data`).
    
*   **Quy tắc 4-6:** Phát âm & tìm kiếm được (`generationTimestamp` thay `genymdhms`). Danh từ cho Class (`Customer`, tránh `Manager`/`Processor`), động từ cho Method (`postPayment()`). Một từ cho một khái niệm (không lẫn `fetch`/`retrieve`/`get`).
    
*   **Best Practices:** Tránh Hungarian notation. Ngữ cảnh rõ ràng (gom `state,city,zipcode` vào struct `Address`).
    

**BÀI TẬP:** Sửa lỗi tên trong class `Manager{int d; vector<string> list; void f();}`; Thiết kế Interface Ngân hàng (chuyển tiền/kiểm tra số dư/lịch sử); Đọc chương 1-2 Clean Code.

**Câu hỏi:** Tại sao tên dài rõ nghĩa tốt hơn tên ngắn? Khi nào biến 1 ký tự được chấp nhận?

### Ngày 2: Hàm (Functions) & Quy tắc nhỏ gọn

*   **Kích thước:** Hàm không quá 20 dòng. "Do One Thing" - 1 cấp độ trừu tượng/hàm. Step-down Rule (đọc như bài báo).
    
*   **Tham số:** 0 (lý tưởng) → 1 → 2 (chấp nhận) → 3+ (đóng gói struct/class). Flag Arguments là "tội ác" - tách 2 hàm. Side Effects ngầm là nguồn bug khó tìm.
    
*   **CQS & DRY:** Command Query Separation - hàm chỉ Command hoặc Query, không cả hai. Extract Method loại trùng lặp.
    

**BÀI TẬP:** Sửa `saveUser(User,bool,bool)` (vi phạm nhiều nguyên tắc); Đóng gói tham số `makeCircle` thành struct; Đọc chương 3, tóm tắt "one level of abstraction".

**Câu hỏi:** Tách hàm lớn thành nhỏ có chậm đi do function call overhead? (nghĩ `inline`). Đặt tên hàm nhỏ sau khi tách sao cho mạch lạc?

### Ngày 3: Chú thích (Comments) & Định dạng (Formatting)

*   **Triết lý Comment:** Là "thừa nhận thất bại" diễn đạt bằng code. Tốt: legal, informative (thuật toán phức tạp), warning of consequences, TODO. Xấu: mumbling, redundant, position markers, **commented-out code** (ô nhiễm nhất - Git giữ lại rồi, xóa đi).
    
*   **Vertical Formatting:** "Newspaper Metaphor" - tổng quát trên, chi tiết dưới. Vertical Openness (dòng trống phân tách ý niệm) vs Density (liên quan chặt nên sát nhau). Biến khai báo gần nơi dùng.
    
*   **Horizontal Formatting:** 80-120 ký tự/dòng. Khoảng trắng quanh toán tử. Không nên căn lề cột biến. Thụt lề luôn dùng dù 1 dòng.
    

**BÀI TẬP:** Thay comment bằng code sạch (trích xuất `isEligibleForReward`); Dọn code rác (xóa comment-out, format Vertical Openness); Thiết lập `.clang-format` (Google/LLVM style).

**Câu hỏi:** Thuyết phục đồng nghiệp "code tự giải thích" tốt hơn Javadoc-style comment mọi hàm? Tại sao khai báo biến ngay trước khi dùng tốt hơn khai báo đầu hàm (C cũ)?

### Ngày 4: Xử lý lỗi (Error Handling) & Boundaries

*   **Return codes vs Exceptions:** `if(status==ERROR)` làm bẩn code, đứt mạch logic chính. Exception tách biệt success/failure logic. Try như "transaction". Catch cụ thể, tránh `catch(...)`.
    
*   **Kỹ thuật C++:** Custom exceptions kế thừa `std::exception`, chứa "điều gì xảy ra" + "ở đâu". Special Case Pattern - trả object rỗng thay throw nếu là logic nghiệp vụ thông thường. Không trả/truyền `nullptr`.
    
*   **Boundaries:** Adapter Pattern bọc thư viện bên thứ ba - nếu thư viện đổi, chỉ sửa 1 chỗ. Learning Tests cho API chưa quen.
    

**BÀI TẬP:** Refactor return codes→exceptions; Wrapper class cho thư viện logging giả định; Đọc chương 7-8, ghi chú Special Case Pattern.

**Câu hỏi:** Exception đắt hơn `int` - tại sao Clean Code vẫn khuyên dùng? `shared_ptr` thay NULL đã là cách xử lý lỗi tốt nhất chưa?

### Ngày 5: Unit Tests (TDD)

*   **3 Luật TDD:** Không viết production code trước khi có test fail; không viết test nhiều hơn cần để fail; không viết code nhiều hơn cần để pass. Red-Green-Refactor.
    
*   **Test sạch:** 1 Assert/test, 1 khái niệm/test. AAA (Arrange-Act-Assert).
    
*   **F.I.R.S.T:** Fast, Independent, Repeatable, Self-Validating, Timely.
    

**BÀI TẬP:** Cài Google Test, test `sum(a,b)`; TDD đúng luật cho FizzBuzz; Refactor test bẩn theo AAA+F.I.R.S.T.

**Câu hỏi:** Test tốn 30% thời gian - tại sao công ty lớn vẫn bắt buộc (chi phí sửa bug Prod vs Dev)? Test hàm phụ thuộc thời gian/random thế nào? (Mocking, DI).

## NGÀY 5.5: TESTING VỚI GOOGLE TEST

*Mục tiêu: chuyển từ TDD lý thuyết sang framework, dùng xuyên suốt các Lab OOP còn lại - điểm giao giữa "hiểu TDD" và "làm TDD thật mỗi ngày".*

#### Từ lý thuyết sang thực hành

Ngày 5 dạy 3 Luật và F.I.R.S.T dưới dạng khái niệm. Hôm nay biến thành công cụ gõ tay, không "giả lập" bằng comment hay `assert()` thô.

#### Cài đặt & tích hợp

*   Google Test đã cài qua vcpkg (Ngày 0) - tích hợp CMakeLists.txt: `enable_testing()`, `add_executable(tests ...)`, `target_link_libraries(tests GTest::gtest_main)`, `add_test(...)`.
    
*   `TEST(SuiteName, TestName){EXPECT_EQ(a,b);}` - nhắc "Một Assert/Test" và AAA (Ngày 5), giờ bằng cú pháp thật.
    
*   `TEST_F` (Fixture): nhiều test cần cùng setup/teardown - về bản chất là **RAII** (Ngày 22, Phần 1) áp dụng vào testing: constructor setup, destructor tự dọn.
    

#### Mocking - nối vào Interface & Dependency Injection

Sẽ học đầy đủ DIP ở Ngày 18, nhưng hôm nay giới thiệu trước: nếu lớp phụ thuộc `IDatabase` (Interface) thay vì `MySQLDatabase` cụ thể, có thể viết `MockDatabase` giả lập chỉ phục vụ test - không cần DB thật, giữ đúng F.I.R.S.T. Google Mock dùng macro `MOCK_METHOD`.

**LAB:**

1.  Viết lại FizzBuzz (Ngày 5) hoàn toàn bằng Google Test thật, đúng 3 Luật TDD.
    
2.  Chọn 1 Lab đã làm Ngày 1-4 (Phần 3), viết ≥3 test case bằng `TEST_F`.
    
3.  Định nghĩa Interface `IClock` (hàm `now()`), viết `MockClock` trả giờ cố định, test hàm phụ thuộc thời gian mà không cần chờ thời gian thực.
    

**Yêu cầu bắt buộc từ đây:** mọi Lab từ Ngày 6 (Phần 3) trở đi phải kèm ≥3 test case bằng Google Test.

**Câu hỏi:**

1.  Tại sao dùng Mock cho `IDatabase` thay test trực tiếp Database thật, xét F.I.R.S.T (Ngày 5)?
    
2.  `TEST_F` dùng constructor/destructor setup/cleanup - có phải ứng dụng RAII (Ngày 22)? Nếu test throw exception giữa đường, destructor Fixture còn chạy không?
    

### Ngày 6: Lớp (Classes) & Tổ chức hệ thống

*(Thuộc Giai đoạn 1: Clean Code - trọng tâm là tổ chức lớp ở tầm nguyên tắc thiết kế, khác với Ngày 9 chỉ nói cơ chế* `public/private/protected`*.)*

#### Tổ chức nội dung lớp (Class Organization)

*   **Thứ tự các thành phần:** Tại sao đặt biến hằng (`public static constants`) lên đầu? Thứ tự: Variables (Private → Protected) → Public Functions → Private Utilities. Quy tắc "Ẩn đi chi tiết" - hàm private hỗ trợ hàm public nên nằm ngay sau nó (đọc theo quy tắc tờ báo, Ngày 3).
    
*   **Kích thước lớp:** Quy tắc số 1 - Lớp phải NHỎ. Đếm trách nhiệm thay vì đếm dòng code. Một lớp không nên có quá nhiều "lý do để thay đổi".
    
*   **Single Responsibility Principle (SRP) - nhận diện qua tên:** Nếu tên lớp chứa `Manager`, `Processor`, `Super`, nó thường vi phạm SRP. *(Chỉ nhận diện ở đây; học đầy đủ ở cấp kiến trúc tại Ngày 16.)*
    

#### Sự gắn kết (Cohesion) - khác Encapsulation của Ngày 9

*   Một lớp có độ gắn kết cao là lớp mà **hầu hết hàm dùng hầu hết biến thành viên**. Khi gắn kết giảm - dấu hiệu nên tách lớp lớn thành nhiều lớp nhỏ hơn. *(Đây là góc nhìn "cấu trúc nội bộ 1 lớp", khác hẳn Ngày 9 nói về "ai được quyền truy cập gì".)*
    
*   Giới thiệu sơ lược Open-Closed Principle (mở rộng không cần sửa code cũ) - học đầy đủ Ngày 16.
    

#### Thực hành C++ & Refactoring

*   Constructor/Destructor sạch — tránh logic phức tạp trong Constructor.
    
*   Tách biệt dữ liệu và hành vi — khi nào dùng `struct` (DTO) và khi nào dùng `class`.
    

**BÀI TẬP:**

1.  Phân tích `class Employee{calculatePay(); saveToDatabase(); reportHours(); printPayStub();}` — liệt kê lý do vi phạm SRP (ai quan tâm mỗi hàm: Kế toán/DB Admin/Nhân sự?).
    
2.  Tách `class MultiTool{double x,y; string buffer; move(); appendText(); clearBuffer(); draw();}` thành 2 lớp tăng Cohesion.
    
3.  Đọc chương 10 Clean Code, ghi chú kỹ thuật "Tách lớp để hỗ trợ thay đổi" (ví dụ lớp `Sql`).
    

**LAB 6 "The Great Split":** Nhận 1 lớp "Vạn năng" (God Class) làm đủ thứ — tính toán, lưu file, in báo cáo. Chia thành các lớp nhỏ phối hợp với nhau.

**Câu hỏi:** Tách lớp lớn thành nhiều lớp nhỏ làm tăng số file — có làm hệ thống khó hiểu hơn không? Gọi qua nhiều lớp trung gian (Delegation) có làm chậm chương trình không?

### Ngày 7: Ôn tập

Ôn tập các kiến thức đã học từ Ngày 1–6 (Clean Code: Đặt tên, Hàm, Comment/Format, Error Handling, TDD/Testing thật, Tổ chức lớp).

*   Tự trả lời lại toàn bộ câu hỏi cuối ngày Ngày 1–6 mà không xem lại đáp án.
    
*   Không có Lab mới - đây là ngày củng cố trước khi bước hẳn vào OOP (Ngày 8).
    

## Giai đoạn 2: OOP nền tảng (Ngày 8–15)

### Ngày 8: Đối tượng & Lớp

Ôn nhanh: Stack (LIFO, tự hủy khi ra scope) vs Heap (`new`/`delete`, memory leak nếu quên). Con trỏ tới đối tượng: `p->show()` = `(*p).show()`. Con trỏ `this`. Member initializer list. Shallow vs Deep Copy - Copy Constructor tránh "Double Free".

### Ngày 9: Encapsulation & Access Specifiers

Ôn nhanh: `public`/`private`/`protected` - kiểm tra compile-time không phải runtime. "Tell, Don't Ask" - bảo đối tượng làm việc (`withdraw(amount)`) thay lấy dữ liệu ra tự tính. Setter là "người gác cổng" (validation). Const member functions.

### Ngày 10: Tính kế thừa (Inheritance) & Thành phần (Composition)

*   **Inheritance - "Is-a":** Tái sử dụng code qua Derived/Base class. `public`/`protected`/`private` inheritance. Chỉ kế thừa khi lớp con thực sự là biến thể lớp cha (`Car is-a Vehicle`). Vấn đề: Tight Coupling, Fragile Base Class Problem.
    
*   **Composition - "Has-a":** Tạo lớp phức tạp bằng cách chứa object khác làm thành viên (`Car has-a Engine`). Ưu tiên vì Loose Coupling (đổi `Engine` không ảnh hưởng `Car`) và linh hoạt runtime (kế thừa là tĩnh, composition đổi được lúc chạy).
    
*   **Đa kế thừa & Diamond Problem:** Lớp kế thừa 2 lớp cùng 1 lớp cha → conflict. Giải pháp: Virtual Inheritance.
    

**BÀI TẬP:** Phân tích `Stack` kế thừa `ArrayList` có hợp lý không (nên composition); Diamond Problem code + sửa bằng `virtual`; Đọc chương 9 (Joyce Farrell).

**LAB 10 "Robot Simulator":** Cách 1 (Inheritance) - `CombatRobot`/`WorkerRobot` kế thừa `Robot`, vấn đề khi cần `CombatWorkerRobot` (đa kế thừa phức tạp). Cách 2 (Composition, khuyên dùng) - `Robot` chứa `vector<Module>` (WeaponSystem, ToolSystem), thêm module bất kỳ lúc nào.

**Câu hỏi:** Kế thừa chỉ để tái sử dụng hàm nhưng không thực sự "is-a" - vi phạm nguyên tắc gì (Clean Code)? Khi nào dùng `protected` thay `private` cho lớp cha?

### Ngày 11: Polymorphism & Virtual Functions

*(****RÚT GỌN*** *— chủ đề này đã học đầy đủ và sâu ở Ngày 22-23, Phần 1: cơ chế* `virtual`*, Virtual destructor,* `override`*/*`final`*, và đặc biệt là V-Table/V-Ptr ở tầm Assembly. Ngày này chỉ ôn nhanh 15-20 phút để nối mạch trước khi sang Ngày 12, không làm lại Lab.)*

**Ôn nhanh:** `virtual` cần con trỏ/tham chiếu để kích hoạt (Dynamic Binding). Virtual destructor bắt buộc cho base class - thiếu gây leak khi `delete` qua con trỏ base trỏ tới object derived. `override` (ép compiler kiểm tra chữ ký, tránh lỗi ngớ ngẩn) / `final` (chặn kế thừa/ghi đè, cho phép devirtualization tăng tốc). Object Slicing - mất tính đa hình khi pass-by-value cho base class thay vì tham chiếu/con trỏ.

**Bài tập ôn (5 phút):** Tự trả lời không xem lại - Tại sao thiếu `virtual` destructor gây leak? Chi phí gọi hàm ảo đến từ đâu (V-Ptr → V-Table → Function Address)?

### Ngày 12: Lớp trừu tượng (Abstract Classes) & Interface

*   **Abstract Classes:** Pure virtual (`=0`). Không thể khởi tạo (`Animal a;` lỗi nếu trừu tượng). Vẫn cần Constructor (khởi tạo thuộc tính chung cho con).
    
*   **Interface trong C++:** Chỉ chứa pure virtual, không data member - "Hợp đồng". C++ không có từ khóa `interface`, dùng lớp thuần ảo. Đa kế thừa Interface là Best Practice (khác đa kế thừa lớp nguy hiểm) - 1 lớp đóng nhiều "vai" (`SmartPhone` là `ICamera`+`IPhone`+`IGpsDevice`).
    
*   **"Program to an Interface":** Decoupling - Client không cần biết Server cụ thể, chỉ cần biết Interface. Dễ thay phụ thuộc (`SqlDatabase`→`MongoDatabase`). Quy ước tiền tố `I` (`IShape`, `ILogger`).
    

**BÀI TẬP:** Phân loại `LivingThing/Bird/Eagle/Flyable/Swimmable/Penguin` (concrete/abstract/interface); Cài `IShape`+`IDrawable` cho `Circle`; Đọc chương 10 cuối (Joyce Farrell).

**LAB 12 "Notification System":** `IMessageService` (pure virtual `sendMessage`); 3 lớp thực thi (Email/Sms/PushNotification); `UserAlert` chứa con trỏ `IMessageService`, hoàn toàn không quan tâm loại service cụ thể.

**Câu hỏi:** Tại sao ưu tiên Interface hơn kế thừa Concrete Base Class (linh hoạt, tránh Fragile Base Class)? Pure virtual function có thể có thân hàm không, để làm gì?

### Ngày 13: Operator Overloading

*   **Toán tử số học:** Tại sao `complex1+complex2` tốt hơn `.add()`. Không nạp chồng được: `.`, `::`, `?:`, `sizeof`. Trả về giá trị (không tham chiếu) cho phép tạo kết quả mới.
    
*   **So sánh/Nhập-xuất/Gán:** So sánh trả `bool`; nạp `<` nên nạp cả `==`. `<<`/`>>` **bắt buộc** friend function (đối tượng trái là `ostream`, không phải class của bạn). Gán: kiểm tra self-assignment (`this==&other`). Tăng/giảm: phân biệt prefix/postfix bằng tham số `int` giả.
    
*   **Best Practices:** Nhất quán (không nạp `+` để trừ); nạp `+` thì nạp cả `+=`. Sơ lược R-value ref & Move Assignment (tiền đề Ngày 25).
    

**BÀI TẬP:** Chỉ lỗi logic toán tử `+` dùng nhân sai; `Student` nạp `<` để `std::sort` theo GPA; `Point2D` nạp `<<`/`>>` định dạng `(x,y)`.

**LAB 13 "Fraction Calculator":** `+,-,*,/` trả phân số tối giản; `==,!=`; `<<,>>`; hàm `private gcd()`.

**Câu hỏi:** Tại sao truyền `const ClassName&` thay giá trị trực tiếp cho toán tử? Nạp `[]` nên trả về gì để dùng được `myObj[0]=10`?

### Ngày 14: Friend Functions & Friend Classes

*   **Khái niệm:** Hàm/lớp không phải thành viên nhưng truy cập được `private`/`protected`. Đặc điểm: không bắc cầu, không hai chiều, không kế thừa.
    
*   **Khi nào dùng:** (1) Nạp `<<`/`>>` (phổ biến nhất, Ngày 13). (2) Tối ưu hiệu năng - truy cập trực tiếp thay chuỗi Getter/Setter (ma trận, đồ họa). (3) Bridge Pattern giữa 2 lớp liên quan chặt (`Matrix`×`Vector`).
    
*   **Bảo mật:** Chỉ dùng khi làm Interface tự nhiên hơn hoặc hiệu năng sống còn. Friend Member Function - chỉ 1 hàm cụ thể làm bạn, không cả lớp.
    

**BÀI TẬP:** So sánh hiệu năng in mảng 1 triệu phần tử qua Getter 1 triệu lần vs friend function; `Bank`+`Auditor` - chỉ 1 hàm cụ thể được friend; Đọc chương 10 Clean Code, liên hệ friend với SRP.

**LAB 14 "Matrix-Vector Multiplier":** `friend Vector multiply(const Matrix&, const Vector&)` truy cập trực tiếp `m.data`/`v.values`, không dùng Getter nào.

**Câu hỏi:** Tại sao `friend` có thể **tăng** đóng gói trong vài trường hợp (thay vì giảm)? Lớp có quá nhiều "bạn" là dấu hiệu vấn đề gì (Cohesion/Coupling)?

### Ngày 15: Templates & Generic Programming

Ôn nhanh: Function template (Template Argument Deduction). Class template (`Stack<T>`). Specialization cho kiểu cụ thể. Non-type parameters (`array<T,N>`). Code Bloat - mỗi kiểu mới sinh mã mới.

## Giai đoạn 3: SOLID & Design Patterns

### Ngày 16: SOLID - S (Single Responsibility) & O (Open/Closed)

*   **SRP (cấp kiến trúc):** "Một lớp chỉ nên có một lý do để thay đổi." Actor analysis - ai yêu cầu thay đổi. Dấu hiệu vi phạm: God Class, quá nhiều dependency. Facade/Proxy Pattern để tách nhóm trách nhiệm.
    
*   **OCP:** "Mở cho mở rộng, đóng cho sửa đổi." Abstraction giải quyết. Thay `if-else`/`switch` bằng Interface `DiscountStrategy` - thêm khách hàng mới chỉ tạo class mới.
    
*   **Liên hệ S↔O:** Không làm tốt SRP thì không đạt được OCP.
    

**BÀI TẬP:** Phân tích Actor cho `Book` (getTitle/printToConsole/saveToDatabase); Refactor `calculateArea(vector<Circle>)` dùng Interface `Shape` khi thêm `Square`; Đọc mục G5/G6 (Duplication, Wrong Abstraction Level).

**LAB 16 "Smart Tax Calculator":** Sai (if-else theo country) vs Đúng (`ITaxStrategy`→`VietnamTax`/`USTax`/`EuropeTax`, `TaxService` nhận qua DI). Thêm `LuxuryTax` - kiểm chứng không sửa `TaxService`.

**Câu hỏi:** OCP triệt để tăng số lớp - cân bằng "sạch, mở rộng" và "đơn giản" thế nào? `Customer` có Name/Address/Email có vi phạm SRP? (Cohesion).

### Ngày 17: SOLID - L (Liskov Substitution) & I (Interface Segregation)

*   **LSP:** "Object lớp cha thay được bằng lớp con mà không đổi tính đúng đắn." Kế thừa = chia sẻ **hành vi**. Vi phạm: con throw exception cho hàm cha xử lý bình thường, hàm rỗng "không dùng đến", `dynamic_cast` kiểm tra kiểu trước gọi. Ví dụ kinh điển: `Square` kế thừa `Rectangle` phá vỡ logic.
    
*   **ISP:** "Không ép Client phụ thuộc method không dùng." Fat Interfaces buộc implement hàm vô nghĩa. Giải pháp: chia Interface lớn thành nhỏ chuyên biệt, kế thừa nhiều Interface nhỏ.
    

**BÀI TẬP:** Phân tích `Penguin::fly() throw` vi phạm LSP; Tách `IMultiFunctionDevice` thành 3 Interface độc lập; Đọc mục G11/G32 (Inconsistency, Feature Envy).

**LAB 17 "Worker Management":** Sai (`IWorker` có work/eat/sleep - `RobotWorker` không ăn/ngủ) vs Đúng (`IWorkable`/`IEatable`/`ISleepable` tách riêng). Kiểm chứng LSP: `manageWork(IWorkable*)` chạy đúng cả Human và Robot.

**Câu hỏi:** Vi phạm LSP (dùng `typeid` check) thường dẫn đến vi phạm OCP vì sao? Tại sao STL có nhiều lớp nhỏ (`iterator`, `allocator`) thay vì 1 lớp lớn?

### Ngày 18: SOLID - D (Dependency Inversion)

*   **DIP:** Module cấp cao không phụ thuộc module cấp thấp, cả 2 phụ thuộc Abstraction. Đảo luồng: `UI→Interface←Business Logic→Interface←Database`. Vi phạm gây Rigidity, Immobility.
    
*   **Dependency Injection:** Constructor Injection (khuyên dùng - đảm bảo đủ dữ liệu ngay), Setter Injection, Interface Injection. Dùng `unique_ptr`/`shared_ptr` bơm Interface.
    
*   **Thực hành:** Ai chịu trách nhiệm xóa đối tượng được bơm? DI là "vua" Unit Test - Mock Objects giả lập Database/Network.
    

**BÀI TẬP:** Sửa `PasswordAnalyzer` phụ thuộc trực tiếp `MySQLDatabase`; Constructor Injection với `IDatabase`; Đọc mục G13/G14 (Artificial Coupling, Feature Envy).

**LAB 18 "Smart Home Controller":** Sai (`Switch` chứa trực tiếp `LightBulb`) vs Đúng (`ISwitchable`, `Switch` nhận `ISwitchable&` qua Constructor). Test bằng `MockDevice`.

**Câu hỏi:** Code rời rạc do Interface+DI khắp nơi - làm sao biết Interface được implement bởi lớp nào (Go to Implementation, tài liệu kiến trúc)? DIP đáng giá hơn 1% hiệu năng mất khi nào?

### Ngày 19: Design Patterns - Creational

*   **Singleton:** 1 instance duy nhất, điểm truy cập toàn cục. Constructor `private`, biến `static`, `getInstance()`. Thread-safety (mutex/"Magic Statics" C++11). Anti-pattern nếu lạm dụng (che giấu dependency, khó test).
    
*   **Factory Method:** Interface tạo object, lớp con quyết định loại cụ thể. Tuân OCP - thêm sản phẩm chỉ tạo Factory mới.
    
*   **Abstract Factory:** Tạo **họ** object liên quan (khác Factory Method chỉ tạo 1 loại). Ví dụ: `WindowsFactory`/`MacFactory` tạo bộ Button+Checkbox đồng bộ.
    

**BÀI TẬP:** Singleton `DatabaseConnection` (không copy, thread-safe); Factory Method cho game (`Enemy`, `EasyLevel`/`HardLevel`); Đọc chương 11 Clean Code (DI liên quan Creational Patterns).

**LAB 19 "Theme Builder" (Abstract Factory):** `IButton`/`ITextBox` → `DarkButton`/`LightButton`... → `IThemeFactory`→`DarkThemeFactory`/`LightThemeFactory`. Người dùng chọn Dark/Light, khởi tạo đúng bộ UI.

**Câu hỏi:** Tại sao ngày nay ưu tiên DI hơn Singleton? Thêm sản phẩm thứ 3 `ISlider` vào Abstract Factory - sửa bao nhiêu lớp, hạn chế thế nào?

### Ngày 20: Design Patterns - Structural

*   **Adapter:** Interface không tương thích làm việc được với nhau (phích chuyển đổi). Object Adapter (composition, khuyên dùng) vs Class Adapter (đa kế thừa).
    
*   **Decorator:** Gán thêm trách nhiệm runtime không sửa cấu trúc lớp. Tránh Class Explosion của kế thừa tĩnh - "lắp ghép như Lego" (`SimpleCoffee`+`WithMilk`+`WithSugar`).
    
*   **Facade:** Interface đơn giản cho subsystem phức tạp. "Đừng bắt khách hàng biết quá nhiều chi tiết" (`HomeTheaterFacade.watchMovie()` gọi 5 bước bên dưới).
    

**BÀI TẬP:** Adapter cho thư viện có `specificRequest()` khớp với `ITarget::request()`; Coffee Shop Decorator (`ICoffee`+`MilkDecorator`+`SugarDecorator`); Đọc chương 8 Clean Code, liên hệ Adapter với Boundaries.

**LAB 20 "Computer Startup Facade":** `ComputerFacade.startComputer()` gọi ngầm `CPU.freeze()`, `Memory.load()`, `HardDrive.read()`, `CPU.execute()`.

**Câu hỏi:** Adapter vs Decorator - khác biệt cốt lõi mục đích (đổi Interface vs thêm tính năng)? Facade có phải hình thức đóng gói, có ngăn Client truy cập trực tiếp lớp dưới không?

### Ngày 21: Design Patterns - Behavioral

*   **Strategy:** Họ thuật toán đóng gói, thay thế lẫn nhau. Composition - Context chứa `IStrategy*`, đổi chiến lược bất cứ lúc nào. Ví dụ hoàn hảo cho OCP.
    
*   **Observer:** 1-nhiều - Subject đổi trạng thái, Observer tự động nhận thông báo. `vector<IObserver*>`, `notify()` gọi `update()`. Cẩn thận attach/detach tránh Dangling Pointer.
    
*   **State:** Đối tượng đổi hành vi theo trạng thái nội bộ, như "đổi lớp". Loại bỏ `switch(currentState)` phức tạp. Mỗi trạng thái 1 lớp kế thừa `IState`, Context delegate.
    

**BÀI TẬP:** Strategy thanh toán (`IPaymentStrategy`→CreditCard/Paypal, chọn runtime); Observer tin tức (`NewsAgency`→`TVChannel`/`MobileApp`); Đọc chương 13 Clean Code (Race Condition khi Observer đa luồng).

**LAB 21 "Traffic Light" (State):** `ITrafficLightState`→`RedState`/`GreenState`/`YellowState`, `TrafficLight` giữ con trỏ trạng thái hiện tại, đổi hành vi mượt mà không 1 câu `if`.

**Câu hỏi:** Strategy vs State - UML gần giống nhau, khác biệt cốt lõi ở **ý định** (ai quyết định đổi object bên trong)? Observer truyền dữ liệu hiệu quả nhất - Push hay Pull?

### Ngày 22: Resource Management (RAII)

Ôn nhanh: RAII = tài nguyên gắn vòng đời object trên Stack. `unique_ptr` (độc quyền, zero-overhead), `shared_ptr` (reference counting, atomic), `weak_ptr` (phá circular dependency). Rule of Five. `make_unique`/`make_shared` an toàn hơn `new`.

*(Đã học rất kỹ Ngày 26-29, Phần 1 - đọc lại phần Smart Pointer trong ngữ cảnh Design Pattern để thấy góc nhìn mới, không làm lại Lab cơ bản.)*

### Ngày 23: Thực hành Design Patterns

*   **Mini-Framework "Order & Notification System":** Strategy (phí vận chuyển), Observer (thông báo Kho/Vận chuyển/Khách hàng), Singleton/Factory (config/Service).
    
*   **Circular Dependency thách thức:** `Order` cần biết `Customer` để thông báo; `Customer` cần danh sách `Order` - nếu cả 2 dùng `shared_ptr`, bộ nhớ không giải phóng.
    
*   **Kỹ thuật giải quyết:** Forward Declaration (`class Customer;` trong `Order.h`). `Order` sở hữu `Customer` (`shared_ptr`), `Customer` chỉ tham chiếu `Order` (`weak_ptr`).
    

**BÀI TẬP "Smart-Store":** AirShipping/GroundShipping (Strategy); thông báo khi status="SHIPPED" (Observer); `Customer::printHistory()` duyệt `weak_ptr`, kiểm tra `.lock()` trước khi in.

**LAB 23 "Phẫu thuật Circular Dependency":** Sửa `orderHistory` từ `shared_ptr`→`weak_ptr`; triển khai Strategy tính giá; đảm bảo cả `Customer` và `Order` in "destroyed" khi `main` kết thúc.

**Câu hỏi:** Forward Declaration chỉ hoạt động với con trỏ/tham chiếu, không với object thực thể - tại sao? Dùng `weak_ptr`, làm sao đảm bảo data không bị xóa giữa lúc dùng `printHistory()`? (`lock()`).

## Giai đoạn 4: Tối ưu hóa (Ngày 24–29)

### Ngày 24: Memory Management & Cache Locality

#### Phân cấp bộ nhớ & Cơ chế Cache

*   **Memory Hierarchy:** Tại sao CPU không đọc trực tiếp từ RAM — chênh lệch tốc độ giữa Register, L1, L2, L3 Cache và RAM.
    
*   **Cache Line:** CPU không đọc 1 byte lẻ — khi yêu cầu 1 biến, CPU bốc nguyên 1 khối (thường **64 bytes**) xung quanh vào Cache.
    
*   **Spatial Locality:** Truy cập 1 địa chỉ, khả năng cao sẽ truy cập địa chỉ sát nó trong tương lai gần.
    
*   **Temporal Locality:** Dữ liệu vừa dùng có khả năng được dùng lại sớm.
    

#### Array vs Linked List

*   **Mảng (Contiguous):** Phần tử nằm kề nhau — nạp 1 Cache Line có sẵn 4-16 phần tử tiếp theo (Cache Hit).
    
*   **Linked List (Fragmented):** Node rải rác trên Heap — mỗi lần nhảy Node là 1 lần đợi RAM (Cache Miss).
    
*   **CPU Pipelining & Branch Prediction:** Mảng giúp dự đoán dữ liệu tiếp theo cực chính xác.
    
*   **Thực nghiệm:** So sánh duyệt 1 triệu phần tử `vector<int>` vs `list<int>`.
    

#### Data-Oriented Design (DOD) sơ lược

*   **Tư duy hướng dữ liệu:** Thay vì gom mọi thứ vào Object (AoS — Array of Structures), cân nhắc tách dữ liệu (SoA — Structure of Arrays) để tối ưu Cache. *(Sẽ áp dụng sâu ở Ngày 33, Track B Game Development, phần ECS.)*
    
*   **Padding & Alignment:** Tại sao `struct` đôi khi lớn hơn tổng các thành phần cộng lại (nhắc lại Ngày 10, Phần 1).
    

**BÀI TẬP:**

1.  Duyệt mảng 2D 10000×10000 theo hàng (`array[i][j]`) vs cột (`array[j][i]`) — đo thời gian, giải thích bằng Cache Line.
    
2.  `sizeof` so sánh `struct Bad{char a; double b; char c;}` vs `struct Good{double b; char a; char c;}` — tại sao `Good` nhỏ hơn.
    

**LAB 24 "Cache-Conscious Search":** 1 triệu số nguyên — lưu `vector<int>` (sorted) vs `set<int>` (cây, node rời rạc). Tìm kiếm 10.000 giá trị ngẫu nhiên trên cả 2. Dù cùng O(log n), `vector`+`lower_bound` nhanh hơn đáng kể — giải thích bằng Cache Locality.

**Câu hỏi:** Nếu mảng luôn nhanh hơn, tại sao vẫn cần Linked List? Trường hợp nào tính cục bộ bộ nhớ không còn là ưu thế tuyệt đối? **False Sharing:** hai luồng ghi vào 2 biến khác nhau nhưng chung 1 Cache Line thì sao?

### Ngày 25: Move Semantics & Rvalue References

#### Lvalue và Rvalue

*   **Lvalue:** đối tượng có định danh, địa chỉ cố định (biến `x`, `obj`). **Rvalue:** giá trị tạm thời (hằng số, kết quả phép tính, object tạm trả về từ hàm).
    
*   **Rvalue Reference (**`&&`**):** cú pháp "bắt" giá trị tạm thời — đánh dấu "đối tượng sắp chết, có thể lấy trộm tài nguyên".
    

#### Move Constructor & Move Assignment

*   **Move Constructor:** thay vì cấp phát mới + copy (Copy Constructor), chỉ "trỏ" con trỏ mới vào vùng nhớ cũ, gán con trỏ cũ `nullptr`.
    
*   **Move Assignment Operator:** tương tự Move Constructor nhưng cho phép gán.
    
*   `std::move()`**:** không di chuyển gì cả — chỉ ép kiểu Lvalue thành Rvalue để kích hoạt Move Constructor.
    
*   **Rule of Five (hoàn thiện):** Destructor, Copy Constructor, Copy Assignment, Move Constructor, Move Assignment.
    

#### Perfect Forwarding & Tối ưu thực chiến

*   `std::forward`**:** giữ nguyên tính chất Lvalue/Rvalue khi truyền tham số qua Template.
    
*   **RVO:** khi nào compiler tự động thực hiện Return Value Optimization — tại sao **không nên** dùng `std::move()` khi trả về biến cục bộ từ hàm (ngăn RVO).
    

**BÀI TẬP:**

1.  Phân biệt Lvalue/Rvalue trong: `int a=10; int b=a+5; string s1="Hello"; string s2=s1+" World";`
    
2.  Thêm Move Constructor + Move Assignment cho `SimpleString` (Ngày 8), in "Move called" để kiểm chứng.
    
3.  `vector<SimpleString>` — `push_back` với Lvalue vs `push_back(std::move(obj))` — quan sát số lần cấp phát bộ nhớ giảm.
    

**LAB 25 "Big Data Transfer":** `BigData` chứa `int* data` 10 triệu phần tử. Copy Constructor (loop 10 triệu lần, chậm) vs Move Constructor (hoán đổi con trỏ, cực nhanh). `BigData createBigData()` trả về — đo thời gian `BigData b1 = createBigData();` (gần như 0ms nhờ Move).

**Câu hỏi:** Tại sao sau `std::move(obj)` không nên dùng lại `obj`? Nếu lớp có `unique_ptr` làm thành viên, compiler có tự tạo Move Constructor không? (`default` keyword).

### Ngày 26: Exception Safety & Performance

#### Chi phí thực sự của Exception

*   **Stack Unwinding:** khi `throw` kích hoạt, CPU tìm khối `catch` phù hợp và gọi Destructor cho mọi object trên Stack đang unwinding.
    
*   **Chi phí "Happy Path":** code có `try-catch` vẫn nhanh gần như thường nhờ "Zero-cost exceptions" (table-based).
    
*   **Chi phí khi lỗi xảy ra:** `throw` đắt hơn hàng trăm lần so với `if-else`/return code.
    
*   `noexcept` **(C++11):** đánh dấu hàm không ném exception để compiler tối ưu cực hạn.
    

#### 3 Cấp độ An toàn ngoại lệ

*   **Basic Guarantee:** không leak, object vẫn hợp lệ (dù data có thể không như ý).
    
*   **Strong Guarantee (Rollback):** "All or Nothing" — thất bại thì quay về trạng thái y hệt trước khi gọi. Kỹ thuật: **Copy-and-Swap**.
    
*   **No-fail Guarantee:** cam kết không bao giờ throw (Destructor, Move Constructor, hàm giải phóng tài nguyên).
    

#### Kỹ thuật viết code An toàn & Hiệu năng

*   RAII là chìa khóa — không có Exception Safety nếu không dùng RAII (Ngày 26 gốc, đã học Ngày 22 Phần 1 Phần 3).
    
*   Ném exception trong Destructor khi đang unwinding → gọi `std::terminate` ngay lập tức.
    
*   `std::optional`/`std::expected` (đã học Ngày 50.9) thay Exception trong code nhạy cảm hiệu năng.
    

**BÀI TẬP:**

1.  Move Constructor không `noexcept` — thêm vào `vector`, quan sát `vector` chọn Copy thay Move để an toàn (giảm hiệu năng). Thêm `noexcept`, chạy lại.
    
2.  Viết `operator=` cho `MyBuffer` đạt Strong Exception Safety bằng Copy-and-Swap (tạo bản sao tạm, swap với `this`, swap không được throw).
    
3.  Đọc chương 7 Clean Code, mục "Define Exception Classes in Terms of a Caller's Needs".
    

**LAB 26 "Transaction Manager":** `transfer(Account& from, Account& to, double amount)` — Strong Guarantee: lỗi khi trừ `from` → tiền không mất; lỗi khi cộng `to` → tiền phải trả lại `from`. Dùng RAII để tự động hoàn tác nếu giao dịch không hoàn tất.

**Câu hỏi:** Tại sao Google/Linux Kernel thường cấm C++ Exceptions dù nó làm code sạch hơn? Exception thoát khỏi 1 `noexcept` function thì chuyện gì xảy ra?

### Ngày 27: Concurrency & Multithreading (Cơ bản)

*(Ghi chú: đây là bài học Multithreading* ***đầu tiên*** *trong Phần 3 — khác Ngày 51-55 Phần 1 vốn đã học rất sâu. Ngày này ôn lại nhanh dưới góc nhìn Class Design, không lặp lại toàn bộ lý thuyết đã học.)*

#### Luồng & Race Condition — ôn nhanh

*   `std::thread`: `join()` vs `detach()`. Khởi tạo bằng hàm thường/Lambda/**Hàm thành viên của lớp** (`std::thread t(&Downloader::download, &myObj);` — điểm quan trọng khi kết hợp OOP).
    
*   Race Condition: 2 luồng đọc/ghi cùng biến. `std::mutex`, RAII cho mutex (`lock_guard`, `unique_lock`).
    

#### Thread-Safe Class Design — trọng tâm ngày này

*   **Tích hợp mutex vào Class:** đặt `mutable std::mutex` làm thành viên `private` để bảo vệ dữ liệu, ngay cả trong hàm `const` (`mutable` cho phép lock trong hàm `const`).
    
*   **Granularity (độ mịn khóa):** khóa toàn bộ object hay chỉ 1 phần dữ liệu — đánh đổi an toàn vs hiệu năng.
    
*   `std::atomic`: khi nào dùng biến nguyên tử thay Mutex cho biến đơn giản, đạt hiệu suất cao hơn.
    

**BÀI TẬP:**

1.  `Counter{int value=0;}` — 2 luồng, mỗi luồng tăng 100.000 lần không mutex → kết quả sai (Race Condition). Sửa bằng `mutex`, kết quả đúng.
    
2.  `Downloader` — tạo luồng chạy hàm thành viên `download()` của 1 object cụ thể.
    
3.  Đọc chương 13 Clean Code (Concurrency): "Keep your concurrency-related code separate" và "Limit the scope of data".
    

**LAB 27 "The Thread-Safe Bank":** `BankAccount` hỗ trợ nạp/rút tiền từ nhiều luồng đồng thời mà không sai lệch số dư. **LAB phụ "Multi-threaded Logger":** `Logger` Singleton, `log(string)` mở file/ghi timestamp/đóng file — dùng `lock_guard` đảm bảo dòng log không trộn lẫn khi 10 luồng cùng gọi.

*(Ghi chú: Logger tự viết ở đây sẽ được thay bằng thư viện thật* `spdlog` *ở Ngày 31.)*

**Câu hỏi:** Hàm chỉ **đọc** dữ liệu có cần Mutex không? (`std::shared_mutex`, C++17). Lạm dụng Mutex có thể làm chương trình đa luồng chạy **chậm hơn** đơn luồng — tại sao?

### Ngày 28: STL Optimization

#### Tối ưu hóa Vector & Chuỗi

*   **Reallocation:** tại sao `push_back` có thể chậm gấp 10 lần (copy toàn bộ mảng khi vượt `capacity`). `reserve()` vs `resize()`. `emplace_back()` vs `push_back()` (in-place construction).
    
*   **Small String Optimization (SSO):** ôn lại Ngày 14, Phần 1 — chuỗi ngắn lưu trên Stack.
    
*   `shrink_to_fit()` và swap idiom để giải phóng bộ nhớ thực sự.
    

#### Map vs Unordered\_Map

*   `map` (Red-Black Tree, O(log n), có thứ tự, tốn bộ nhớ node, không cache-friendly) vs `unordered_map` (Hash Table, O(1) trung bình, có thể Hash Collision → O(n) worst case).
    

#### Set & Modern STL (C++17/20)

*   `set` vs `unordered_set`. Tại sao `vector` đã sort + `binary_search` đôi khi tốt hơn `set` (Cache Locality, Ngày 24).
    
*   `std::string_view`: tránh copy chuỗi khi chỉ đọc. `std::span`: truyền mảng/vector vào hàm không phụ thuộc container.
    

**BÀI TẬP:**

1.  `push_back` 1 triệu phần tử — đo có/không `reserve()`, đếm số lần `.data()` đổi địa chỉ.
    
2.  Benchmark `map` vs `unordered_map`: 100.000 cặp Key-Value, tìm 10.000 khóa — giải thích tại sao `unordered_map` nhanh hơn.
    
3.  Đọc chương 14 Clean Code — liên hệ cấu trúc dữ liệu sạch giúp giảm độ phức tạp thuật toán.
    

**LAB 28 "Customer Data Analyzer":** 500.000 khách hàng (ID int, Name string). Tìm theo ID nhanh (`unordered_map`); liệt kê ID 1000-2000 tăng dần (`map`); tối ưu bộ nhớ bằng `vector`+`lower_bound` cho data tĩnh; hàm nhận `string_view` thay `const string&`, đo chênh lệch hiệu năng.

**Câu hỏi:** Tại sao `operator[]` trên `map` nguy hiểm hơn `map::at()`? Với tập dữ liệu nhỏ (<100 phần tử), tại sao `vector` phẳng thường nhanh hơn `unordered_map`?

### Ngày 29: Profiling & Debugging

#### Debug với GDB

*   Biên dịch với cờ `-g` giữ thông tin debug. Lệnh sống còn: `run`, `break`, `step`, `next`, `print`.
    
*   Nâng cao: `backtrace` (truy vết crash), `watch` (dừng khi biến đổi giá trị), debug đa luồng.
    

#### Valgrind

*   **Memcheck:** "Definitely lost" vs "Still reachable". Phát hiện Invalid read/write, biến chưa khởi tạo.
    
*   **Helgrind:** tìm Race Condition trong code đa luồng (Ngày 27).
    

#### Profiling

*   **Gprof & Perf:** tìm "Hot spots" — hàm tốn CPU nhất. **Flame Graphs.** **Cachegrind:** đo Cache Miss (thực chứng Ngày 24).
    

**Ghi chú bổ sung:** chạy song song ASan/UBSan (Ngày 0, đã dùng từ Ngày 11/13 Phần 1) với Valgrind/GDB ở mọi Lab ngày này — tự so sánh 2 bộ công cụ trên cùng 1 lỗi: tốc độ, độ chi tiết thông báo.

**BÀI TẬP:**

1.  Code cố tình truy cập con trỏ NULL/mảng quá giới hạn — dùng GDB `backtrace` xác định chính xác dòng lỗi.
    
2.  `SimpleString` không Destructor (hoặc `vector` con trỏ `new` không `delete`) — chạy Valgrind, sửa đến khi "All heap blocks were freed".
    
3.  Đọc chương 15 Clean Code (JUnit Internals) — liên hệ Unit Test tốt giúp Debug dễ dàng hơn.
    

**LAB 29 "Memory & Performance Doctor":** Ứng dụng xử lý 1 triệu sinh viên đang gặp 2 vấn đề: (1) leak RAM càng chạy càng nhiều, (2) sort/tìm kiếm mất 10 giây. Dùng Valgrind Memcheck tìm chỗ quên `delete`; dùng Gprof phát hiện đang dùng Bubble Sort O(n²), thay `std::sort`; dùng Cachegrind kiểm tra % Cache Miss giảm khi đổi `list`→`vector`.

**Câu hỏi:** Tại sao không nên bật `-O3` khi debug bằng GDB (compiler có thể đổi thứ tự dòng/xóa biến)? Khác biệt Static Analysis (Cppcheck) vs Dynamic Analysis (Valgrind) — tại sao cần cả hai?

## Ngày 30 - Capstone Project (Smart Library Engine/Mini Game Engine)

#### Phân tích & Thiết kế kiến trúc

Chọn 1 trong 2 chủ đề:

*   **Chủ đề A (Hệ thống quản lý):** Smart Library Management — chức năng tìm kiếm, mượn trả, phân loại sách đa tầng.
    
*   **Chủ đề B (Hệ thống mô phỏng):** Mini Game Engine — quản lý entity, xử lý va chạm, hệ thống Rendering trừu tượng.
    

**Nhiệm vụ thiết kế:**

*   **Sơ đồ lớp (Class Diagram):** vẽ cấu trúc phân cấp, xác định các Interface (ví dụ `IRepository`, `IEntity`, `IObserver`).
    
*   **Áp dụng SOLID:** xác định nơi dùng **Strategy** (tìm kiếm/sắp xếp), nơi dùng **Factory** (khởi tạo đối tượng), nơi dùng **Observer** (thông báo sự kiện).
    

#### Thực thi mã nguồn "sạch"

*   **Memory Management:** tuyệt đối `unique_ptr`/`shared_ptr`, không `new/delete` thủ công.
    
*   **Templates:** viết Container hoặc hàm tìm kiếm tổng quát.
    
*   **Move Semantics:** tối ưu chuyển giao dữ liệu giữa các module.
    
*   **Exception Safety:** hệ thống không "sập" khi input sai hoặc file hỏng.
    
*   **Thread-safety:** (nếu làm hệ thống lớn) đảm bảo truy xuất đồng thời không gây Race Condition.
    

#### Tối ưu hóa, Debug & Đóng gói

*   **Profiling:** chạy Valgrind đảm bảo 0% Memory Leak.
    
*   **Performance:** áp dụng Cache Locality (Ngày 24) và STL Optimization (Ngày 28) cho các vòng lặp xử lý dữ liệu nặng.
    
*   **Clean Code Review:** đọc lại code lần cuối — "Nếu người khác đọc code này, họ hiểu ngay trong 30 giây không?"
    
*   **Documentation:** viết `README.md` hướng dẫn biên dịch và kiến trúc hệ thống.
    

#### YÊU CẦU KỸ THUẬT BẮT BUỘC (CHECKLIST)

1.  **Encapsulation:** không có biến thành viên nào để `public`.
    
2.  **Polymorphism:** có ≥1 Interface hoặc Abstract Class.
    
3.  **SOLID:** LSP (lớp con thay lớp cha không gây lỗi); DIP (lớp cấp cao không phụ thuộc trực tiếp lớp cấp thấp — dùng Dependency Injection).
    
4.  **Design Patterns:** áp dụng ≥2 mẫu (ví dụ: Singleton cho Logger, Factory cho việc tạo Book/Entity).
    
5.  **Modern C++:** dùng `auto`, `lambda`, `nullptr`, `std::string_view`.
    
6.  **Bổ sung:** ≥5 test case bằng Google Test cho các class quan trọng nhất (ví dụ `LibraryCatalog`, `SearchStrategy`).
    

#### LAB 30: THE FINAL CHALLENGE - "SMART LIBRARY ENGINE"

Nếu chọn hệ thống quản lý thư viện, thực hiện các tính năng sau để chứng minh trình độ:

1.  **Dữ liệu lớn:** xử lý 100.000 cuốn sách lưu trong `std::vector`, được Index bởi `std::unordered_map` để tìm kiếm O(1).
    
2.  **Tính năng tìm kiếm (Strategy Pattern):** cho phép tìm theo Tên, Tác giả, hoặc ISBN bằng cách đổi thuật toán tìm kiếm tại Runtime.
    
3.  **Hệ thống Log (Observer Pattern):** mỗi khi sách được mượn, các module `EmailService` và `InventoryService` nhận thông báo để cập nhật.
    
4.  **An toàn:** dùng `std::unique_ptr` quản lý danh sách sách, đảm bảo khi chương trình tắt, toàn bộ dữ liệu được giải phóng sạch sẽ.
    

## NGÀY 31: QUẢN LÝ DEPENDENCY VỚI VCPKG

*Mục tiêu: tích hợp thư viện thật vào Capstone thay vì tiếp tục tự viết mọi thứ - ranh giới giữa "bài tập học thuật" và "code thực tế đi làm".*

#### Vì sao không tự viết mọi thứ

110 ngày trước bạn tự viết Logger, Smart Pointer, Container - đúng mục đích hiểu internal. Nhưng thực tế, tự viết lại Logger/JSON parser là lãng phí, rủi ro (thư viện chuẩn đã được kiểm thử nhiều năm). Ranh giới đúng: hiểu internal để **chọn đúng và debug được**, không phải luôn tự viết lại.

#### vcpkg manifest mode

`vcpkg.json` khai báo dependency riêng từng project. Tích hợp `CMAKE_TOOLCHAIN_FILE` (Ngày 0). Semantic Versioning (`X.Y.Z`): Major/Minor/Patch.

#### Thay Logger tự viết bằng spdlog - kiểm chứng DIP thực tế

Ngày 27 tự viết Logger dùng mutex. Hôm nay thay bằng `spdlog` (async logging, format nhanh nhờ `fmt`). **Điểm mấu chốt:** nếu code gọi qua Interface `ILogger` (DIP - Ngày 18) thay vì gọi trực tiếp, đổi sang spdlog **không cần sửa dòng nào** ở code nghiệp vụ - chỉ viết `SpdlogAdapter` (Ngày 20) bọc spdlog theo `ILogger`.

**LAB:**

1.  Tạo `vcpkg.json` khai báo `spdlog`+`fmt`.
    
2.  Viết `SpdlogAdapter : public ILogger` bọc `spdlog::logger`.
    
3.  Đo hiệu năng ghi 100.000 dòng log giữa Logger tự viết vs spdlog, giải thích chênh lệch bằng async logging.
    

**Câu hỏi:**

1.  Nếu `ILogger` là abstraction tốt (DIP), đổi Logger→spdlog ảnh hưởng gì code gọi nó? Bằng chứng thực tế cho DIP?
    
2.  Khi nào "tự viết lại thay vì dùng thư viện có sẵn" vẫn là lựa chọn đúng? (nhớ lại mục đích Ngày 15, Phần 1 - Mini Project Smart Pointer).
    

## NGÀY 32: SANITIZERS & CI CƠ BẢN

*Mục tiêu: đưa Capstone qua pipeline kiểm tra tự động giống môi trường làm việc thực tế.*

#### Sanitizers trên toàn bộ Capstone

Build lại toàn bộ (Ngày 30-31) với `-fsanitize=address,undefined` (Ngày 0), chạy toàn bộ test suite (Ngày 5.5). Mục tiêu: 0 lỗi trước khi coi project "sẵn sàng".

#### CI cơ bản (GitHub Actions)

1 file `.github/workflows/ci.yml`: mỗi lần push, tự build CMake, chạy `ctest`, build lại với sanitizer. Vai trò CI: máy khác build lại từ đầu, phát hiện lỗi "chạy được trên máy tôi nhưng không chạy trên máy khác".

#### Static Analysis

`clang-tidy`: tự phát hiện code smell (Ngày 1-6, Phần 3). `clang-format`: format nhất quán (Ngày 3, Phần 1), loại tranh cãi style trong team.

#### Checklist hoàn thiện cuối

1.  Toàn bộ test (Ngày 5.5) pass. 2. 0 lỗi ASan/UBSan. 3. 0 warning nghiêm trọng clang-tidy. 4. Format nhất quán. 5. CI pipeline pass.
    

**LAB:**

1.  Viết `.github/workflows/ci.yml` build+test+sanitize tự động.
    
2.  Chạy `clang-tidy`, sửa ≥5 warning.
    
3.  Áp `clang-format` (Google style) toàn project, commit.
    

**Câu hỏi (tổng kết toàn bộ 122 ngày):**

1.  Nhìn lại Ngày 1 (Phần 1) - "vòng đời chương trình C++" - CI hôm nay tự động hóa đúng bước nào trước kia phải làm tay?
    
2.  Chọn 3 khoảnh khắc "hiểu ra tận gốc" quan trọng nhất trong 122 ngày - Cache Line (Ngày 9), V-Table (Ngày 23), Move Semantics (Ngày 25), Coroutine Frame trên Heap (Ngày 50.7), Sanitizer hôm nay - đâu là 3 điều thay đổi cách bạn đọc code C++ của người khác nhiều nhất?
    

# PHẦN 4: 17 NGÀY CHUYÊN SÂU THEO HƯỚNG

## TRACK A: SYSTEMS PROGRAMMING

### Ngày 33: SIMD & Vectorization

*Mục tiêu: hiểu cách CPU xử lý nhiều dữ liệu trong 1 chu kỳ - nối lại Ngày 45 (Parallel STL) và Ngày 56 (Alignment/Cache-friendly).*

*   **SIMD là gì:** Single Instruction Multiple Data - 1 lệnh CPU xử lý 4/8/16 số cùng lúc (SSE, AVX, AVX-512). Khác Multithreading (Ngày 51) - SIMD song song trong **1 lõi**, không cần nhiều thread.
    
*   **Auto-vectorization:** Compiler tự SIMD hóa loop đơn giản với `-O3 -march=native` (đã dùng Ngày 20, Phần 2). Điều kiện: loop không có branch phức tạp, dữ liệu liên tục (liên hệ Cache Line Ngày 9).
    
*   **Intrinsics thủ công:** `<immintrin.h>` - `_mm256_add_ps` cộng 8 float cùng lúc. So sánh Assembly (godbolt.org, Ngày 7) giữa loop thường và intrinsics.
    
*   **Data layout cho SIMD:** AoS vs SoA (Ngày 56) - SIMD chỉ hiệu quả khi dữ liệu là SoA (Structure of Arrays), vì cần load liên tục cùng loại.
    

**LAB:** Viết hàm cộng 2 mảng 10 triệu float bằng loop thường, loop auto-vectorized (`-O3`), và intrinsics tay. Benchmark 3 cách bằng `<chrono>` (Ngày 7), giải thích chênh lệch dựa trên Cache Line và AoS/SoA.

**Câu hỏi:** Tại sao SIMD yêu cầu dữ liệu liên tục trong RAM (liên hệ `vector` vs `list`, Ngày 39 Phần 2)? Tại sao SIMD không giúp gì nếu loop có `if` phức tạp bên trong (branch misprediction, Ngày 5)?

### Ngày 34: Lock-free Data Structures nâng cao

*Mục tiêu: vượt qua ThreadPool cơ bản (Ngày 55) để viết cấu trúc lock-free thực dụng.*

*   **Nhắc lại nền tảng:** `atomic`, CAS (`compare_exchange_weak/strong`), memory ordering (Ngày 54).
    
*   **Lock-free Ring Buffer (SPSC - Single Producer Single Consumer):** Dùng 2 `atomic<size_t>` (head/tail) thay mutex. Nối trực tiếp Ring Buffer đã học Ngày 4 (Phần 2 DSA) nhưng loại bỏ hoàn toàn lock.
    
*   **ABA Problem:** Vấn đề kinh điển của lock-free - giá trị đổi A→B→A giữa 2 lần CAS khiến thread tưởng không đổi gì. Giải pháp: tagged pointer hoặc versioning.
    
*   **Khi nào lock-free THỰC SỰ đáng làm:** Chỉ khi đã profiling (Ngày 58) và xác nhận mutex là bottleneck thật - lock-free cực khó debug, dễ sai hơn nhiều so với mutex.
    

**LAB:** Viết SPSC Ring Buffer lock-free hoàn chỉnh bằng `atomic`. Benchmark với ThreadPool dùng mutex (Ngày 55) trên bài toán producer-consumer 10 triệu item, đo throughput.

**Câu hỏi:** Tại sao SPSC (1 producer, 1 consumer) dễ làm lock-free hơn MPMC (nhiều producer, nhiều consumer)? ABA Problem có thể xảy ra trong Ring Buffer SPSC không, tại sao?

### Ngày 35: Đọc source LLVM - Kiến trúc Compiler

*Mục tiêu: nhìn lại toàn bộ Ngày 1 (Phần 1) qua lăng kính của người viết compiler thật.*

*   **Kiến trúc 3 tầng:** Frontend (Clang - parse C++ thành AST) → Middle-end (LLVM IR - dạng trung gian độc lập ngôn ngữ) → Backend (sinh mã máy cho x86/ARM). Nối lại Pipeline Ngày 1 nhưng chi tiết hơn nhiều bước.
    
*   **LLVM IR:** Đọc IR sinh ra từ 1 hàm C++ đơn giản (`clang -S -emit-llvm`). So sánh IR ở `-O0` vs `-O2` để thấy optimization pass hoạt động (inlining Ngày 7, devirtualization Ngày 22 đều là LLVM pass).
    
*   **Optimization Passes:** Dead code elimination, loop unrolling (Ngày 5), constant folding (Ngày 8) - tất cả là các pass riêng biệt chạy trên IR, không phải "một khối tối ưu hóa".
    

**LAB:** Lấy 1 hàm đã viết ở Ngày 22 (Virtual Function) và Ngày 25 (Move Semantics), sinh LLVM IR ở `-O0` và `-O2`, đọc và chỉ ra optimization pass nào đã áp dụng (inlining, devirtualization nếu có `final` - Ngày 22).

**Câu hỏi:** Tại sao LLVM IR độc lập ngôn ngữ lại cho phép Clang, Rust, Swift dùng chung 1 backend? Việc tách Frontend/Backend này liên hệ gì với nguyên lý SRP (Ngày 16, Phần 3)?

### Ngày 36: Đọc source Folly (Meta) - Thư viện hiệu năng cao thực chiến

*Mục tiêu: xem cách công ty lớn viết lại STL cho hiệu năng cực hạn - đối chiếu với mọi thứ đã tự viết.*

*   `folly::small_vector`**:** SSO (Ngày 14, 20) áp dụng cho `vector` không chỉ `string` - tránh cấp phát Heap khi số phần tử nhỏ.
    
*   `folly::F14 (F14ValueMap/F14FastMap)`**:** Hash table tối ưu hơn `unordered_map` (Ngày 38, Phần 2) - dùng SIMD (Ngày 33) để tìm slot nhanh hơn.
    
*   `folly::Synchronized<T>`**:** Wrapper RAII (Ngày 26) bọc mutex quanh dữ liệu - mẫu hình thực tế của "Thread-Safe Class Design" đã học sơ lược Ngày 27.
    

**LAB:** Đọc source `folly::small_vector` trên GitHub, xác định ngưỡng SSO nó dùng và so với ngưỡng SSO của `std::string` đã đo ở Ngày 14. Viết lại 1 phiên bản tối giản của `small_vector<T, N>` (template, N phần tử đầu trên Stack, vượt N thì chuyển Heap).

**Câu hỏi:** Vì sao các công ty lớn (Meta, Google với Abseil) vẫn viết lại container thay vì dùng STL chuẩn, dù STL đã rất tối ưu? Đánh đổi gì giữa "tự viết để tối ưu cực hạn" và "dùng chuẩn để dễ bảo trì" (liên hệ Ngày 31, Phần 3)?

### Ngày 37: Custom Allocators & Memory Pools nâng cao

*Mục tiêu: vượt qua Placement New sơ lược (Ngày 11) để viết allocator thực dụng theo chuẩn C++17 Polymorphic Allocator.*

*   `std::pmr` **(Polymorphic Memory Resource, C++17):** `memory_resource` interface - cách chuẩn hóa allocator thay vì template allocator kiểu cũ phức tạp.
    
*   **Arena Allocator:** Cấp 1 khối lớn trước, cấp phát nhỏ bên trong bằng cách tăng con trỏ - không `free` từng phần tử, giải phóng cả khối 1 lần. Nối lại "memory pool" đã nhắc ở Capstone Order Book (Ngày 59-60, Phần 1).
    
*   **Khi nào custom allocator đáng làm:** Chỉ khi Profiling (Ngày 58) xác nhận `new/delete` là bottleneck - ví dụ game engine cấp phát/hủy hàng ngàn object mỗi frame.
    

**LAB:** Viết `ArenaAllocator` tuân `std::pmr::memory_resource`, dùng nó với `std::pmr::vector` để quản lý 1 triệu object nhỏ trong 1 frame giả lập, đo tốc độ so với `new/delete` thường.

**Câu hỏi:** Arena Allocator không hỗ trợ giải phóng từng phần tử riêng lẻ - tại sao đây là đánh đổi hợp lý cho game engine nhưng không hợp lý cho hệ thống Order Book (Ngày 59-60)?

### Ngày 38: Capstone Track A

*Dự án tổng hợp:* ***"High-Performance Lock-Free Metrics Aggregator"*** *\- hệ thống thu thập metrics (giống Prometheus mini).*

**Yêu cầu:**

1.  SPSC lock-free ring buffer (Ngày 34) nhận metrics từ nhiều thread ghi log.
    
2.  Arena allocator (Ngày 37) cấp phát các struct Metric nhỏ, tránh `new/delete` liên tục.
    
3.  Dùng SIMD (Ngày 33) để tính trung bình/tổng trên batch metrics.
    
4.  Sinh LLVM IR (Ngày 35) cho hàm tính toán nóng nhất, xác nhận đã được vectorize ở `-O2`.
    
5.  Test bằng Google Test (Ngày 5.5) + chạy qua ASan/TSan (Ngày 0, 27).
    

**Checklist:** 0 lock trong hot path; 0 cấp phát Heap trong loop chính; SIMD xác nhận qua Assembly; throughput đo bằng `<chrono>` so với bản dùng `mutex`+`new/delete` thường.

## TRACK B: GAME DEVELOPMENT

### Ngày 33: Data-Oriented Design sâu - Entity Component System (ECS)

*Mục tiêu: biến "AoS vs SoA" (nhắc sơ lược Ngày 56) thành kiến trúc game thực tế.*

*   **Vấn đề của OOP truyền thống trong game:** `class Enemy : public GameObject` với hàm ảo `update()` (Ngày 22) - gọi 1 triệu object mỗi frame qua V-Table (Ngày 23) gây cache miss liên tục vì mỗi object nằm rải rác trên Heap.
    
*   **ECS - tư duy đảo ngược:** Không có "Enemy object" nữa. Chỉ có **Component arrays** riêng biệt: `vector<Position>`, `vector<Velocity>`, `vector<Health>` - mỗi array liên tục trong RAM (đúng SoA, Ngày 56). Entity chỉ là 1 ID liên kết index qua các array.
    
*   **System xử lý:** 1 hàm `MovementSystem` duyệt `vector<Position>`+`vector<Velocity>` liên tục - tận dụng Cache Line tối đa (Ngày 9), không hàm ảo, không pointer chasing (Ngày 3, Phần 2 DSA).
    

**LAB:** Viết ECS tối giản: `EntityID` (int), `ComponentArray<Position>`, `ComponentArray<Velocity>`. So sánh benchmark update 1 triệu entity bằng ECS vs bằng OOP truyền thống (`vector<unique_ptr<Enemy>>`, gọi `virtual update()`).

**Câu hỏi:** Tại sao ECS loại bỏ hoàn toàn Virtual Function (Ngày 22) khỏi hot loop? Đánh đổi gì về mặt "dễ đọc code" so với OOP truyền thống (liên hệ Clean Code, Ngày 1-6 Phần 3)?

### Ngày 34: Job System & Frame-based Memory

*Mục tiêu: quản lý bộ nhớ và song song hóa theo nhịp frame - khác hoàn toàn ThreadPool tổng quát (Ngày 55).*

*   **Frame Arena Allocator:** Nối lại Ngày 37 (Track A) - mỗi frame cấp 1 arena, "xóa" bằng cách reset con trỏ về đầu khi frame kết thúc, không gọi `delete` từng object.
    
*   **Job System:** Chia công việc mỗi frame (physics, AI, rendering) thành các Job nhỏ, phân cho Thread Pool cố định (Ngày 55) - khác `std::async` (Ngày 53) vì Job System tối ưu cho hàng ngàn task cực nhỏ, lặp lại mỗi frame, không tạo/hủy thread liên tục.
    
*   **Dependency giữa Job:** Job B chỉ chạy sau Job A xong (ví dụ: AI phải chạy sau khi Physics cập nhật vị trí) - dùng `atomic<int>` đếm dependency đã hoàn thành (Ngày 54).
    

**LAB:** Viết Frame Arena Allocator reset mỗi frame. Viết Job System tối giản với dependency counter, chạy 3 Job giả lập (Physics→AI→Render) trên ThreadPool 4 luồng, đo thời gian mỗi frame.

**Câu hỏi:** Tại sao Frame Arena không cần gọi destructor từng object khi reset, miễn là object không sở hữu tài nguyên ngoài (file, socket)? Đây có vi phạm RAII (Ngày 26) không, tại sao vẫn được chấp nhận trong game engine?

### Ngày 35: Unreal C++ - UCLASS/UPROPERTY & Garbage Collection riêng

*Mục tiêu: hiểu Unreal Engine "phá vỡ" nhiều quy tắc C++ chuẩn đã học vì lý do gì.*

*   **UCLASS/UPROPERTY/UFUNCTION:** Macro sinh code (Unreal Header Tool) - không phải C++ chuẩn, là 1 lớp tiền xử lý bổ sung trên Preprocessing (Ngày 1). `UPROPERTY()` đánh dấu biến để Garbage Collector và Editor nhận diện.
    
*   **Garbage Collection của Unreal:** Khác hoàn toàn `unique_ptr`/`shared_ptr` (Ngày 27-28) - Unreal dùng GC riêng (mark-and-sweep) cho `UObject`. Vì sao game engine chọn GC thay RAII thuần: đối tượng game có vòng đời phức tạp, tham chiếu qua lại (Actor→Component→Actor) mà `weak_ptr` (Ngày 28) xử lý được nhưng cồng kềnh ở quy mô hàng ngàn object.
    
*   `TSharedPtr`**/**`TWeakPtr`**:** Bản riêng của Unreal cho object **không phải** `UObject` - vẫn dùng reference counting như `shared_ptr` (Ngày 28) nhưng tự viết vì lý do lịch sử platform.
    

**LAB (cần Unreal Engine cài sẵn):** Tạo 1 `UCLASS` Actor tối giản với `UPROPERTY` là `TArray<AActor*>` (tương đương `vector<Actor*>` nhưng được GC quản lý). Quan sát Unreal tự động set `nullptr` khi object bị destroy - so sánh với hành vi dangling pointer thường gặp ở Ngày 13 (Phần 1).

**Câu hỏi:** Vì sao Unreal không dùng `shared_ptr` chuẩn cho toàn bộ `UObject` mà viết GC riêng? Nối lại lý do circular reference (Ngày 28) - GC mark-and-sweep giải quyết circular reference tốt hơn `weak_ptr` ở quy mô nào?

### Ngày 36: Unreal C++ - Gameplay Framework

*Mục tiêu: đối chiếu Actor/Component của Unreal với Composition (Ngày 10, Phần 3) đã học.*

*   **Actor & Component:** `AActor` chứa nhiều `UActorComponent` (Movement, Mesh, Collision) - đây chính là **Composition ("Has-a")** đã học Ngày 10, không phải kế thừa sâu. Unreal khuyến khích "component-based" hơn "inheritance-heavy" vì lý do giống hệt bài học Ngày 10 (Loose Coupling, linh hoạt runtime).
    
*   **Replication sơ lược (multiplayer):** `UPROPERTY(Replicated)` - biến tự đồng bộ giữa server/client. Đây là 1 dạng Observer Pattern (Ngày 21) ở tầm network, nhưng ẩn hoàn toàn cơ chế network bên dưới.
    

**LAB:** Tạo 1 `AActor` với 2 Component tùy biến (ví dụ `HealthComponent`, `WeaponComponent`) - áp dụng đúng tư duy Composition đã học Ngày 10, không kế thừa `AActor` cho từng loại vật phẩm.

**Câu hỏi:** So sánh kiến trúc Actor-Component của Unreal với bài toán "Robot Simulator" đã làm ở Ngày 10 (Phần 3) - chúng có cùng động lực thiết kế không?

### Ngày 37: Capstone Track B

*Dự án tổng hợp:* ***"Mini ECS Game Engine"*** *\- không cần Unreal, chạy console, chứng minh hiểu Data-Oriented Design.*

**Yêu cầu:**

1.  ECS tối giản (Ngày 33): Position, Velocity, Health components.
    
2.  Frame Arena Allocator (Ngày 34) cấp phát mọi entity mỗi frame.
    
3.  Job System (Ngày 34) chạy 2 System song song (Movement, Health regen) trên ThreadPool.
    
4.  Mô phỏng 100.000 entity di chuyển 1000 frame, đo FPS trung bình.
    
5.  So sánh với bản viết bằng OOP truyền thống (`vector<unique_ptr<GameObject>>` + virtual `update()`) - chứng minh ECS nhanh hơn nhờ Cache Locality (Ngày 9).
    

**Checklist:** Không dùng Virtual Function trong hot loop; Component arrays liên tục trong RAM; Frame Arena reset đúng mỗi frame không leak; benchmark có số liệu cụ thể chứng minh chênh lệch.

## TRACK C: BACKEND HIỆU NĂNG CAO

### Ngày 33: Boost.Asio - I/O nền cho network

*Mục tiêu: nối* `std::thread`*/*`async` *(Ngày 51, 53) vào bài toán I/O mạng thật.*

*   **io\_context:** Trái tim của Asio - event loop chạy các callback khi I/O sẵn sàng, khác `std::thread` (Ngày 51) chạy song song thật, `io_context` chạy tuần tự trên callback nhưng không blocking.
    
*   **Async operations:** `async_read`/`async_write` nhận callback - mô hình callback lồng nhau ("callback hell") chính là vấn đề mà Coroutine (Ngày 50.7-50.8) giải quyết.
    
*   **Strand:** Đảm bảo các callback trên cùng 1 `strand` không chạy đồng thời - 1 dạng mutex ngầm (Ngày 51) nhưng không cần lock tay.
    

**LAB:** Viết TCP echo server tối giản bằng Asio callback-style (chưa dùng coroutine), nhận nhiều kết nối đồng thời, đo số kết nối xử lý được so với việc tạo `std::thread` riêng cho mỗi kết nối (Ngày 51).

**Câu hỏi:** Vì sao Asio callback-style xử lý được hàng ngàn kết nối trên vài thread, còn tạo `std::thread`/kết nối (Ngày 51) thì không? (liên hệ chi phí context-switch, Ngày 27).

### Ngày 34: Asio + Coroutines - nối trực tiếp Ngày 50.7–50.8

*Mục tiêu: thay callback lồng nhau bằng code tuyến tính dùng Coroutine đã học.*

*   `co_await` **với Asio:** `boost::asio::awaitable<T>` - Asio tự cung cấp Awaitable (đã học giao thức 3 hàm `await_ready/suspend/resume` ở Ngày 50.8) để `co_await async_read(...)` viết như code đồng bộ.
    
*   **So sánh trực tiếp:** Code Ngày 33 (callback lồng nhau) vs code hôm nay (tuyến tính với `co_await`) cho **cùng logic** - thấy rõ giá trị thực tế của Coroutine Frame (Ngày 50.7) ngoài lý thuyết.
    
*   **Cẩn trọng vòng đời:** Coroutine chờ I/O có thể "sống" qua nhiều event loop tick - object nó tham chiếu phải còn tồn tại (liên hệ Dangling View, Ngày 50.6, và RAII Ngày 26).
    

**LAB:** Viết lại TCP echo server Ngày 33 bằng `co_await`, so sánh độ dài/độ rõ code với bản callback. Test với 1000 kết nối đồng thời.

**Câu hỏi:** Vì sao "callback hell" là vấn đề thực sự (không chỉ lý thuyết) khi server cần đọc→xử lý→ghi→đọc tiếp theo nhiều bước? Coroutine Frame (Heap, Ngày 50.7) tồn tại bao lâu trong 1 kết nối TCP kéo dài 10 phút?

### Ngày 35: gRPC & Protocol Buffers trong C++

*Mục tiêu: xây API giữa service - nối lại Template/Generic Programming (Ngày 31-35, Phần 1) qua code sinh tự động.*

*   **Protocol Buffers:** Định nghĩa message trong file `.proto`, `protoc` sinh code C++ (struct + serialize/deserialize) - tương tự cách Template Instantiation (Ngày 31) sinh code cho từng kiểu, nhưng sinh từ file định nghĩa riêng thay vì từ C++ trực tiếp.
    
*   **gRPC service:** Định nghĩa RPC (`rpc GetUser(UserRequest) returns (UserResponse)`), gRPC tự sinh client/server stub. Bên dưới dùng HTTP/2 + Asio-like event loop (Ngày 33-34).
    
*   **Streaming RPC:** gRPC hỗ trợ streaming (client/server/bidirectional) - mô hình gần giống Coroutine generator (`co_yield`, Ngày 50.7) khi server trả nhiều message liên tục.
    

**LAB:** Viết 1 service gRPC đơn giản (`GetUser`) bằng C++, build bằng CMake (Ngày 0) với `protobuf`/`grpc` qua vcpkg. Test bằng client gRPC gọi thử.

**Câu hỏi:** Vì sao Protocol Buffers chọn binary format thay JSON cho performance - liên hệ chi phí parse text (Ngày 1, Preprocessing) so với đọc trực tiếp cấu trúc nhị phân đã biết trước layout (liên hệ Alignment, Ngày 10)?

### Ngày 36: Thiết kế server hiệu năng cao - Connection Pooling & Backpressure

*Mục tiêu: áp dụng toàn bộ kiến thức Concurrency (Ngày 51-55) + Resource Management (Ngày 26-29) vào 1 hệ thống server thật.*

*   **Connection Pool:** Nối lại "socket pool dựa RAII" đã nhắc sơ lược Ngày 29 (Phần 1) - dùng `unique_ptr`/`shared_ptr` (Ngày 27-28) quản lý vòng đời connection, tránh tạo/hủy connection liên tục (chi phí handshake TCP đắt hơn tái sử dụng nhiều).
    
*   **Backpressure:** Khi client gửi nhanh hơn server xử lý được - dùng Bounded Queue (Ring Buffer, Ngày 4 Phần 2 DSA) để giới hạn, từ chối/làm chậm thay vì tràn bộ nhớ.
    
*   **Graceful degradation:** Liên hệ Exception Safety Levels (Ngày 26) - hệ thống dưới tải cao vẫn phải giữ ít nhất "Basic Guarantee" (không leak, không crash), có thể hy sinh throughput.
    

**LAB:** Thêm Connection Pool vào server Ngày 34, giới hạn Bounded Queue 1000 request đang chờ, viết logic từ chối request khi đầy. Load test bằng cách tạo 10.000 kết nối đồng thời, quan sát hành vi.

**Câu hỏi:** Vì sao Connection Pool cần `shared_ptr` (Ngày 28) thay `unique_ptr` nếu 1 connection được nhiều Job (Ngày 34, Track B) cùng truy cập? Backpressure có vi phạm nguyên tắc "phục vụ mọi khách hàng" không, và tại sao đó là đánh đổi đúng?

### Ngày 37: Capstone Track C

*Dự án tổng hợp:* ***"High-Performance Chat Server"*** *dùng Asio + Coroutine + gRPC.*

**Yêu cầu:**

1.  TCP server dùng Asio Coroutine (Ngày 34) nhận kết nối chat client.
    
2.  Connection Pool + Bounded Queue chống backpressure (Ngày 36).
    
3.  1 gRPC service riêng (Ngày 35) cho admin API (xem thống kê kết nối, kick user).
    
4.  Dùng `shared_ptr`/`weak_ptr` (Ngày 28) quản lý danh sách user trong room chat (tránh circular reference giống bài toán Order/Customer Ngày 23, Phần 3).
    
5.  Test bằng Google Test (Ngày 5.5) cho logic room/broadcast, chạy qua ASan/TSan (Ngày 0, 27).
    

**Checklist:** Không tạo thread mới cho mỗi kết nối (dùng Coroutine); Connection Pool tái sử dụng đúng; 0 lỗi sanitizer; chịu được ≥1000 kết nối đồng thời trên 1 máy.

# NGÀY 38-39: TỔNG KẾT & PORTFOLIO

### Ngày 38: Đóng gói Portfolio

*Mục tiêu: biến 3 Capstone (Order Book, Ngày 30, và Capstone Track đã chọn) thành sản phẩm trình bày được.*

*   Đưa cả 2 project qua CI đầy đủ (Ngày 32): build, test, sanitizer, clang-tidy, clang-format.
    
*   Viết `README.md` cho mỗi project: kiến trúc, benchmark số liệu cụ thể (không chỉ nói "nhanh hơn" mà có bảng số `<chrono>` thật), lý do chọn từng design pattern.
    
*   Public lên GitHub, đảm bảo người khác `git clone` + `cmake --build` là chạy được ngay (kiểm tra bằng máy/container sạch, không phụ thuộc cấu hình cá nhân).
    

### Ngày 39: Review tổng & Mock Interview

*   Tự trả lời lại 10 câu hỏi khó nhất trong 122 ngày (chọn từ mỗi giai đoạn: V-Table Ngày 23, Move Semantics Ngày 25, Coroutine Frame Ngày 50.7, ECS/Lock-free/Asio tùy track đã chọn).
    
*   Thực hành giải thích kiến trúc Capstone Track trong 5 phút như đang phỏng vấn - luyện nói rõ **tại sao** chọn thiết kế đó, không chỉ **là gì**.
