2.0 — SOLID: lịch sử ra đời và vấn đề nó thực sự giải quyết

1. Vấn đề lịch sử — SOLID sinh ra từ nỗi đau nào? SOLID không rơi từ trên trời xuống. Nó là sản phẩm của một thời điểm lịch sử rất cụ thể — và hiểu bối cảnh đó quyết định việc bạn áp dụng nó đúng hay mù quáng. Thập niên 1990, thế giới C++/OOP doanh nghiệp. Các hệ thống lớn viết bằng C++ thời đó có đặc điểm: biên dịch một lần mất hàng giờ; sửa một header file kéo theo recompile cả dây chuyền phụ thuộc; deploy là chép binary khổng lồ; và cây kế thừa sâu là “best practice” được dạy chính thống. Robert C. Martin (Uncle Bob) quan sát các codebase như vậy và mô tả bốn triệu chứng của “thiết kế mục nát” (design rot): ...

July 17, 2026 · 5 min

1.5 — Interface & Immutability: hai vũ khí thiết kế của Go

Phần A — Interface 1. Problem Statement Interface đã xuất hiện ở mọi chương trước như “công cụ giảm coupling”. Chương này trả lời các câu hỏi mà kỹ sư senior thực sự vướng: interface đặt ở đâu? To hay nhỏ? Khai báo khi nào? Vì sao interface Go khác Java/TS ở tầng triết lý — và điều đó đổi cách thiết kế ra sao? 2. Điều làm interface Go khác biệt: implicit satisfaction package storage type Saver interface { Save(ctx context.Context, key string, data []byte) error } Bất kỳ type nào có method Save đúng chữ ký — tự động thỏa mãn Saver. Không implements, không import package chứa interface. Hệ quả thiết kế sâu sắc: ...

July 17, 2026 · 10 min

1.4 — Composition vs Inheritance & Polymorphism

1. Problem Statement Bài toán: hệ thống có nhiều loại thông báo — Email, SMS, Push. Chúng chia sẻ logic chung (retry, logging, rate-limit) nhưng khác nhau ở cách gửi. Làm sao tái sử dụng phần chung mà không copy-paste? Đây là bài toán mà inheritance (kế thừa) sinh ra để giải. Và cũng là bài toán cho thấy vì sao inheritance thường là câu trả lời sai — đến mức chính GoF, trong cuốn sách 1994, đã viết ở trang 20: “Favor object composition over class inheritance”. Go đi xa hơn: loại bỏ hẳn class inheritance khỏi ngôn ngữ. ...

July 17, 2026 · 10 min

1.3 — Coupling, Cohesion & Dependency: thước đo của mọi quyết định thiết kế

1. Problem Statement Đây là chương quan trọng nhất của Level 1. Mọi nguyên lý (SOLID), mọi pattern (Strategy, Observer…), mọi kiến trúc (Clean, Hexagonal) — khi bóc hết vỏ — đều quy về đúng hai đại lượng: Coupling: hai module dính nhau chặt đến đâu — sửa cái này có phải sửa cái kia không? Cohesion: những thứ trong cùng một module có thực sự thuộc về nhau không? ...

July 17, 2026 · 11 min

1.2 — Abstraction & Encapsulation: che giấu đúng thứ cần che

1. Problem Statement Tiếp tục câu chuyện e-commerce. Team bạn cần gửi email xác nhận đơn hàng. Một dev viết: // V1 — trong order_service.go func (s *OrderService) ConfirmOrder(ctx context.Context, orderID string) error { order, err := s.repo.Find(ctx, orderID) if err != nil { return err } order.Status = "confirmed" if err := s.repo.Save(ctx, order); err != nil { return err } // Gửi email — chi tiết SMTP nằm ngay tại đây auth := smtp.PlainAuth("", "noreply@shop.vn", os.Getenv("SMTP_PASS"), "smtp.gmail.com") body := fmt.Sprintf("Subject: Đơn hàng %s đã xác nhận\r\n\r\nCảm ơn bạn!", order.ID) return smtp.SendMail("smtp.gmail.com:587", auth, "noreply@shop.vn", []string{order.CustomerEmail}, []byte(body)) } Chạy được. Ship được. Nhưng 3 tháng sau: ...

July 17, 2026 · 10 min

1.1 — Vì sao code trở nên khó bảo trì: bản chất của Software Design

1. Problem Statement Hãy bắt đầu bằng một sự thật mà mọi kỹ sư có kinh nghiệm đều biết nhưng ít khi nói thành lời: Chi phí của phần mềm không nằm ở việc viết code lần đầu. Nó nằm ở việc thay đổi code sau đó. Một hệ thống backend điển hình sống 5–10 năm. Trong vòng đời đó, code được đọc nhiều gấp 10 lần được viết, và được sửa nhiều gấp nhiều lần được viết mới. Nghiên cứu kinh điển về chi phí phần mềm ước tính 60–80% tổng chi phí là maintenance — không phải development ban đầu. ...

July 17, 2026 · 8 min

Software Design & Design Patterns — Từ First Principles đến Production

Tài liệu chuyên sâu dành cho Backend Engineer, Golang/Node.js Developer, Tech Lead và Solution Architect. Viết bởi góc nhìn của một Principal Software Architect: pattern không phải là mục tiêu — pattern là kết quả của việc giải quyết một vấn đề thiết kế cụ thể. Triết lý của bộ tài liệu này Hầu hết tài liệu về Design Pattern bắt đầu bằng: “Singleton là… Factory là… Observer là…” — cách học này tạo ra những kỹ sư thuộc lòng 23 pattern nhưng không biết khi nào dùng, và tệ hơn, dùng pattern ở nơi không cần thiết (over-engineering). ...

July 17, 2026 · 5 min