Mọi đội ngũ phát triển đều có một câu chuyện như thế này. Một pull request bị treo suốt nửa ngày. Không phải vì logic bị lỗi hay hợp đồng API thay đổi, mà vì hai người review không thống nhất về việc liệu các object literal có cần dấu phẩy ở cuối hay không. Luồng thảo luận kéo dài. Ai đó gửi một link hướng dẫn phong cách (style guide). Người khác lại phản bác bằng một hướng dẫn khác. Đến khi code được merge, tất cả những người liên quan đều đã mất đi ngữ cảnh về các tính năng mà họ thực sự đang xây dựng.
Những cuộc tranh cãi này rất tốn kém. Chúng tiêu tốn hàng giờ đồng hồ của các kỹ sư dày dạn kinh nghiệm, tạo ra sự bất mãn ngầm giữa các đồng nghiệp, và rèn luyện cho các lập trình viên junior niềm tin rằng kỹ thuật phần mềm chủ yếu là về việc thắng thua trong các cuộc tranh luận về dấu chấm phẩy. Điều tồi tệ nhất là gì? Sản phẩm không hề quan tâm. Người dùng sẽ không bao giờ nhận ra sự khác biệt giữa một khoảng trắng và một phím tab. Họ sẽ nhận ra lỗi mà bạn đã không sửa vì mải tranh cãi về dấu ngoặc kép.
Sự nhất quán thực sự quan trọng. Một codebase trông như thể được viết bởi cùng một người sẽ dễ đọc, dễ review và dễ debug hơn. Sai lầm nằm ở việc cố gắng áp đặt sự nhất quán đó một cách thủ công.
Tự động hóa những việc nhàm chán
Giải pháp rất đơn giản. Loại bỏ hoàn toàn sự phán xét của con người khỏi việc định dạng. Hãy giao phó nó cho các công cụ không có cái tôi và không biết mệt mỏi.
Có ba công cụ xử lý việc này một cách gọn gàng.
Prettier lấy code của bạn và tự động định dạng lại. Nó không cần xin phép. Bạn sẽ không còn phải bận tâm về độ dài dòng, kiểu dấu ngoặc, hay cách ngắt một hàm dài trên nhiều dòng. Bạn chỉ cần lưu file. Prettier sẽ làm cho nó trở nên nhất quán.
ESLint xử lý những vấn đề mà Prettier sẽ không chạm tới. Nó phát hiện các biến không sử dụng, code không thể truy cập được, các dependency bị thiếu trong React hooks, và các pattern vốn thường dẫn đến lỗi. Khi được cấu hình đúng, nó sẽ không can thiệp vào việc định dạng mà tập trung vào chất lượng code thực tế.
Husky cài đặt một pre-commit hook để chặn mọi thứ không được đưa vào repository cho đến khi các bước kiểm tra tự động vượt qua. Nó biến Git pipeline của bạn thành một người gác cổng thay vì một hộp thư góp ý.
Cùng nhau, chúng tạo thành một vòng lặp chặt chẽ. Bạn viết code theo bất kỳ cách nào bạn muốn ở máy cục bộ. Khi bạn commit, các công cụ sẽ làm sạch và kiểm tra nó. Chỉ khi đó, code mới rời khỏi máy của bạn.
Tại sao bộ công cụ (stack) cụ thể này lại hiệu quả
Bạn có thể dành hàng tuần để tinh chỉnh các quy tắc ESLint bằng tay. Hãy cưỡng lại sự thôi thúc đó. Mục tiêu ở đây là ngừng tranh cãi về phong cách, chứ không phải tạo ra một công việc toàn thời gian mới với vai trò là người quản lý hướng dẫn phong cách.
Prettier được thiết kế có chủ đích theo hướng "opinionated". Nó cung cấp các tùy chọn cấu hình hạn chế vì mỗi tùy chọn đều có thể trở thành một cuộc tranh luận trong tương lai. Các thiết lập mặc định là hợp lý. Hãy chọn một tập hợp nhỏ các tùy chọn ghi đè (overrides), viết chúng ra một lần, và tiếp tục công việc.
Nếu để mặc, ESLint sẽ cố gắng áp đặt cả quy tắc chất lượng code lẫn quy tắc định dạng như cách dùng dấu chấm phẩy và kích thước thụt lề. Điều đó tạo ra sự xung đột với Prettier vì cả hai công cụ đều cố gắng chỉnh sửa cùng một ký tự. Package eslint-config-prettier giải quyết vấn đề này bằng cách vô hiệu hóa tất cả các quy tắc ESLint xung đột với Prettier. Sự phân chia nhiệm vụ này là cực kỳ quan trọng. Prettier quản lý phần thẩm mỹ. ESLint quản lý phần logic.
Chỉ chạy kiểm tra trong quá trình tích hợp liên tục (continuous integration) là quá muộn. Đến khi CI thất bại, bạn đã commit code lộn xộn, đã chuyển sang tác vụ khác và có thể đã mở một pull request. Việc sửa lỗi đòi hỏi một commit khác, một lần push khác và một chu kỳ chờ đợi khác. Husky rút ngắn vòng lặp phản hồi đó xuống còn vài giây. Lint-staged giúp quá trình này nhanh chóng bằng cách chỉ chạy các công cụ trên những file bạn thực sự thay đổi, thay vì quét toàn bộ repository trong mỗi lần commit.
Thiết lập từng bước một
Cấu hình sau đây dành cho một dự án JavaScript hoặc React hiện đại, nhưng mô hình này có thể áp dụng cho TypeScript, Vue hoặc Node với một vài điều chỉnh nhỏ. Hãy chạy từng bước từ thư mục gốc của dự án.
Bắt đầu bằng cách cài đặt mọi thứ dưới dạng dev dependencies:
npm install -D prettier eslint husky lint-staged eslint-config-prettier
