Quy ước của framework giúp ứng dụng dễ hiểu hơn mà không cần nhiều tài liệu. Tìm hiểu quy ước bao phủ điều gì, khi nào chúng thất bại, và cách chỉ ghi chép những ngoại lệ.

Quy ước của framework là “cách mặc định để làm việc” mà framework khuyến khích—hoặc kỳ vọng. Thay vì mỗi đội tự nghĩ ra bố cục thư mục, quy tắc đặt tên, hoặc luồng request/response, framework cung cấp một mẫu chung. Nếu bạn theo nó, những lập trình viên khác có thể đoán được nơi đặt file và hành vi mà không cần một hướng dẫn dài dòng.
Hầu hết tài liệu không được viết vì mọi người thích viết docs. Nó tồn tại để giải quyết vài vấn đề lặp lại:
Quy ước giải quyết tốt hai mục đầu tiên. Khi “đặt X ở đâu” và “đặt tên Y như thế nào” đã được framework quyết, sẽ ít phải giải thích và ít tranh luận hơn.
“Quy ước thay thế tài liệu” không có nghĩa là dự án trở nên không cần tài liệu. Nó có nghĩa là một phần lớn hướng dẫn cơ bản chuyển từ văn bản sang cấu trúc có thể dự đoán. Thay vì đọc trang wiki để biết controller nằm ở đâu, bạn suy ra vì framework mong controller ở một chỗ nhất định (và các công cụ, generator, ví dụ củng cố điều đó).
Kết quả là ít tài liệu về những điều hiển nhiên hơn, và tập trung hơn vào việc ghi lại những gì thực sự đặc thù cho dự án: quy tắc nghiệp vụ, lựa chọn kiến trúc bất thường, và các ngoại lệ có chủ ý.
Bài này dành cho lập trình viên, tech lead và các đội quan tâm đến codebase rõ ràng và onboarding nhanh hơn mà không phải duy trì một trang tài liệu khổng lồ.
Bạn sẽ hiểu cách quy ước framework tạo ra “tài liệu ngầm định”, những thứ quy ước thường chuẩn hóa, nơi quy ước thất bại, và những gì vẫn cần được ghi thành văn bản—để tính rõ ràng tăng lên trong khi tài liệu giảm xuống.
“Convention over configuration” nghĩa là framework chọn lựa các thiết lập hợp lý cho bạn—khi bạn tuân theo quy tắc đã thỏa thuận. Thay vì viết (và đọc) trang hướng dẫn cấu hình dài, các đội dựa vào mặc định chung mà mọi người đều nhận ra.
Hãy nghĩ như lái xe ở một quốc gia nơi mọi người đồng ý đi bên phải, dừng ở đèn đỏ và tuân theo biển báo tiêu chuẩn.
Bạn có thể viết một cẩm nang chi tiết cho từng ngã tư (“Nếu thấy biển đỏ hình bát giác, dừng; nếu đèn màu xanh, đi…”), nhưng bạn không cần—vì quy ước đã được biết và áp dụng nhất quán.
Quy ước framework cũng hoạt động tương tự: chúng biến “cách ta làm ở đây” thành hành vi có thể dự đoán.
Khi framework có mặc định, bạn không phải ghi chép từng quyết định nhỏ. Framework (và đội bạn) có thể giả định các mẫu như:
controllers một chỗ, template một chỗ)User ánh xạ tới dữ liệu users)Nền tảng chia sẻ này thu gọn tài liệu từ “đây là mọi bước để thiết lập X” thành “chúng tôi theo mặc định của framework, ngoại trừ nơi có ghi chú.” Nó cũng giảm gánh nặng tinh thần khi onboarding: người mới đoán đúng thường xuyên hơn, vì mã khớp với những gì họ đã thấy ở dự án khác.
Quy ước không miễn phí. Nhược điểm là đôi khi bạn từ bỏ cấu trúc thư mục khác lạ, cách đặt tên tùy biến, hoặc workflow rất đặc thù.
Ưu điểm là tính nhất quán: ít tranh luận, ít bất ngờ, ít “kiến thức bộ tộc” mà chỉ người lâu năm mới biết. Các đội tiến nhanh hơn vì dành ít thời gian giải thích và nhiều thời gian xây dựng hơn.
Một quy ước chỉ tiết kiệm tài liệu nếu mọi người đã biết nó—hoặc có thể học một lần và tái sử dụng ở mọi nơi.
Đó là lý do các framework phổ biến mạnh mẽ: quy ước được dạy rộng rãi, dùng nhiều và lặp lại qua nhiều codebase. Khi dự án của bạn tuân theo những mặc định được chia sẻ đó, code trở nên dễ hiểu mặc định, với ít giải thích bằng văn bản hơn nhiều.
Quy ước framework là những phím tắt chung. Chúng chuẩn hóa các câu hỏi mà mọi đồng đội mới đặt vào ngày đầu: “Cái này đặt ở đâu?” và “Gọi nó là gì?” Khi những câu trả lời có thể dự đoán, bạn có thể thay hàng trang tài liệu bằng vài mặc định nhất quán.
Hầu hết framework đẩy một cấu trúc dự án dễ nhận diện: nơi cho UI, nơi cho routes, nơi cho truy cập dữ liệu, nơi cho test. Tính nhất quán này quan trọng vì mọi người không cần đọc hướng dẫn để tìm “phần render trang” so với “phần nói chuyện với database.”
Quy ước tốt nhất khiến các tác vụ phổ biến trở thành phản xạ: thêm màn hình mới, bạn đã biết nó thuộc thư mục nào.
Quy tắc đặt tên giảm nhu cầu giải thích như “Controller của chúng ta ở X và phải được nối ở Y.” Thay vào đó, tên ngụ ý vai trò.
Ví dụ phổ biến:
Nhiều web framework ánh xạ file tới route (hoặc khiến route dễ suy ra). Nếu bạn có thể đoán URL từ tên file—hoặc ngược lại—bạn không cần tài liệu routing cho từng feature.
Quy ước cũng đặt kỳ vọng về dynamic routes, nested routes và xử lý 404, nên “thêm endpoint mới thế nào?” có câu trả lời chuẩn.
Quy ước thường xác định nơi đặt “mã dữ liệu”: models, repositories, services, migrations, file schema. Dù app nhỏ, có một nơi thống nhất cho truy cập dữ liệu ngăn chặn việc gọi database rải rác trong code UI.
Các lệnh chuẩn (run, test, build, lint, format) loại bỏ sự mơ hồ. Dev mới không nên cần wiki để biết cách khởi động dự án—npm test (hoặc tương đương) nên là bước rõ ràng đầu tiên.
Khi năm khu vực này nhất quán, codebase tự trả lời hầu hết câu hỏi “chúng ta làm ở đây thế nào?”.
Một wiki "cách mọi thứ hoạt động" cố mô tả toàn hệ thống bằng văn bản. Nó thường bắt đầu hữu ích, rồi lỗi thời khi thư mục di chuyển, tên đổi và feature mới xuất hiện. Quy ước đảo ý tưởng đó: thay vì đọc một lời giải thích dài, bạn đọc cấu trúc.
Khi framework (và đội bạn) đồng ý nơi đặt thứ gì, repo trở nên điều hướng như lưới đường phố.
Nếu bạn biết component UI vào components/, view cấp trang vào pages/, và handler API vào api/, bạn sẽ ngừng hỏi “X ở đâu?” vì dự đoán đầu tiên thường đúng. Dù không đúng, tìm kiếm của bạn bị thu hẹp: nó không còn ở bất cứ đâu—mà ở một vài chỗ mong đợi.
Quy ước khiến tên file và symbol mang ý nghĩa. Người mới có thể suy ra hành vi từ vị trí và tên:
user.controller có khả năng xử lý logic requestUserService có thể chứa quy tắc nghiệp vụmigrations/ thường chứa thay đổi DB chạy một lần và theo thứ tựSự suy luận này giảm các câu hỏi “giải thích kiến trúc cho tôi” thành các câu nhỏ hơn có thể trả lời (“Service này có được quyền gọi DB trực tiếp không?”), vốn dễ ghi lại hơn.
Cách nhanh nhất để củng cố bản đồ là scaffolding. Starter template và generator tạo feature mới theo “hình dạng đúng” mặc định—thư mục, tên file, boilerplate, và thường là test.
Điều này quan trọng vì quy ước chỉ hữu ích khi được áp dụng nhất quán. Template là rào chắn: nó đưa mọi route, component hoặc module mới về cấu trúc mong đợi, nên codebase giữ được tính đọc được mà không cần thêm trang wiki.
Nếu bạn duy trì scaffold nội bộ, liên kết nó từ một trang onboarding ngắn (ví dụ, /docs/getting-started) và để cây thư mục làm phần còn lại.
Quy ước framework thường hoạt động như hướng dẫn tích hợp im lặng. Thay vì viết trang giải thích “đặt thứ gì ở đâu” hay “nối cái này thế nào”, framework đã quyết—và đội học cách đọc cấu trúc.
Rails nổi tiếng với convention over configuration. Một ví dụ đơn giản: nếu bạn tạo controller tên OrdersController, Rails giả định có thư mục view tương ứng ở app/views/orders/.
Quy ước đơn lẻ này có thể thay một phần tài liệu nếu không sẽ phải giải thích:
Kết quả: người mới có thể thêm trang chỉ bằng cách theo mẫu thư mục, mà không hỏi “file này đặt ở đâu?”
Django khuyến khích cấu trúc “app” nhất quán. Khi ai đó nhìn thấy một app Django, họ mong tìm models.py cho kiểu dữ liệu, views.py cho xử lý request, và templates/ cho HTML.
Bạn có thể viết hướng dẫn dài mô tả cấu trúc dự án, nhưng mặc định của Django đã dạy điều đó. Khi đồng đội muốn thay đổi giao diện trang, họ biết tìm templates/. Khi cần chỉnh dữ liệu lưu trữ, họ bắt đầu ở models.py.
Kết quả: sửa lỗi nhanh hơn, ít mất thời gian tìm kiếm, ít câu hỏi “file nào điều khiển điều này?”
Next.js giảm nhu cầu tài liệu bằng cách làm routing phản chiếu trực tiếp cấu trúc thư mục. Tạo file ở app/about/page.tsx (hoặc pages/about.tsx trong cấu hình cũ hơn), và bạn tự động có trang /about.
Điều đó loại bỏ nhu cầu tài liệu giải thích:
Kết quả: onboarding đơn giản hơn—mọi người khám phá hình dạng website bằng cách quét thư mục.
Rails, Django và Next.js khác nhau về bề ngoài, nhưng nguyên tắc giống nhau: mặc định chung biến cấu trúc dự án thành hướng dẫn. Khi mọi người tin vào cùng một quy ước, codebase tự trả lời nhiều câu “chúng ta làm thế nào?”—không cần thêm tài liệu duy trì.
Quy ước framework có vẻ “vô hình” khi chúng hoạt động. Bạn đoán được file nằm đâu, tên gì và yêu cầu chạy qua app như thế nào. Sự bối rối quay lại khi codebase lệch khỏi những mặc định chung đó.
Một vài mô hình xuất hiện sớm:
UserService, phần kia UsersManager, phần khác user_serviceKhông phải tất cả đều sai—nhưng chúng khiến người mới không còn dựa vào “bản đồ” của framework nữa.
Hầu hết sự sụp đổ quy ước bắt đầu bằng tối ưu hoá cục bộ hợp lý: “Tính năng này đặc biệt, nên để nó chỗ này” hoặc “Cách đặt tên này đọc ổn hơn.” Vấn đề là ngoại lệ dễ lan. Khi ngoại lệ đầu tiên ra mắt, dev tiếp theo xem đó như tiền lệ:
Lúc đó, quy ước ngừng là quy ước—nó trở thành kiến thức bộ tộc.
Khi quy ước mờ nhạt, onboarding chậm vì người ta không đoán được nơi tìm. Công việc hàng ngày mất nhiều thời gian hơn (“Thư mục nào là thư mục thật?”), và lỗi tăng (nối nhầm module, dùng pattern sai, nhân đôi logic). Đội bù bằng cách tổ chức nhiều sync hơn, viết giải thích PR dài hơn, và thêm “quick docs” rồi để chúng lỗi thời.
Chỉ tuỳ chỉnh khi có lý do rõ ràng—và để lại ghi chú bằng văn bản.
Ghi chú này có thể nhẹ: một comment ngắn gần cấu trúc bất thường, hoặc một mục ngắn trong /docs/decisions giải thích gì thay đổi, vì sao đáng, và cách tiếp cận chuẩn cho công việc tương lai.
Quy ước framework có thể loại bỏ cả trang giải thích, nhưng không miễn trách nhiệm. Những phần vẫn cần tài liệu là nơi dự án của bạn khác có chủ ý so với giả định của đa số dev.
Bỏ qua việc giải thích lại hành vi chuẩn của framework. Thay vào đó, ghi lại các quyết định ảnh hưởng đến công việc hàng ngày:
Ví dụ: “Chúng tôi dùng feature folders dưới /src/features thay vì phân lớp (/src/components, /src/services) vì ownership gắn với đội và giảm coupling giữa đội.” Một câu đơn này ngăn chặn sự trôi dạt trong vài tuần.
Khi một ngoại lệ quan trọng cục bộ, đặt ghi chú cục bộ. Một README.md nhỏ trong thư mục, hoặc header comment ngắn ở đầu file, thường tốt hơn wiki trung tâm mà chẳng ai kiểm tra.
Ứng viên tốt:
Giữ ghi chú ngắn và hành động được: khác gì, vì sao khác, và phải làm gì tiếp theo.
Có một trang nhẹ (thường ở /docs/project-rules.md hoặc README gốc) liệt kê chỉ 5–10 lựa chọn chính mà mọi người dễ vấp:
Đây không phải manual đầy đủ—chỉ là bộ lan can chia đường.
Ngay cả với quy ước, onboarding nghẽn khi mọi người không biết chạy app. Thêm phần “How to run/test” ngắn khớp với lệnh chuẩn và thiết lập thực tế của bạn.
Nếu lệnh convention là npm test nhưng dự án bạn cần npm run test:unit, hãy ghi rõ điều đó.
Tài liệu chính xác khi nó được coi là một phần của thay đổi. Trong review, hỏi: “Thay đổi này tạo ngoại lệ mới không?” Nếu có, yêu cầu ghi chú kèm theo (README cục bộ, Project Rules, hoặc quickstart) trong cùng pull request đó.
Nếu quy ước là “mặc định chung” của codebase, tự động hóa là thứ biến chúng thành hiện thực. Thay vì yêu cầu dev nhớ quy tắc từ wiki, bạn biến quy tắc thành code—vậy dự án tự thực thi.
Một thiết lập tốt bắt kịp sự lệch sớm và lặng lẽ:
*.spec.ts, cách đặt tên describe/it, hoặc assertions bắt buộc để test đọc đồng đều.Những kiểm tra này thay hàng đoạn “hãy nhớ…” bằng một kết quả đơn giản: code khớp quy ước hoặc không.
Tự động hóa tỏa sáng vì nó fail nhanh:
Bộ quy tắc tốt nhất là nhỏ và nhàm chán. Bắt đầu với mặc định của framework, rồi chỉ thêm những gì bảo vệ tính rõ ràng (đặt tên, cấu trúc, ranh giới). Mỗi rule thêm vào là một điều người ta phải hiểu, nên đối xử với rule mới như code: thêm khi nó giải quyết vấn đề lặp lại, và xóa khi không còn hữu ích.
Quy ước của framework là những mẫu mặc định mà framework mong đợi bạn tuân theo — cấu trúc thư mục, cách đặt tên, routing, truy cập dữ liệu và các lệnh phổ biến. Khi bạn bám sát chúng, các lập trình viên khác có thể suy ra nơi đặt file và cách hoạt động mà không cần đọc tài liệu riêng của dự án.
Vì khó giữ prose (tài liệu dạng văn) chính xác khi mã nguồn thay đổi. Tài liệu tồn tại chủ yếu để:
Quy ước giải quyết hai mục đầu tiên bằng cách làm cho cấu trúc trở nên dự đoán được.
Không. Quy ước giảm lượng tài liệu về những điều rõ ràng (nơi đặt file, cách route được nối), nhưng bạn vẫn cần viết những gì đặc thù dự án: quy tắc nghiệp vụ, các lệch chủ ý và quyết định quan trọng. Nghĩ theo cách “ít tài liệu hơn, nhưng giá trị cao hơn.”
Chúng chuẩn hóa các câu hỏi lặp lại ngày đầu:
Khi mã theo một mẫu quen thuộc, cây thư mục và tên file đóng vai trò như biển chỉ đường. Người mới có thể định hướng theo kỳ vọng (ví dụ: “templates nằm trong templates/”, “migrations ở migrations/”) thay vì đọc một trang kiến trúc dài dễ lỗi thời.
Chúng mã hóa quy ước thành mặc định để người ta không phụ thuộc vào trí nhớ. Scaffold tốt tạo ra:
Điều này ngăn trôi và giữ “bản đồ” nhất quán giữa các feature.
Bạn sẽ thấy điều đó khi các dev không thể dự đoán file nằm ở đâu hay gọi là gì. Dấu hiệu phổ biến:
UserService vs UsersManager vs user_service)Lúc đó đội bù lại bằng Slack, PR dài hơn và “quick docs” lỗi thời.
Chỉ tùy chỉnh khi có lợi rõ ràng, rồi để lại ghi chú ngắn giải thích sự lệch:
README.md nhỏ trong thư mục bất thường/docs/decisions hoặc tương tựGhi lại đã thay đổi gì, vì sao, và cách tiêu chuẩn nên thực hiện tiếp theo.
Bắt đầu bằng một nền tảng thực tế, ví dụ:
Giữ gọn và yêu cầu cập nhật tài liệu khi code review nếu một thay đổi tạo ra ngoại lệ mới.
Dùng tự động hóa để biến quy ước thành những gì có thể thực thi:
Khi check fail ở local hoặc PR, dev học quy tắc ngay—và reviewer bớt thời gian canh style.
Khi những điều này dự đoán được, repo tự nó trở nên dễ hiểu.