# Syllabus software engineering (4)

# Giai đoạn 9 - Security & API Design (Ngày 428–455)

*Giai đoạn mới bổ sung.* Bắt buộc cho Technical Architect - không thể thiết kế hệ thống production mà bỏ qua bảo mật và chuẩn giao tiếp API.

## Nhóm 1: Giới thiệu (Ngày 428–429)

**Ngày 428: Giới thiệu Security & API Design**

*   Mục tiêu: Hiểu vì sao 2 mảng này đi cùng nhau trong 1 giai đoạn.
    
*   Lý thuyết: API là bề mặt tấn công (attack surface) chính của hầu hết hệ thống hiện đại - thiết kế API tốt và bảo mật tốt là 2 mặt của cùng 1 vấn đề.
    
*   Thực hành: Liệt kê toàn bộ API endpoint đã tạo ra ở 3-service project (Giai đoạn 8), đánh giá sơ bộ endpoint nào đang thiếu kiểm soát truy cập.
    

**Ngày 429: Threat Modeling cơ bản - STRIDE**

*   Mục tiêu: Có tư duy hệ thống để tìm ra rủi ro trước khi học từng kỹ thuật cụ thể.
    
*   Lý thuyết: STRIDE - Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege.
    
*   Thực hành: Áp STRIDE vào flow đặt hàng (Order → Payment → Inventory) của project Giai đoạn 8, liệt kê ít nhất 1 rủi ro cho mỗi chữ cái trong STRIDE.
    

## Nhóm 2: Authentication & Authorization (Ngày 430–437)

**Ngày 430: Authentication vs Authorization**

*   Mục tiêu: Phân biệt rạch ròi 2 khái niệm hay bị gộp chung.
    
*   Lý thuyết: Authentication (AuthN) trả lời "bạn là ai", Authorization (AuthZ) trả lời "bạn được phép làm gì" - luôn AuthN trước, AuthZ sau.
    
*   Thực hành: Với API `DELETE /order/{id}`, liệt kê rõ bước nào thuộc AuthN, bước nào thuộc AuthZ.
    

**Ngày 431: Password Hashing**

*   Mục tiêu: Hiểu cách lưu trữ password an toàn.
    
*   Lý thuyết: Không bao giờ lưu plaintext hay hash nhanh (MD5/SHA1); dùng thuật toán hash chậm có salt (bcrypt, argon2) để chống brute-force/rainbow table.
    
*   Thực hành: Viết ví dụ hash password bằng bcrypt, verify password nhập vào, giải thích vì sao cùng 1 password cho ra hash khác nhau mỗi lần (salt).
    

**Ngày 432: Session-based Authentication**

*   Mục tiêu: Hiểu cơ chế auth truyền thống dựa trên session.
    
*   Lý thuyết: Server tạo session sau khi login, lưu session ID vào cookie, session data lưu ở server (memory/Redis) - stateful.
    
*   Thực hành: Thiết kế flow login bằng session cho Mini Web Framework (Giai đoạn 3): tạo session, set cookie, middleware kiểm tra session ở request sau.
    

**Ngày 433: Token-based Authentication - JWT**

*   Mục tiêu: Hiểu cơ chế auth phổ biến trong hệ thống phân tán hiện đại.
    
*   Lý thuyết: JWT gồm 3 phần (Header.Payload.Signature), stateless - server không cần lưu session, chỉ cần verify signature.
    
*   Thực hành: Decode 1 JWT thật (dùng jwt.io hoặc thủ công base64-decode), chỉ ra rõ 3 phần và ý nghĩa của claim `exp`/`iat`/`sub`.
    

**Ngày 434: JWT - Lỗ hổng phổ biến**

*   Mục tiêu: Hiểu các sai lầm thực tế khi implement JWT.
    
*   Lý thuyết: Lỗ hổng `alg: none` (chấp nhận token không ký), dùng secret yếu, không kiểm tra `exp`, không có cơ chế thu hồi (revoke) token - và giải pháp refresh token để giảm thời gian sống của access token.
    
*   Thực hành: Viết checklist bảo mật JWT (5-7 mục) để tự review khi implement.
    

**Ngày 435: OAuth2 - Authorization Code Flow**

*   Mục tiêu: Hiểu flow OAuth2 phổ biến nhất, dùng cho web app truyền thống.
    
*   Lý thuyết: Authorization Code Flow - client redirect user tới Authorization Server, nhận code, đổi code lấy token ở backend (không lộ token ở frontend/URL).
    
*   Thực hành: Vẽ sơ đồ tuần tự đầy đủ Authorization Code Flow (User → Client → Authorization Server → Client → Resource Server).
    

**Ngày 436: OAuth2 - Các Flow khác**

*   Mục tiêu: Biết chọn đúng flow cho đúng loại client.
    
*   Lý thuyết: Client Credentials Flow (service-to-service, không có user), Authorization Code + PKCE (mobile/SPA, không có backend an toàn để giữ client secret).
    
*   Thực hành: Với 3-service project (Giai đoạn 8), xác định flow OAuth2 phù hợp cho: (a) Saga Orchestrator gọi Payment Service, (b) 1 mobile app gọi Order Service thay mặt user.
    

**Ngày 437: mTLS & Lab - Thiết kế Auth cho 3-Service Project**

*   Mục tiêu: Học cơ chế auth dành riêng cho giao tiếp service-to-service.
    
*   Lý thuyết: Mutual TLS - cả client và server đều xác thực certificate của nhau (khác TLS thông thường chỉ server có certificate) - phổ biến trong service mesh.
    
*   Thực hành: Thiết kế đầy đủ chiến lược auth cho 3-service project Giai đoạn 8: JWT cho end-user gọi vào Order Service, mTLS hoặc Client Credentials cho giao tiếp nội bộ giữa Order/Payment/Inventory.
    

## Nhóm 3: OWASP Top 10 (Ngày 438–443)

**Ngày 438: OWASP Top 10 - Tổng quan**

*   Mục tiêu: Có danh sách rủi ro bảo mật phổ biến nhất làm checklist tham chiếu.
    
*   Lý thuyết: OWASP Top 10 là danh sách 10 rủi ro bảo mật web phổ biến nhất, cập nhật định kỳ dựa trên dữ liệu thực tế từ cộng đồng bảo mật.
    
*   Thực hành: Đọc danh sách OWASP Top 10 phiên bản mới nhất, ghi chú lại 3 mục liên quan trực tiếp nhất tới 3-service project đã xây.
    

**Ngày 439: Injection**

*   Mục tiêu: Hiểu và phòng chống lỗ hổng injection kinh điển nhất.
    
*   Lý thuyết: SQL Injection xảy ra khi nối chuỗi trực tiếp input người dùng vào câu query - phòng chống bằng parameterized query/prepared statement.
    
*   Thực hành: Viết 1 ví dụ code có lỗ hổng SQL Injection (nối chuỗi trực tiếp), sửa lại bằng parameterized query, minh hoạ input `' OR '1'='1` bị vô hiệu hoá sau khi sửa.
    

**Ngày 440: Broken Access Control**

*   Mục tiêu: Nhận diện lỗ hổng phổ biến thứ 2, thường bị bỏ sót nhất.
    
*   Lý thuyết: IDOR (Insecure Direct Object Reference) - API cho phép truy cập tài nguyên của người khác chỉ bằng cách đổi ID trong URL, do thiếu kiểm tra ownership.
    
*   Thực hành: Rà lại API `GET /order/{id}` của Order Service (Giai đoạn 8), kiểm tra có đang thiếu bước verify order đó thuộc về user đang gọi hay không, sửa nếu thiếu.
    

**Ngày 441: Cryptographic Failures**

*   Mục tiêu: Hiểu rủi ro khi tự chế cơ chế mã hoá.
    
*   Lý thuyết: Lỗi thường gặp: tự viết thuật toán mã hoá riêng, dùng thuật toán cũ (MD5/SHA1 cho mật khẩu), không dùng HTTPS cho dữ liệu nhạy cảm - nguyên tắc chung: dùng thư viện/thuật toán đã được kiểm chứng, không tự phát minh.
    
*   Thực hành: Rà soát toàn bộ project Giai đoạn 7-8, liệt kê nơi nào có dữ liệu nhạy cảm (password, thông tin thanh toán) và cách đang bảo vệ chúng.
    

**Ngày 442: XSS & CSRF**

*   Mục tiêu: Hiểu 2 lỗ hổng phổ biến ở tầng web (dù project hiện tại là API, vẫn cần biết cho các service có UI).
    
*   Lý thuyết: XSS (Cross-Site Scripting) - chèn script độc hại vào trang hiển thị cho user khác; CSRF (Cross-Site Request Forgery) - lừa user đã login thực hiện hành động ngoài ý muốn qua request giả mạo.
    
*   Thực hành: Viết ví dụ minh hoạ 1 input không được escape gây XSS, và giải thích cách CSRF token ngăn CSRF.
    

**Ngày 443: Lab - Security Review**

*   Mục tiêu: Áp dụng toàn bộ OWASP Top 10 đã học vào project thật.
    
*   Lý thuyết: Ôn lại toàn bộ 5 mục đã học (Injection, Broken Access Control, Cryptographic Failures, XSS, CSRF).
    
*   Thực hành: Viết security review report đầy đủ cho Mini Web Framework (Giai đoạn 3) và 3-service project (Giai đoạn 8), liệt kê lỗ hổng tìm thấy và đề xuất fix.
    

## Nhóm 4: Secrets Management & Encryption (Ngày 444–447)

**Ngày 444: Secrets Management**

*   Mục tiêu: Hiểu vì sao hardcode secret trong code là sai lầm nghiêm trọng.
    
*   Lý thuyết: Secret (API key, database password, JWT signing key) không bao giờ commit vào source control - dùng biến môi trường tối thiểu, hoặc secret manager chuyên dụng (Vault, AWS Secrets Manager) cho production.
    
*   Thực hành: Rà lại 3-service project, tìm bất kỳ secret nào đang hardcode, chuyển sang đọc từ biến môi trường.
    

**Ngày 445: Encryption cơ bản - Symmetric vs Asymmetric**

*   Mục tiêu: Ôn và củng cố kiến thức đã chạm ở Giai đoạn 6 (TLS).
    
*   Lý thuyết: Symmetric encryption (1 khoá dùng chung, nhanh, dùng cho dữ liệu lớn) vs Asymmetric encryption (khoá công khai/riêng tư, chậm hơn, dùng để trao đổi khoá hoặc ký số).
    
*   Thực hành: Lập bảng so sánh 2 loại, liên hệ lại với TLS handshake đã học Ngày 281 (dùng cả 2 loại kết hợp).
    

**Ngày 446: Encryption at Rest vs In Transit**

*   Mục tiêu: Hiểu 2 phạm vi bảo vệ dữ liệu khác nhau, cần cả 2.
    
*   Lý thuyết: Encryption in transit (TLS, bảo vệ dữ liệu khi di chuyển qua mạng) vs Encryption at rest (mã hoá dữ liệu khi lưu trên đĩa/database) - thiếu 1 trong 2 vẫn để lộ rủi ro.
    
*   Thực hành: Với dữ liệu payment trong project Giai đoạn 7-8, xác định dữ liệu nào cần encryption at rest (VD: thông tin thẻ nếu có lưu), dữ liệu nào chỉ cần in transit là đủ.
    

**Ngày 447: Lab - Implement Secrets Management**

*   Mục tiêu: Hoàn thiện thực hành cho project.
    
*   Lý thuyết: Ôn lại nguyên tắc "principle of least privilege" - mỗi service chỉ nên truy cập được secret nó thực sự cần.
    
*   Thực hành: Thiết lập biến môi trường cho từng service trong 3-service project (database credentials, JWT signing key), verify không còn secret nào hardcode trong source.
    

## Nhóm 5: API Design (Ngày 448–451)

**Ngày 448: REST Maturity Model**

*   Mục tiêu: Hiểu các cấp độ trưởng thành của 1 REST API.
    
*   Lý thuyết: Richardson Maturity Model - Level 0 (RPC qua HTTP, 1 endpoint duy nhất), Level 1 (nhiều resource/URI), Level 2 (dùng đúng HTTP verb + status code), Level 3 (HATEOAS - response chứa link tới hành động tiếp theo).
    
*   Thực hành: Đánh giá API của Order Service (Giai đoạn 8) đang ở level nào, đề xuất cải thiện lên level tiếp theo.
    

**Ngày 449: API Versioning**

*   Mục tiêu: Hiểu cách quản lý thay đổi API mà không phá vỡ client cũ.
    
*   Lý thuyết: URI versioning (`/v1/orders`), header versioning (`Accept: application/vnd.api.v1+json`), so sánh ưu nhược từng cách.
    
*   Thực hành: Thiết kế chiến lược versioning cho Order Service, áp dụng thử 1 thay đổi breaking change (VD: đổi format response) sang version mới mà không phá client cũ.
    

**Ngày 450: Idempotency**

*   Mục tiêu: Hiểu khái niệm cực kỳ quan trọng cho API thanh toán.
    
*   Lý thuyết: Idempotency key - client gửi kèm 1 key duy nhất cho mỗi request, server đảm bảo dù request bị gửi lại nhiều lần (do retry mạng) vẫn chỉ xử lý 1 lần - bắt buộc cho API `ChargePayment`.
    
*   Thực hành: Thiết kế cơ chế idempotency key cho `POST /payment/charge` (Payment Service, Giai đoạn 8): lưu key đã xử lý, trả về kết quả cũ nếu key trùng thay vì charge lại.
    

**Ngày 451: Lab - Thiết kế lại API theo REST Best Practice**

*   Mục tiêu: Áp dụng toàn bộ Ngày 448-450 vào project thật.
    
*   Lý thuyết: Ôn lại toàn bộ nguyên tắc đã học.
    
*   Thực hành: Thiết kế lại đầy đủ API cho Order Service và Payment Service: đúng HTTP verb/status code, có versioning, `POST /payment/charge` có idempotency key.
    

## Nhóm 6: gRPC & GraphQL (Ngày 452–454)

**Ngày 452: gRPC & Protobuf**

*   Mục tiêu: Biết lựa chọn thay thế REST cho giao tiếp nội bộ.
    
*   Lý thuyết: gRPC dùng HTTP/2 (đã học Giai đoạn 6) + Protocol Buffers (binary, nhanh hơn JSON, có schema tường minh) - phù hợp giao tiếp service-to-service tốc độ cao.
    
*   Thực hành: Viết 1 file `.proto` định nghĩa service `PaymentService` với method `ChargePayment`, generate code và thử gọi thử.
    

**Ngày 453: GraphQL**

*   Mục tiêu: Biết lựa chọn thay thế REST cho client cần linh hoạt truy vấn dữ liệu.
    
*   Lý thuyết: GraphQL cho phép client tự định nghĩa chính xác field cần lấy (tránh over-fetching/under-fetching của REST), đánh đổi bằng độ phức tạp ở server (resolver, N+1 query problem).
    
*   Thực hành: Thiết kế 1 GraphQL schema đơn giản cho việc truy vấn `Order` kèm thông tin `Payment` liên quan (mà REST cần 2 request riêng).
    

**Ngày 454: Lab - So sánh REST vs gRPC**

*   Mục tiêu: Có trải nghiệm thực tế để so sánh, không chỉ lý thuyết.
    
*   Lý thuyết: Ôn lại tình huống nào nên chọn REST (public API, cần dễ đọc/debug), gRPC (nội bộ, hiệu năng cao), GraphQL (client cần linh hoạt truy vấn).
    
*   Thực hành: Implement cùng 1 endpoint `GetOrderDetail` bằng cả REST và gRPC, so sánh độ dài code, tốc độ, độ dễ debug (đọc payload).
    

## Nhóm 7: Review (Ngày 455)

**Ngày 455: Review & Retrospective Giai đoạn 9**

*   Mục tiêu: Tổng kết toàn bộ Security & API Design.
    
*   Lý thuyết: Nhìn lại toàn bộ chuỗi: Threat Modeling → AuthN/AuthZ → OWASP Top 10 → Secrets/Encryption → API Design chuẩn → giao thức thay thế (gRPC/GraphQL).
    
*   Thực hành: Viết "Security & API Design Checklist" cá nhân (1 trang) sẽ dùng để review mọi API mới trước khi đưa vào production.
    

* * *

# Giai đoạn 10 - Framework Internals (Ngày 456–581)

Giai đoạn dài nhất trong roadmap. Bắt đầu đọc source code thật thay vì chỉ học lý thuyết - 3 track song song theo 3 ngôn ngữ.

## Nhóm 1: Giới thiệu (Ngày 456–457)

**Ngày 456: Giới thiệu Framework Internals**

*   Mục tiêu: Chuyển tư duy từ "dùng framework" sang "hiểu framework hoạt động thế nào".
    
*   Lý thuyết: Mọi framework lớn (Spring, FastAPI, gRPC) đều xây dựng từ chính những khái niệm đã học ở các giai đoạn trước (DI = Factory/Builder pattern, MVC = Chain of Responsibility, ORM = Repository/Unit of Work).
    
*   Thực hành: Với 1 framework bạn dùng hàng ngày, viết ra 3 pattern/khái niệm đã học trước đó mà bạn đoán framework đó đang dùng bên trong.
    

**Ngày 457: Cách đọc Source Code hiệu quả**

*   Mục tiêu: Có phương pháp trước khi lao vào đọc hàng nghìn dòng code.
    
*   Lý thuyết: Đọc từ entry point (constructor chính/hàm khởi tạo), dùng debugger để trace luồng thực thi thay vì đọc tuyến tính, tập trung vào 20% code core trước khi đọc edge case.
    
*   Thực hành: Clone 1 framework sẽ học trong giai đoạn này (khuyến nghị Spring), tìm entry point chính, đặt breakpoint và chạy thử 1 ví dụ đơn giản nhất.
    

## PHẦN A: JAVA TRACK - SPRING (Ngày 458–507)

### Spring Core (Ngày 458–467)

**Ngày 458: Giới thiệu Spring Framework - IoC Container**

*   Mục tiêu: Hiểu ý tưởng trung tâm của Spring.
    
*   Lý thuyết: Inversion of Control - thay vì code tự tạo dependency (`new`), container tạo và inject vào - chính là Dependency Injection đã học ở Giai đoạn 3 (Mini Web Framework) được hiện thực hoá đầy đủ.
    
*   Thực hành: So sánh `Container` đã viết ở Giai đoạn 3 với khái niệm IoC Container của Spring, liệt kê điểm giống nhau.
    

**Ngày 459: BeanFactory**

*   Mục tiêu: Hiểu interface gốc, đơn giản nhất của Spring container.
    
*   Lý thuyết: `BeanFactory` cung cấp API cơ bản: `getBean()`, lazy initialization theo mặc định.
    
*   Thực hành: Đọc Javadoc/source `BeanFactory` interface, liệt kê các method chính và mục đích.
    

**Ngày 460: ApplicationContext**

*   Mục tiêu: Hiểu interface mở rộng được dùng thực tế nhiều hơn.
    
*   Lý thuyết: `ApplicationContext` kế thừa `BeanFactory`, thêm: event publishing, internationalization, eager initialization theo mặc định.
    
*   Thực hành: Lập bảng so sánh `BeanFactory` vs `ApplicationContext`, khi nào Spring khuyến nghị dùng cái nào.
    

**Ngày 461: Bean Definition**

*   Mục tiêu: Hiểu cách Spring biết "công thức" tạo ra 1 bean.
    
*   Lý thuyết: `BeanDefinition` chứa metadata (class, scope, dependency, lifecycle callback) - được tạo ra từ XML config, annotation, hoặc Java config, tất cả quy về cùng 1 cấu trúc dữ liệu nội bộ.
    
*   Thực hành: Viết 1 bean bằng `@Component` và 1 bean bằng Java Config (`@Bean`), giải thích cả 2 đều sinh ra `BeanDefinition` tương đương.
    

**Ngày 462: Bean Scope**

*   Mục tiêu: Hiểu vòng đời khác nhau của bean tuỳ theo scope.
    
*   Lý thuyết: `singleton` (mặc định, 1 instance duy nhất), `prototype` (tạo mới mỗi lần request), `request`/`session` (web-specific).
    
*   Thực hành: Viết 2 bean cùng class nhưng khác scope (`singleton` và `prototype`), verify qua code lấy bean 2 lần và so sánh reference.
    

**Ngày 463: Bean Lifecycle**

*   Mục tiêu: Hiểu toàn bộ vòng đời từ lúc tạo tới lúc huỷ bean.
    
*   Lý thuyết: Instantiate → Populate properties (DI) → `@PostConstruct`/`InitializingBean` → sẵn sàng dùng → `@PreDestroy`/`DisposableBean` khi container đóng.
    
*   Thực hành: Viết 1 bean có đầy đủ callback lifecycle, in log ở mỗi bước, verify thứ tự gọi khi start/stop `ApplicationContext`.
    

**Ngày 464: BeanPostProcessor**

*   Mục tiêu: Hiểu extension point mạnh nhất của Spring container.
    
*   Lý thuyết: `BeanPostProcessor` cho phép can thiệp vào bean ngay trước/sau lúc initialization - đây chính là cơ chế Spring dùng để implement AOP (sẽ học sau) và nhiều annotation khác.
    
*   Thực hành: Viết 1 `BeanPostProcessor` tuỳ chỉnh in log tên mọi bean được tạo ra trong container.
    

**Ngày 465: Lab - Đọc Source** `ApplicationContext.refresh()`

*   Mục tiêu: Đọc thẳng vào trái tim của Spring container (đã đơn giản hoá).
    
*   Lý thuyết: `refresh()` là method trung tâm: đọc bean definition → tạo `BeanFactory` → chạy `BeanFactoryPostProcessor` → đăng ký `BeanPostProcessor` → khởi tạo toàn bộ singleton bean.
    
*   Thực hành: Đọc source `AbstractApplicationContext.refresh()` (bỏ qua chi tiết phức tạp), vẽ lại sơ đồ các bước chính theo đúng thứ tự.
    

**Ngày 466: Lab - Viết Mini BeanFactory**

*   Mục tiêu: Bắt đầu xây Mini Spring - bước nền tảng đầu tiên.
    
*   Lý thuyết: Ôn lại toàn bộ Bean Definition, Scope, Lifecycle đã học.
    
*   Thực hành: Cài đặt `MiniBeanFactory` với `registerBean(name, class)`, `getBean(name)`, hỗ trợ scope singleton, gọi `@PostConstruct` nếu có.
    

**Ngày 467: Review Spring Core**

*   Mục tiêu: Củng cố nhóm kiến thức nền tảng nhất của Spring.
    
*   Lý thuyết: Tổng hợp lại: BeanFactory → ApplicationContext → BeanDefinition → Scope → Lifecycle → BeanPostProcessor.
    
*   Thực hành: Vẽ sơ đồ tổng thể quan hệ giữa các khái niệm vừa học.
    

### Spring DI (Ngày 468–475)

**Ngày 468: Dependency Injection trong Spring**

*   Mục tiêu: Hiểu 3 cách inject dependency và tradeoff.
    
*   Lý thuyết: Constructor injection (khuyến nghị - dependency bắt buộc, immutable), Setter injection (dependency optional), Field injection (ngắn gọn nhưng khó test, không khuyến nghị).
    
*   Thực hành: Viết cùng 1 bean bằng cả 3 cách injection, giải thích vì sao Field injection khó viết unit test hơn.
    

**Ngày 469: @Autowired - Cách Spring Resolve Dependency**

*   Mục tiêu: Hiểu cơ chế tự động tìm bean phù hợp.
    
*   Lý thuyết: `@Autowired` tìm bean theo type trước, nếu có nhiều candidate cùng type thì tìm theo tên field/parameter.
    
*   Thực hành: Viết ví dụ 2 bean cùng implement 1 interface, quan sát lỗi `NoUniqueBeanDefinitionException` khi Spring không biết chọn bean nào.
    

**Ngày 470: @Qualifier & @Primary**

*   Mục tiêu: Học cách giải quyết ambiguity ở Ngày 469.
    
*   Lý thuyết: `@Primary` đánh dấu bean ưu tiên mặc định; `@Qualifier` chỉ định chính xác bean cần inject theo tên.
    
*   Thực hành: Sửa lỗi ở Ngày 469 bằng cả 2 cách, so sánh khi nào nên dùng cách nào.
    

**Ngày 471: Circular Dependency**

*   Mục tiêu: Hiểu vấn đề thực tế hay gặp và cách Spring xử lý.
    
*   Lý thuyết: Circular dependency (A cần B, B cần A) - Spring xử lý được với setter/field injection qua cơ chế 3-level cache (early bean reference), nhưng KHÔNG xử lý được với constructor injection thuần.
    
*   Thực hành: Viết ví dụ 2 bean phụ thuộc vòng tròn qua constructor injection, quan sát lỗi Spring ném ra; sửa bằng setter injection để thấy Spring xử lý được.
    

**Ngày 472: Stereotype Annotation**

*   Mục tiêu: Hiểu ý nghĩa ngữ nghĩa đằng sau các annotation quen thuộc.
    
*   Lý thuyết: `@Component` (annotation gốc), `@Service`/`@Repository`/`@Controller` là chuyên biệt hoá của `@Component` mang ý nghĩa kiến trúc (liên hệ Layered Architecture đã học Giai đoạn 8), về bản chất kỹ thuật hoạt động giống nhau.
    
*   Thực hành: Đọc source annotation `@Service`, chỉ ra nó chỉ là `@Component` được "meta-annotate" thêm.
    

**Ngày 473: Component Scanning**

*   Mục tiêu: Hiểu cách Spring tự động tìm thấy bean mà không cần khai báo thủ công từng cái.
    
*   Lý thuyết: `@ComponentScan` quét package, dùng classpath scanning để tìm class có stereotype annotation, tự động đăng ký `BeanDefinition`.
    
*   Thực hành: Viết ví dụ 3 bean ở 3 package khác nhau, verify `@ComponentScan` tìm thấy đủ cả 3.
    

**Ngày 474: Lab - Implement Autowiring cho Mini Spring**

*   Mục tiêu: Nâng cấp Mini Spring đã bắt đầu ở Ngày 466.
    
*   Lý thuyết: Ôn lại: dùng reflection để tìm constructor/field cần inject, resolve bean theo type từ `MiniBeanFactory`.
    
*   Thực hành: Thêm khả năng auto-wire constructor injection vào `MiniBeanFactory`, hỗ trợ resolve dependency lồng nhau (bean A cần bean B, bean B cần bean C).
    

**Ngày 475: Review Spring DI**

*   Mục tiêu: Củng cố nhóm DI.
    
*   Lý thuyết: Tổng hợp lại: 3 cách injection, cơ chế resolve, circular dependency, component scanning.
    
*   Thực hành: Viết checklist các lỗi DI thường gặp và cách chẩn đoán (dựa trên các ví dụ đã làm trong tuần).
    

### Spring AOP (Ngày 476–483)

**Ngày 476: AOP - Giới thiệu**

*   Mục tiêu: Hiểu vấn đề cross-cutting concern mà AOP giải quyết.
    
*   Lý thuyết: Cross-cutting concern (logging, transaction, security) là logic lặp lại xuyên suốt nhiều class không liên quan nhau - AOP cho phép tách logic này ra riêng thay vì rải khắp code (liên hệ Decorator/Proxy pattern đã học Giai đoạn 3).
    
*   Thực hành: Tìm 1 ví dụ trong 3-service project (Giai đoạn 8) nơi logging/transaction logic đang lặp lại ở nhiều method, đánh dấu để refactor sau.
    

**Ngày 477: Proxy-based AOP**

*   Mục tiêu: Hiểu cơ chế kỹ thuật đứng sau AOP của Spring.
    
*   Lý thuyết: Spring AOP dùng runtime proxy - JDK Dynamic Proxy (khi bean implement interface) hoặc CGLIB (subclass, khi bean không có interface) - chính là Proxy pattern đã học, áp dụng tự động.
    
*   Thực hành: Viết 1 bean có interface và 1 bean không có interface, verify (qua log hoặc debug) Spring tạo loại proxy khác nhau cho mỗi trường hợp.
    

**Ngày 478: Pointcut & Advice**

*   Mục tiêu: Hiểu 2 khái niệm cốt lõi của AOP.
    
*   Lý thuyết: Pointcut định nghĩa "ở đâu" áp dụng logic xen vào (VD: mọi method trong package `service`), Advice định nghĩa "logic gì" sẽ chạy tại điểm đó.
    
*   Thực hành: Viết 1 pointcut expression match mọi method bắt đầu bằng `save`, giải thích cú pháp AspectJ pointcut expression cơ bản.
    

**Ngày 479: @Around/@Before/@After**

*   Mục tiêu: Thực hành các loại advice phổ biến.
    
*   Lý thuyết: `@Before` (chạy trước), `@After` (chạy sau, dù thành công hay lỗi), `@Around` (kiểm soát hoàn toàn, có thể chặn không cho method gốc chạy).
    
*   Thực hành: Viết 1 Aspect log thời gian thực thi method bằng `@Around`.
    

**Ngày 480: AOP Use Case Thực Tế**

*   Mục tiêu: Thấy AOP được dùng ở đâu trong framework thật.
    
*   Lý thuyết: `@Transactional` (transaction management), `@Secured` (security check), logging framework - đều implement bằng AOP đứng sau annotation.
    
*   Thực hành: Đọc source `@Transactional` implementation ở mức tổng quan, giải thích nó dùng `@Around` advice để bọc method trong transaction begin/commit/rollback.
    

**Ngày 481: Lab - Implement Transaction Management bằng AOP**

*   Mục tiêu: Tự tay implement 1 use case AOP thực tế.
    
*   Lý thuyết: Ôn lại `@Around` advice có thể bắt exception và quyết định rollback.
    
*   Thực hành: Viết `@MyTransactional` annotation tự chế + Aspect xử lý: bắt đầu transaction trước method, commit nếu thành công, rollback nếu có exception.
    

**Ngày 482: Lab - Mini AOP Proxy cho Mini Spring**

*   Mục tiêu: Tích hợp AOP vào Mini Spring đang xây.
    
*   Lý thuyết: Ôn lại JDK Dynamic Proxy - cách tạo proxy runtime bằng `java.lang.reflect.Proxy`.
    
*   Thực hành: Thêm khả năng tạo proxy tự động cho bean có annotation tuỳ chỉnh (VD: `@LogExecutionTime`) vào `MiniBeanFactory`.
    

**Ngày 483: Review Spring AOP**

*   Mục tiêu: Củng cố nhóm AOP.
    
*   Lý thuyết: Tổng hợp lại: Proxy-based mechanism, Pointcut/Advice, use case thực tế, giới hạn (AOP chỉ áp dụng được cho method public, không áp dụng được khi gọi method nội bộ trong cùng class).
    
*   Thực hành: Viết ví dụ minh hoạ giới hạn "self-invocation" của Spring AOP (gọi method có `@Transactional` từ chính method khác trong cùng bean sẽ không kích hoạt AOP).
    

### Spring MVC (Ngày 484–491)

**Ngày 484: DispatcherServlet - Front Controller Pattern**

*   Mục tiêu: Hiểu điểm vào trung tâm của mọi request trong Spring MVC.
    
*   Lý thuyết: Front Controller pattern - mọi request đi qua 1 servlet trung tâm (`DispatcherServlet`), sau đó được định tuyến tới đúng handler - tương tự Router đã xây ở Giai đoạn 3.
    
*   Thực hành: Vẽ sơ đồ luồng request đi qua `DispatcherServlet` tới khi trả response, so sánh với luồng của Mini Web Framework đã xây.
    

**Ngày 485: @Controller & @RequestMapping**

*   Mục tiêu: Hiểu cách khai báo route trong Spring MVC.
    
*   Lý thuyết: `@Controller` đánh dấu class xử lý web request, `@RequestMapping`/`@GetMapping`/`@PostMapping` khai báo route + HTTP method.
    
*   Thực hành: Viết 1 `@RestController` với vài endpoint CRUD đơn giản.
    

**Ngày 486: HandlerMapping & HandlerAdapter**

*   Mục tiêu: Hiểu cơ chế bên trong `DispatcherServlet` tìm và gọi đúng handler.
    
*   Lý thuyết: `HandlerMapping` tìm handler phù hợp với request (dựa trên URL/method), `HandlerAdapter` biết cách gọi handler đó (vì handler có thể có nhiều dạng khác nhau).
    
*   Thực hành: Đọc source `RequestMappingHandlerMapping` ở mức tổng quan, giải thích cách nó match URL pattern với path param.
    

**Ngày 487: Model-View-Controller Flow đầy đủ**

*   Mục tiêu: Hiểu toàn bộ vòng đời xử lý 1 request MVC.
    
*   Lý thuyết: Request → DispatcherServlet → HandlerMapping tìm Controller → Controller xử lý, trả Model → ViewResolver tìm View → View render response.
    
*   Thực hành: Vẽ sơ đồ tuần tự đầy đủ cho 1 request cụ thể qua toàn bộ MVC flow.
    

**Ngày 488: Exception Handling**

*   Mục tiêu: Hiểu cách Spring MVC xử lý lỗi tập trung.
    
*   Lý thuyết: `@ExceptionHandler`/`@ControllerAdvice` cho phép xử lý exception tập trung thay vì try-catch rải rác ở từng controller.
    
*   Thực hành: Viết `@ControllerAdvice` xử lý tập trung cho các exception nghiệp vụ (VD: `OrderNotFoundException` → trả 404).
    

**Ngày 489: Interceptor**

*   Mục tiêu: Liên hệ lại Chain of Responsibility/Middleware đã học.
    
*   Lý thuyết: `HandlerInterceptor` với `preHandle`/`postHandle`/`afterCompletion` - chính là middleware pattern đã implement ở Mini Web Framework Giai đoạn 3.
    
*   Thực hành: Viết 1 Interceptor log thời gian xử lý mỗi request, so sánh cấu trúc với `MiddlewarePipeline` đã viết trước đó.
    

**Ngày 490: Lab - Mini MVC Layer cho Mini Spring**

*   Mục tiêu: Ghép Mini Spring với khả năng xử lý HTTP.
    
*   Lý thuyết: Ôn lại toàn bộ luồng DispatcherServlet → HandlerMapping → Controller.
    
*   Thực hành: Thêm khả năng route HTTP request tới đúng bean có annotation `@MiniController` trong `MiniBeanFactory`.
    

**Ngày 491: Review Spring MVC**

*   Mục tiêu: Củng cố nhóm MVC.
    
*   Lý thuyết: Tổng hợp lại toàn bộ flow và liên hệ với Mini Web Framework (Giai đoạn 3) đã xây trước đó - thấy rõ Spring MVC chỉ là phiên bản trưởng thành hơn của cùng ý tưởng.
    
*   Thực hành: Viết bảng ánh xạ: mỗi thành phần Spring MVC tương ứng thành phần nào trong Mini Web Framework tự viết.
    

### Spring Data (Ngày 492–499)

**Ngày 492: Spring Data JPA - Giới thiệu**

*   Mục tiêu: Hiểu cách Spring Data trừu tượng hoá persistence layer.
    
*   Lý thuyết: Spring Data JPA implement Repository pattern (đã học Giai đoạn 7) tự động - chỉ cần khai báo interface, Spring tự sinh implementation lúc runtime bằng dynamic proxy.
    
*   Thực hành: Viết interface `OrderRepository extends JpaRepository<Order, Long>`, không viết implementation, verify vẫn gọi được `save()`/`findById()`.
    

**Ngày 493: Query Method tự động**

*   Mục tiêu: Hiểu cách Spring Data "đọc hiểu" tên method để sinh query.
    
*   Lý thuyết: `findByStatusAndCustomerId(...)` được Spring Data parse tên method thành query tương ứng, không cần viết SQL.
    
*   Thực hành: Viết 3 query method theo convention (VD: `findByStatus`, `findByCreatedAtAfter`), verify Spring Data sinh đúng query.
    

**Ngày 494: @Query - Custom Query**

*   Mục tiêu: Học cách viết query phức tạp hơn convention hỗ trợ.
    
*   Lý thuyết: `@Query` cho phép viết JPQL/native SQL trực tiếp khi query method convention không đủ diễn đạt.
    
*   Thực hành: Viết 1 query phức tạp (join nhiều bảng) bằng `@Query`.
    

**Ngày 495: Transaction Management - @Transactional**

*   Mục tiêu: Áp dụng lại AOP đã học (Ngày 480-481) vào ngữ cảnh thực tế.
    
*   Lý thuyết: `@Transactional` của Spring Data hoạt động đúng như Aspect tự viết Ngày 481, với thêm các tuỳ chọn propagation (REQUIRED, REQUIRES\_NEW...) và isolation level.
    
*   Thực hành: Viết 1 method nghiệp vụ có `@Transactional`, cố tình gây lỗi giữa chừng, verify toàn bộ thay đổi được rollback.
    

**Ngày 496: N+1 Query Problem**

*   Mục tiêu: Nhận diện vấn đề hiệu năng kinh điển của ORM.
    
*   Lý thuyết: N+1 xảy ra khi lazy loading gây ra 1 query cho danh sách cha + N query riêng lẻ cho từng con - giải quyết bằng `JOIN FETCH` hoặc `@EntityGraph`.
    
*   Thực hành: Viết ví dụ cố tình gây N+1 (load danh sách Order rồi loop lấy OrderLine), bật SQL logging để đếm số query, sửa bằng `JOIN FETCH`.
    

**Ngày 497: Lab - Áp dụng Spring Data JPA cho Order Service**

*   Mục tiêu: Chuyển Order Service (Giai đoạn 8) từ in-memory repository sang Spring Data JPA thật.
    
*   Lý thuyết: Ôn lại Repository pattern (Giai đoạn 7) - interface không đổi, chỉ đổi implementation.
    
*   Thực hành: Viết `OrderJpaRepository extends JpaRepository`, kết nối với database thật (PostgreSQL), verify Order Service hoạt động đúng với dữ liệu persist thật.
    

**Ngày 498: Lab - Transaction cho Flow Thanh Toán**

*   Mục tiêu: Áp dụng transaction management vào use case quan trọng nhất.
    
*   Lý thuyết: Ôn lại Saga (Giai đoạn 8) xử lý transaction xuyên service, còn `@Transactional` xử lý transaction nội bộ trong 1 service.
    
*   Thực hành: Đảm bảo use case `ChargePayment` trong Payment Service dùng `@Transactional` đúng cách, đặc biệt với logic Event Sourcing/Outbox đã xây (ghi event + ghi aggregate phải cùng transaction).
    

**Ngày 499: Review Spring Data**

*   Mục tiêu: Củng cố nhóm Spring Data.
    
*   Lý thuyết: Tổng hợp lại: Repository abstraction, Query method, N+1 problem, Transaction.
    
*   Thực hành: Viết checklist review cho mọi Repository mới viết trong tương lai (VD: kiểm tra N+1, kiểm tra transaction boundary).
    

### Spring Boot (Ngày 500–503)

**Ngày 500: Auto Configuration**

*   Mục tiêu: Hiểu "phép màu" giúp Spring Boot chạy được với rất ít config.
    
*   Lý thuyết: `@EnableAutoConfiguration` quét classpath, tự động cấu hình bean dựa trên thư viện có sẵn (VD: có `spring-boot-starter-web` trên classpath → tự cấu hình `DispatcherServlet`).
    
*   Thực hành: Đọc 1 class `AutoConfiguration` đơn giản trong source Spring Boot, giải thích điều kiện (`@ConditionalOnClass`) kích hoạt nó.
    

**Ngày 501: Spring Boot Starter**

*   Mục tiêu: Hiểu cách Spring Boot quản lý dependency.
    
*   Lý thuyết: Starter là 1 nhóm dependency đóng gói sẵn cho 1 mục đích (VD: `spring-boot-starter-web` gồm Spring MVC + Tomcat embedded + Jackson).
    
*   Thực hành: Xem file `pom.xml`/`build.gradle` của 1 project Spring Boot thật, liệt kê các starter đang dùng và mục đích của từng cái.
    

**Ngày 502: Spring Boot Actuator**

*   Mục tiêu: Làm quen observability có sẵn (sẽ đào sâu ở Giai đoạn 13).
    
*   Lý thuyết: Actuator cung cấp sẵn endpoint health check, metrics, thông tin runtime - nền tảng cho production monitoring.
    
*   Thực hành: Bật Actuator cho 1 Spring Boot app đơn giản, gọi thử `/actuator/health` và `/actuator/metrics`.
    

**Ngày 503: Review Spring Boot**

*   Mục tiêu: Chốt lại nhóm Spring Boot, kết thúc phần lý thuyết Java Track.
    
*   Lý thuyết: Tổng hợp: Spring Boot không phải framework mới, mà là lớp "convention over configuration" xây trên Spring Core/MVC/Data đã học.
    
*   Thực hành: Viết sơ đồ tổng thể: Spring Core → Spring DI/AOP → Spring MVC/Data → Spring Boot, thể hiện quan hệ xây dựng dần.
    

### Project: Mini Spring (Ngày 504–507)

**Ngày 504: Ghép toàn bộ thành Mini Spring hoàn chỉnh**

*   Mục tiêu: Tổng hợp toàn bộ Java Track thành 1 framework hoàn chỉnh.
    
*   Lý thuyết: Ôn lại tất cả thành phần đã xây rời rạc: `MiniBeanFactory` (Ngày 466), Autowiring (Ngày 474), Mini AOP Proxy (Ngày 482), Mini MVC (Ngày 490).
    
*   Thực hành: Ghép toàn bộ thành 1 package `MiniSpring` thống nhất, đảm bảo các thành phần hoạt động cùng nhau.
    

**Ngày 505: Viết Ứng dụng Demo**

*   Mục tiêu: Kiểm chứng Mini Spring hoạt động với use case thật.
    
*   Lý thuyết: Ôn lại CRUD API đơn giản đã làm nhiều lần trong roadmap.
    
*   Thực hành: Viết 1 ứng dụng CRUD Task chạy hoàn toàn trên Mini Spring (DI + AOP logging + MVC routing).
    

**Ngày 506: Test Mini Spring**

*   Mục tiêu: Đảm bảo framework tự viết đáng tin cậy.
    
*   Lý thuyết: Ôn lại Testing Strategy (Giai đoạn 4) áp dụng cho framework code.
    
*   Thực hành: Viết test cho từng thành phần: bean creation, autowiring, AOP proxy, MVC routing.
    

**Ngày 507: Retrospective Java Track**

*   Mục tiêu: Tổng kết toàn bộ Java Track (50 ngày).
    
*   Lý thuyết: Nhìn lại hành trình từ BeanFactory đơn giản tới Mini Spring hoàn chỉnh, liên hệ với Spring thật.
    
*   Thực hành: Viết báo cáo: những gì Mini Spring còn thiếu so với Spring thật, và tại sao Spring thật cần những phần đó (VD: xử lý nhiều edge case, tối ưu hiệu năng, hỗ trợ nhiều loại config).
    

## PHẦN B: PYTHON TRACK (Ngày 508–545)

### FastAPI (Ngày 508–519)

**Ngày 508: FastAPI - Giới thiệu**

*   Mục tiêu: Hiểu FastAPI được xây trên nền tảng nào.
    
*   Lý thuyết: FastAPI = Starlette (ASGI framework, routing + middleware) + Pydantic (data validation dựa trên type hint).
    
*   Thực hành: Cài đặt FastAPI, chạy thử "Hello World" endpoint, đọc log để thấy Starlette/Uvicorn đứng sau.
    

**Ngày 509: Routing trong FastAPI**

*   Mục tiêu: So sánh với Router đã tự viết ở Giai đoạn 3.
    
*   Lý thuyết: Path operation decorator (`@app.get`), path parameter, query parameter - cú pháp khai báo route hiện đại dựa trên type hint.
    
*   Thực hành: Viết vài endpoint CRUD, so sánh trải nghiệm với `Router` tự viết ở Mini Web Framework.
    

**Ngày 510: Pydantic - Data Validation**

*   Mục tiêu: Hiểu cách FastAPI validate request tự động.
    
*   Lý thuyết: Pydantic model dùng type hint để validate + serialize/deserialize dữ liệu, tự sinh lỗi 422 rõ ràng khi dữ liệu sai.
    
*   Thực hành: Viết Pydantic model cho `Order` request body, verify FastAPI tự trả lỗi validate khi thiếu field bắt buộc.
    

**Ngày 511: Dependency Injection trong FastAPI**

*   Mục tiêu: Thấy DI xuất hiện lại ở 1 framework hoàn toàn khác Spring.
    
*   Lý thuyết: `Depends()` - hàm được gọi trước khi vào endpoint, kết quả được inject vào tham số, tương tự Constructor Injection nhưng theo phong cách function-based.
    
*   Thực hành: Viết 1 dependency function `get_current_user()` dùng `Depends()` để inject vào nhiều endpoint.
    

**Ngày 512: DI nâng cao - Sub-dependency & Scope**

*   Mục tiêu: Hiểu DI trong FastAPI có thể lồng nhau.
    
*   Lý thuyết: Dependency có thể phụ thuộc dependency khác (sub-dependency), FastAPI tự cache kết quả trong phạm vi 1 request.
    
*   Thực hành: Viết `get_db_session()` là dependency của `get_order_repository()`, verify session được tái sử dụng trong cùng request.
    

**Ngày 513: ASGI - So sánh với WSGI**

*   Mục tiêu: Liên hệ lại Concurrency (Giai đoạn 5) và Networking (Giai đoạn 6).
    
*   Lý thuyết: WSGI (đồng bộ, 1 request/1 thread) vs ASGI (bất đồng bộ, dựa trên asyncio event loop) - FastAPI chạy trên ASGI nên tận dụng được `async def` endpoint.
    
*   Thực hành: Viết 1 endpoint đồng bộ (`def`) và 1 endpoint bất đồng bộ (`async def`) gọi I/O, giải thích khi nào FastAPI chạy endpoint đồng bộ trong thread pool riêng để không block event loop.
    

**Ngày 514: Middleware trong FastAPI**

*   Mục tiêu: Liên hệ lại Middleware Pipeline đã xây Giai đoạn 3.
    
*   Lý thuyết: Middleware bọc quanh toàn bộ request/response, tương tự `MiddlewarePipeline` tự viết trước đó.
    
*   Thực hành: Viết middleware log thời gian xử lý mỗi request.
    

**Ngày 515: Background Tasks**

*   Mục tiêu: Học tính năng tiện dụng để xử lý việc không cần block response.
    
*   Lý thuyết: `BackgroundTasks` cho phép chạy 1 tác vụ sau khi đã trả response cho client (VD: gửi email xác nhận).
    
*   Thực hành: Viết endpoint tạo Order trả response ngay, gửi email xác nhận (giả lập) chạy nền bằng `BackgroundTasks`.
    

**Ngày 516: OpenAPI tự động generate**

*   Mục tiêu: Liên hệ lại API Design (Giai đoạn 9).
    
*   Lý thuyết: FastAPI tự sinh OpenAPI spec (Swagger UI) từ chính type hint và Pydantic model, không cần viết doc riêng.
    
*   Thực hành: Chạy app, mở `/docs`, verify toàn bộ endpoint/schema đã khai báo hiện đúng.
    

**Ngày 517: Lab - Viết lại Order Service API bằng FastAPI**

*   Mục tiêu: So sánh trực tiếp với 2 phiên bản đã có (Mini Web Framework Giai đoạn 3, Spring MVC vừa học).
    
*   Lý thuyết: Ôn lại toàn bộ Order Service domain logic (Giai đoạn 7-8) - chỉ cần viết lại API layer.
    
*   Thực hành: Implement lại API layer của Order Service bằng FastAPI, tái sử dụng domain logic đã có.
    

**Ngày 518: Lab - So sánh FastAPI vs Mini Web Framework**

*   Mục tiêu: Đánh giá khách quan công cụ tự viết so với công cụ production-grade.
    
*   Lý thuyết: Ôn lại toàn bộ tính năng đã học ở FastAPI.
    
*   Thực hành: Viết bảng so sánh: những gì Mini Web Framework (Giai đoạn 3) còn thiếu so với FastAPI (validation tự động, OpenAPI, DI nâng cao, ASGI native).
    

**Ngày 519: Review FastAPI**

*   Mục tiêu: Chốt lại nhóm FastAPI.
    
*   Lý thuyết: Tổng hợp: Starlette + Pydantic + ASGI = FastAPI, liên hệ ngược lại toàn bộ Giai đoạn 5 (Concurrency)/6 (Networking)/9 (API Design).
    
*   Thực hành: Viết tổng kết ngắn về triết lý thiết kế của FastAPI (dựa trên type hint, "ít code hơn = ít bug hơn").
    

### SQLAlchemy (Ngày 520–531)

**Ngày 520: SQLAlchemy - Core vs ORM**

*   Mục tiêu: Hiểu SQLAlchemy thực chất có 2 tầng riêng biệt.
    
*   Lý thuyết: SQLAlchemy Core (query builder, gần với SQL) vs SQLAlchemy ORM (xây trên Core, ánh xạ object-relational) - khác với nhiều ORM khác chỉ có 1 tầng.
    
*   Thực hành: Viết cùng 1 query bằng Core (`select()`) và bằng ORM (`session.query()`), so sánh.
    

**Ngày 521: SQLAlchemy Core - Engine & Connection**

*   Mục tiêu: Hiểu tầng thấp nhất quản lý kết nối database.
    
*   Lý thuyết: `Engine` quản lý connection pool, `Connection` là 1 kết nối cụ thể lấy từ pool.
    
*   Thực hành: Tạo `Engine`, chạy raw SQL qua `Connection`, quan sát connection pool qua log.
    

**Ngày 522: SQLAlchemy ORM - Declarative Model**

*   Mục tiêu: Định nghĩa model ánh xạ class ↔ table.
    
*   Lý thuyết: `declarative_base()`, class kế thừa Base tự động map với table qua `__tablename__` và Column.
    
*   Thực hành: Định nghĩa model `Order`/`OrderLine` bằng SQLAlchemy declarative.
    

**Ngày 523: Session - Unit of Work Pattern**

*   Mục tiêu: Hiểu pattern quan trọng nhất của SQLAlchemy ORM.
    
*   Lý thuyết: Unit of Work - `Session` theo dõi mọi thay đổi trên object đã load, gom lại thành 1 transaction khi `commit()`, thay vì ghi database ngay mỗi lần sửa.
    
*   Thực hành: Sửa 1 object đã load qua session, verify database chưa đổi cho tới khi gọi `session.commit()`.
    

**Ngày 524: Identity Map Pattern**

*   Mục tiêu: Hiểu cơ chế đảm bảo tính nhất quán trong 1 session.
    
*   Lý thuyết: Identity Map - trong cùng 1 session, load cùng 1 row 2 lần sẽ trả về cùng 1 object Python (theo reference), tránh tình trạng có 2 object khác nhau đại diện cùng 1 dữ liệu.
    
*   Thực hành: Load cùng 1 `Order` 2 lần trong cùng session bằng `query.get(id)`, verify bằng `is` operator rằng đó là cùng 1 object.
    

**Ngày 525: Relationship**

*   Mục tiêu: Ánh xạ quan hệ giữa các bảng thành quan hệ giữa object.
    
*   Lý thuyết: `relationship()` với `one-to-many`/`many-to-many`, `back_populates` để đồng bộ 2 chiều.
    
*   Thực hành: Thêm relationship `Order.lines` (one-to-many với `OrderLine`), verify truy cập `order.lines` trả về list object tự động.
    

**Ngày 526: Lazy Loading vs Eager Loading**

*   Mục tiêu: Liên hệ lại N+1 problem đã học ở Spring Data (Ngày 496).
    
*   Lý thuyết: Lazy loading (mặc định, load quan hệ khi truy cập) gây N+1; `joinedload()`/`selectinload()` cho eager loading để tránh.
    
*   Thực hành: Viết ví dụ gây N+1 khi load nhiều Order rồi truy cập `lines`, sửa bằng `selectinload()`, đếm số query trước/sau.
    

**Ngày 527: Query - Filter & Join**

*   Mục tiêu: Thành thạo truy vấn phức tạp.
    
*   Lý thuyết: `filter()`, `join()`, kết hợp nhiều điều kiện.
    
*   Thực hành: Viết query tìm tất cả Order có tổng tiền > X, join với Customer để lọc theo email.
    

**Ngày 528: Migration - Alembic**

*   Mục tiêu: Học cách quản lý thay đổi schema theo thời gian.
    
*   Lý thuyết: Alembic tự động sinh migration script dựa trên diff giữa model hiện tại và database, cho phép upgrade/downgrade version.
    
*   Thực hành: Cài Alembic, generate migration đầu tiên cho model `Order`/`OrderLine`, chạy `alembic upgrade head`.
    

**Ngày 529: Lab - Implement Order Model**

*   Mục tiêu: Chuyển toàn bộ Order domain sang SQLAlchemy thật.
    
*   Lý thuyết: Ôn lại toàn bộ khái niệm đã học tuần này.
    
*   Thực hành: Hoàn thiện model `Order`/`OrderLine` với relationship, migration, và các query cần thiết cho Order Service (Python version).
    

**Ngày 530: Lab - Repository Pattern dùng SQLAlchemy**

*   Mục tiêu: Liên hệ lại Repository pattern (Giai đoạn 7).
    
*   Lý thuyết: Ôn lại Repository nên trả về/nhận aggregate hoàn chỉnh, che giấu chi tiết SQLAlchemy Session khỏi domain layer.
    
*   Thực hành: Viết `SqlAlchemyOrderRepository` implement interface `OrderRepository` đã thiết kế ở Giai đoạn 7, verify domain layer không import trực tiếp SQLAlchemy.
    

**Ngày 531: Review SQLAlchemy**

*   Mục tiêu: Củng cố nhóm SQLAlchemy.
    
*   Lý thuyết: Tổng hợp: Core vs ORM, Session (Unit of Work), Identity Map, Relationship, N+1, Migration.
    
*   Thực hành: Viết bảng so sánh SQLAlchemy vs Spring Data JPA (Ngày 492-499) - cả 2 đều implement Unit of Work/Identity Map nhưng cách tiếp cận khác nhau (Session tường minh vs Repository interface tự sinh).
    

### Django ORM (Ngày 532–539)

**Ngày 532: Django ORM - Giới thiệu**

*   Mục tiêu: Làm quen triết lý thiết kế khác biệt so với SQLAlchemy.
    
*   Lý thuyết: Django ORM theo Active Record pattern (object tự biết cách lưu chính nó qua `.save()`), khác SQLAlchemy theo Data Mapper pattern (Session riêng biệt quản lý persistence).
    
*   Thực hành: Viết model `Order` bằng Django ORM, gọi `order.save()` trực tiếp, so sánh với cách gọi `session.add(order)` của SQLAlchemy.
    

**Ngày 533: Model Definition trong Django**

*   Mục tiêu: Thành thạo khai báo model.
    
*   Lý thuyết: `models.Model`, các Field type, `ForeignKey` cho quan hệ.
    
*   Thực hành: Định nghĩa lại `Order`/`OrderLine` bằng Django Model.
    

**Ngày 534: QuerySet - Lazy Evaluation**

*   Mục tiêu: Hiểu cơ chế query đặc trưng của Django.
    
*   Lý thuyết: `QuerySet` là lazy - chỉ thực sự chạy SQL khi được evaluate (iterate, `list()`, `len()`...), cho phép chain nhiều filter mà không tốn query trung gian.
    
*   Thực hành: Viết chain 3 filter liên tiếp trên `QuerySet`, verify chỉ có 1 query SQL được chạy khi in kết quả (dùng Django Debug Toolbar hoặc `query.query`).
    

**Ngày 535: Migration trong Django**

*   Mục tiêu: So sánh với Alembic đã học.
    
*   Lý thuyết: `makemigrations` tự sinh migration file từ thay đổi model, `migrate` áp dụng vào database - tích hợp sẵn trong Django, không cần cài thêm như Alembic.
    
*   Thực hành: Chạy `makemigrations`/`migrate` cho model Ngày 533, so sánh trải nghiệm với Alembic.
    

**Ngày 536: N+1 Problem trong Django**

*   Mục tiêu: Học cách Django giải quyết vấn đề tương tự đã gặp ở Spring Data và SQLAlchemy.
    
*   Lý thuyết: `select_related()` (cho ForeignKey, dùng SQL JOIN) và `prefetch_related()` (cho many-to-many/reverse FK, dùng query riêng rồi join ở Python).
    
*   Thực hành: Viết ví dụ N+1 khi load Order kèm OrderLine, sửa bằng `prefetch_related()`, đếm số query trước/sau.
    

**Ngày 537: So sánh SQLAlchemy vs Django ORM**

*   Mục tiêu: Có tiêu chí chọn lựa rõ ràng cho dự án thực tế.
    
*   Lý thuyết: Active Record (Django, đơn giản, gắn chặt với Django framework) vs Data Mapper (SQLAlchemy, tách biệt persistence khỏi domain model, linh hoạt hơn cho kiến trúc Hexagonal/Clean đã học Giai đoạn 8).
    
*   Thực hành: Lập bảng so sánh, đánh giá: nếu áp dụng Hexagonal Architecture nghiêm ngặt, ORM nào phù hợp hơn và tại sao.
    

**Ngày 538: Lab - Viết lại Order Model bằng Django ORM**

*   Mục tiêu: Có trải nghiệm thực hành trực tiếp để so sánh.
    
*   Lý thuyết: Ôn lại toàn bộ Ngày 532-536.
    
*   Thực hành: Viết lại toàn bộ Order domain bằng Django Model + QuerySet, so với bản SQLAlchemy đã làm Ngày 529.
    

**Ngày 539: Review Django ORM**

*   Mục tiêu: Chốt lại nhóm Django ORM.
    
*   Lý thuyết: Tổng hợp lại điểm mạnh (nhanh cho CRUD đơn giản, tích hợp sẵn admin site) và điểm yếu (khó tách domain khỏi framework) của Django ORM.
    
*   Thực hành: Viết tổng kết: khi nào chọn Django ORM, khi nào chọn SQLAlchemy cho dự án tương lai.
    

### Project: Mini ORM (Ngày 540–545)

**Ngày 540: Thiết kế Mini ORM**

*   Mục tiêu: Lên kiến trúc trước khi code, dựa trên Unit of Work + Identity Map đã học.
    
*   Lý thuyết: Ôn lại 2 pattern cốt lõi: Unit of Work (gom thay đổi, commit 1 lần) và Identity Map (đảm bảo 1 object cho 1 row).
    
*   Thực hành: Vẽ sơ đồ kiến trúc Mini ORM: `Session`, `IdentityMap`, `QueryBuilder`.
    

**Ngày 541: Implement Session/Unit of Work**

*   Mục tiêu: Xây thành phần trung tâm.
    
*   Lý thuyết: Ôn lại Session cần theo dõi object nào "dirty" (đã sửa) để biết cần UPDATE gì khi commit.
    
*   Thực hành: Cài đặt `MiniSession` với `add()`/`commit()`, theo dõi danh sách object mới/đã sửa.
    

**Ngày 542: Implement Identity Map**

*   Mục tiêu: Đảm bảo tính nhất quán trong 1 session.
    
*   Lý thuyết: Ôn lại Ngày 524.
    
*   Thực hành: Thêm `IdentityMap` vào `MiniSession`, verify load cùng ID 2 lần trả về cùng object.
    

**Ngày 543: Implement Query Builder đơn giản**

*   Mục tiêu: Cho phép truy vấn linh hoạt cơ bản.
    
*   Lý thuyết: Ôn lại Builder pattern (Giai đoạn 3) áp dụng cho việc xây câu SQL dần dần.
    
*   Thực hành: Cài đặt `QueryBuilder` hỗ trợ `.filter()`/`.limit()`, sinh ra câu SQL tương ứng.
    

**Ngày 544: Test Mini ORM**

*   Mục tiêu: Đảm bảo Mini ORM hoạt động đúng.
    
*   Lý thuyết: Ôn lại Testing Strategy cho code có phụ thuộc database (Testcontainers, Giai đoạn 4).
    
*   Thực hành: Viết test cho `MiniSession`/`IdentityMap`/`QueryBuilder` dùng database test thật qua Testcontainers.
    

**Ngày 545: Retrospective Python Track**

*   Mục tiêu: Tổng kết toàn bộ Python Track (38 ngày).
    
*   Lý thuyết: Nhìn lại hành trình FastAPI → SQLAlchemy → Django ORM → Mini ORM, liên hệ ngược với Java Track vừa học.
    
*   Thực hành: Viết báo cáo so sánh triết lý framework Python (linh hoạt, ít boilerplate, dựa vào convention) với Java/Spring (tường minh, nhiều annotation, dựa vào container).
