Bài 1 · Vận dụng · 16 phút· Cập nhật 10/06/2026
Tổng Quan
Biên soạn bởi Nguyễn Anh Tuấn
SOLID là gì? Ưu nhược điểm. Khi nào nên áp dụng, và áp dụng tới mức nào để không bị over-engineering.
SOLID không ra đời để làm code trông "học thuật" hơn. Nó ra đời từ một nỗi đau rất thực dụng: phần mềm càng sống lâu, càng nhiều người sửa, càng dễ biến thành một khối khó đổi.
Lúc mới viết, code thường còn nhỏ. Sau vài tháng, một yêu cầu mới có thể kéo theo sửa nhiều module; sửa checkout lại vỡ email; đổi database lại ảnh hưởng nghiệp vụ; muốn viết test nhưng service kéo theo quá nhiều chi tiết hạ tầng. Đó là lúc team bắt đầu cần nguyên tắc thiết kế, không chỉ cần cú pháp.
- ▸Dự án càng sống lâu thì chi phí thay đổi càng quan trọng.
- ▸Team càng đông thì ranh giới trách nhiệm càng cần rõ.
- ▸Yêu cầu càng hay đổi thì dependency cứng càng dễ gây chậm và lỗi.
Các nguyên tắc đứng sau SOLID đến từ cộng đồng thiết kế hướng đối tượng (OOP) cuối thập niên 1990 và đầu thập niên 2000. Robert C. Martin, thường được biết tới với tên Uncle Bob, phổ biến chúng trong bài Design Principles and Design Patterns năm 2000 và các sách về Agile/OOP sau đó.
Ban đầu chúng là các nguyên tắc thiết kế lớp hướng đối tượng. Sau này Michael Feathers được ghi công vì đề xuất acronym SOLID, giúp 5 nguyên tắc dễ nhớ hơn:
| S | Single Responsibility - một module nên có một trách nhiệm chính. |
| O | Open/Closed - mở để mở rộng, đóng để hạn chế sửa code ổn định. |
| L | Liskov Substitution - biến thể thay được kiểu gốc mà không phá hành vi. |
| I | Interface Segregation - interface nhỏ, đúng nhu cầu của client. |
| D | Dependency Inversion - module cấp cao phụ thuộc abstraction, không phụ thuộc chi tiết implementation. |
Ghi công
SOLID hữu ích nhất khi chi phí thay đổi bắt đầu lớn hơn chi phí thiết kế. Nói cách khác: nếu phần mềm còn sống lâu, còn đổi yêu cầu, còn nhiều người chạm vào, thì việc giảm coupling và tách trách nhiệm sẽ tiết kiệm công về sau.
| Bối cảnh | SOLID ít cần | SOLID đáng cân nhắc |
|---|---|---|
| Tuổi thọ dự án | Script một lần, prototype ngắn | Sản phẩm sống nhiều tháng hoặc nhiều năm |
| Mức đổi yêu cầu | Ít đổi, phạm vi rõ | Nhiều biến thể, khách hàng hay đổi luồng |
| Số người tham gia | Một người, ít bàn giao | Nhiều dev, nhiều review, cần chia module |
| Rủi ro khi sửa sai | Sai dễ xoá, dễ viết lại | Sai ảnh hưởng dữ liệu, tiền, bảo mật, vận hành |
Một hiểu lầm phổ biến là "đã học SOLID thì phải áp dụng đủ cả 5 nguyên tắc ở mọi nơi". Cách nghĩ đó dễ đẩy team vào over-engineering: nhiều class, nhiều interface, nhiều file, nhưng luồng nghiệp vụ lại khó đọc hơn.
- ▸SOLID là bộ câu hỏi thiết kế, không phải checklist để tích đủ.
- ▸Có module chỉ cần SRP: tách trách nhiệm cho dễ đọc và dễ test.
- ▸Có ranh giới I/O nên ưu tiên DIP: database, email, payment, API ngoài.
- ▸OCP, LSP, ISP đáng đầu tư hơn khi hệ thống có nhiều biến thể và nhiều client.
Trung thực
Áp dụng SOLID giống như trả một khoản chi phí thiết kế trước để giảm chi phí thay đổi sau này. Câu hỏi không phải "SOLID tốt hay xấu?", mà là "với dự án này, khoản chi đó có đáng không?"
Lợi ích thường thấy
- Thay đổi ít lan ra ngoài module liên quan.
- Test nghiệp vụ dễ hơn vì dependency có thể thay bằng fake hoặc mock data.
- Thêm biến thể mới ít phải sửa code ổn định.
- Ranh giới module rõ hơn, review dễ hơn.
Chi phí phải trả
- Team cần học chung thuật ngữ và cách review.
- Giai đoạn đầu có thể viết nhiều file hơn.
- Abstraction sai chỗ làm code khó lần theo.
- Legacy code cần test đỡ lưng trước khi refactor mạnh.
SOLID không chỉ là quyết định kỹ thuật. Nó là quyết định của team. Nếu team chưa cùng hiểu interface, dependency injection, unit test, refactor và code review, việc yêu cầu "áp dụng SOLID" có thể tạo ra 5 kiểu code khác nhau.
- ▸Team senior, có test và review đều: có thể áp dụng sâu ở module lõi và ranh giới hạ tầng.
- ▸Team hỗn hợp: chọn 1-2 nguyên tắc dễ thống nhất trước, viết guideline ngắn và review bằng ví dụ.
- ▸Team mới hoặc deadline gấp: ưu tiên đọc dễ, test được phần quan trọng, tránh coupling lộ rõ.
- ▸Team legacy: không refactor hàng loạt; chọn điểm đau, viết characterization test, cải thiện dần.
Câu hỏi nên hỏi trước khi áp dụng
Trước khi đưa SOLID vào một dự án, team có thể dùng khung 4 bước này trong buổi technical planning hoặc trước một đợt refactor:
- ▸Bước 1: chấm bối cảnh dự án - tuổi thọ, tần suất đổi yêu cầu, số người cùng sửa, rủi ro lỗi.
- ▸Bước 2: chấm năng lực team - OOP, interface, unit test, refactor, code review.
- ▸Bước 3: chọn mức áp dụng - nhẹ, vừa, hoặc mạnh; ghi rõ nguyên tắc nào ưu tiên trước.
- ▸Bước 4: đo lại sau 2-4 tuần - PR có dễ review hơn không, test có dễ viết hơn không, bug có giảm không.
Gợi ý mức áp dụng
Bài tổng quan chỉ giúp bạn ra quyết định có nên học và áp dụng SOLID ở mức nào. Các bài sau mới đi vào từng nguyên tắc bằng ví dụ TypeScript trước/sau:
- ▸Bài 2: Single Responsibility - tách trách nhiệm để module chỉ có một lý do chính để đổi.
- ▸Bài 3: Open/Closed - mở rộng bằng đa hình, Strategy hoặc registry thay vì sửa nhánh if cũ.
- ▸Bài 4-6: LSP, ISP, DIP - giữ lời hứa kế thừa, chia interface nhỏ, đảo chiều phụ thuộc.
- ▸Bài 7-8: áp dụng tổng hợp và refactor một module legacy có test đỡ lưng.
Đi tiếp
Câu hỏi thường gặp
Không bắt buộc. Một team có thể bắt đầu từ SRP để tách trách nhiệm, DIP ở ranh giới I/O để dễ test, rồi học OCP/LSP/ISP khi gặp nhu cầu mở rộng. Áp dụng theo rủi ro và năng lực team tốt hơn làm đủ cho đẹp.
Có thể dùng ở mức nhẹ: đặt tên rõ, tách trách nhiệm rõ, tránh coupling quá lộ. Nhưng đừng tạo nhiều interface, factory, class trung gian nếu dự án chỉ vài file và ít khả năng đổi yêu cầu.
Đừng đưa thẳng vào deadline gấp. Hãy học chung thuật ngữ, review code mẫu, refactor một module nhỏ có test, rồi rút ra quy ước nội bộ. Mục tiêu là team hiểu cùng một cách, không phải mỗi người áp dụng theo một kiểu.
Tick những điều em tự tin làm được. Càng lên cao, em càng hiểu sâu.
Trả lời vài câu để chắc rằng em đã nắm bài.
Ai là người đúc kết & phổ biến 5 nguyên tắc SOLID?
- 1
Thuộc 5 chữ cái
Viết ra S-O-L-I-D, mỗi chữ một câu mô tả bằng lời của mèo con.
✅ Hoàn thành khi: Đủ 5 nguyên tắc; mỗi câu nêu đúng ý chính, không chép nguyên văn bảng trong bài.
- 2
Kể lại lịch sử
Viết đoạn 5-7 câu: SOLID xuất hiện trong bối cảnh nào, ai phổ biến, acronym do ai đề xuất, vì sao OOP cần các nguyên tắc này.
✅ Hoàn thành khi: Có mốc năm 2000, Robert C. Martin, Michael Feathers, và bối cảnh phần mềm cần dễ bảo trì.
- 3
Chấm điểm dự án
Chọn một dự án của mèo con. Chấm 1-5 cho bốn yếu tố: thời gian sống, tần suất đổi yêu cầu, số người cùng sửa, rủi ro khi sửa sai.
✅ Hoàn thành khi: Có điểm cho 4 yếu tố và kết luận dự án nên áp dụng SOLID nhẹ, vừa, hay mạnh.
- 4
Đánh giá team
Liệt kê kiến thức hiện có của team: OOP, interface, unit test, refactor, code review. Mỗi mục ghi: đã vững, đang học, hay chưa có.
✅ Hoàn thành khi: Có bảng đánh giá năng lực và ít nhất 2 việc cần chuẩn bị trước khi áp SOLID rộng.
- 5
Cân thiệt hơn
Chọn một nguyên tắc SOLID muốn áp dụng trước. Viết 2 lợi ích mong đợi và 2 chi phí hoặc rủi ro cho team.
✅ Hoàn thành khi: Lợi ích và chi phí gắn với bối cảnh dự án, không nói chung chung.
- 6
Quy ước thử nghiệm
Viết một quy ước 3 dòng cho team: áp dụng SOLID ở đâu, chưa áp dụng ở đâu, và tiêu chí xem lại sau 2 tuần.
✅ Hoàn thành khi: Quy ước đủ cụ thể để một pull request có thể được review theo đó.