Để có thể dễ dàng bảo trì, sửa chữa và cập nhật những tính năng mới, Javascript đang hướng đến việc viết code cho con người hiểu thay vì cho máy tính hiểu. Vì vậy, những dòng code của bạn phải dễ hiểu nhất. Dưới đây là những kinh nghiệm để giúp bạn viết code JavaScript sao cho dễ bảo trì và dễ đọc nhất.
Mục lục
Sử dụng TypeScript ở mọi nơi
TypeScript không còn quá xa lạ với các lập trình viên Front – end, nó là một trong những ngôn ngữ lập trình được Microsoft “tặng” miễn phí cho các lập trình viên. Đây là ngôn ngữ mã nguồn mở của JavaScript, được dùng để thiết kế và xây dựng các dự án ứng dụng quy mô lớn, mang tính chất phức tạp.
Nếu bạn sử dụng IDE hoặc editor có tính năng tính năng tự động hoàn thành, đề xuất, tài liệu nội tuyến thì TypeScript là sự lựa chọn tốt dành cho bạn. Bạn có thể xem ví dụ dưới đây để nhìn thấy sự khác biệt:
Đối với không sử dụng TypeScript
// src/api/posts.js
export default {
getPosts: () => axios.get(“/posts”),
}
Bạn có thể thấy rằng với cách tiếp cận vấn đề của đoạn code này có thể không rõ ràng, getPosts trả về cái gì? Nếu bạn cần chuyển từ axios sang fetch? Làm sao để bạn thêm một chức năng để tạo bài đăng? Làm cách nào để bạn xác định cấu trúc dữ liệu trong một đối tượng?
Đối với sử dụng TypeScript
// src/api/posts.ts
export interface Post {
title: string;
excerpt: string;
}
export default {
getPosts: function(): Promise<AxiosResponse<Post[]>> {
return axios.get(“/posts”);
},
};
Sự khác biệt giữa 2 đoạn code là tính minh bạch. Khi sử dụng TypeScript, các models được chia sẻ cho phép bạn thực thi cùng một cấu trúc trên cả server và client. Bên cạnh đó, bạn cũng có thể tránh được những lỗi chính tả trong code bằng cách forced một loại properties hoặc classes cụ thể.
Học tốt JavaScript và các Framework
Bạn cần phải hiểu về asynchronous JavaScript (bất đồng bộ JavaScript), generator functions, functional và object-oriented paradigms, phạm vi, hiệu suất,… Tuy nhiên, có nhiều lập trình viên vẫn không hiểu rõ về asynchronous JavaScript. Dưới đây là một vài hướng dẫn để bạn có thể sử dụng asynchronous JavaScript hiệu quả.
Đây là những gì bạn có thể bắt đầu ngay hôm nay mà không cần học bất cứ điều gì mới.
- Làm việc với tài liệu: Có thể là Next.js, Webpack, React, TypeScript hoặc bất kỳ tool nào khác. Ví dụ, React có nhiều hooks mà hầu hết chúng ta chưa từng sử dụng. Dành thời gian để phát triển một tính năng chính hoặc thiết lập một dự án liên quan đến nội dung của tài liệu đã tham khảo.
- Kiểm tra hiệu suất code với profilers, debuggers, time measurements và overblown test: Cố gắng hướng tới khả năng đọc tốt cũng như hiệu suất trước khi phát hành một tính năng chính. Kiểm tình huống xấu nhất để xem liệu code của bạn có phải là nguyên nhân gây ra lỗi hay không?
- Không nên quá phụ thuộc vào NPM: hầu hết các thư viện đơn giản nhất đều dễ dàng tự triển khai. Nếu bạn sử dụng thư viện không có tài liệu hướng dẫn, hãy đọc source code.
- Phân tích tác động kích thước bundle: Bạn không cần nhập toàn bộ thư viện lodash cho một lệnh gọi _.omit. Việc tải một bundle lớn sẽ làm chậm đáng kể quá trình tải ban đầu của ứng dụng.
Định dạng code và style
Đây thường là một khía cạnh bị bỏ qua nhưng rất quan trọng khi lập trình. Bất kể làm việc một mình hay theo nhóm, bạn cũng cần tuân thủ một số nguyên tắc sau:
- Sử dụng ESLint và Prettier sẽ giúp bạn tập trung vào chức năng của đoạn code. Bạn sẽ không bao giờ bị báo lỗi khi kiểm tra CI tự động bởi vì thiếu dấu phẩy ở cuối. Ngoài ra, bằng cách sử dụng các giá trị mặc định của Prettier, bạn có thể kết thúc code-style arguments một lần và mãi mãi.
- Đặt tên mô tả (descriptive name) cho các biến sẽ giúp bạn hiểu ý nghĩa của nó là gì ngay khi đọc tên. Cân nhắc giữa buttonDomElem với el, cái nào sẽ dễ hiểu hơn? Hoặc bạn cũng có thể sử dụng isUserDataLoading. Các tiền tố biến boolean với động từ như is hoặc has và đừng sợ nếu như tên biến dài hơn. Các IDE sẽ gợi ý tên và vim users sẽ nhanh chóng sao chép nó.
- Sử dụng ngắt dòng: ngay cả bên trong một function hoặc object declaration, bạn cũng nên sử dụng single-line breaks mà nó để lại nếu điều đó làm cho văn bản dễ đọc hơn.
Comment trong code và các tài liệu nội tuyến
Bạn có thể thay thế sử dụng TypeScript bằng TSDoc hoặc JSDoc mặc dù nó không được khuyến khích. Sử dụng JSdoc kết hợp với TypeScript để giúp mọi người hiểu điều gì đang xảy ra khi thực hiện lệnh gọi của bạn ở các vị trí khác nhau của ứng dụng. Bạn có thể sử dụng định dạng từ khóa hoặc tài liệu của mình miễn là nó dễ đọc.
Khi viết các phần code phức tạp, hãy luôn đặt mục tiêu viết thật dễ hiểu để sau 2 năm, khi quay lại một dự án để sửa lỗi, bạn có thể hiểu mọi thứ hoạt động như thế nào mà không cần đọc toàn bộ mã nguồn.
Tạo ra các bản thử nghiệm hữu ích và ý nghĩa
Bạn đã từng nghe đến mô hình phát triển dựa trên thử nghiệm ( test-driven development – TDD) chưa? Thông thường, các lập trình viên sẽ chia làm 2 nhóm, một số sẽ là theo TDD và số còn lại sẽ coi thường TDD.
Thực tế, TDD sẽ phù hợp hoặc không phù hợp trong một số trường hợp khác nhau. Ví dụ nếu bạn phát triển một tính năng backend quan trọng thì TDD sẽ có ích. Nhưng nếu bạn tạo front-end cho dashboard app thì TDD có thể làm chậm tốc độ của bạn. Vì vậy, trước khi sử dụng, bạn cần cân nhắc trường hợp đó ưu điểm có nhiều hơn nhược điểm hay không.
Ví dụ kiểm tra backend tests về output của unit test trong Node.js backend app
- Unit testing là phương pháp thử nghiệm cho hầu hết các trường hợp sử dụng. Unit test cho frontend app có thể đánh giá các thành phần phức tạp như bố cục, modal dialogs, wizards, các forms được xác thực nhiều bước từ client-side,…
- End-to-end (E2E) testing: là một phương pháp kiểm thử để kiểm tra luồng hoạt động của ứng dụng từ đầu đến cuối. Mục đích của thử nghiệm E2E là mô phỏng kịch bản của người dùng thực, xác nhận hệ thống đang được thử nghiệm và các thành phần của nó để tích hợp và toàn vẹn dữ liệu.
Tập trung vào việc làm cho các test trở nên hữu ích. Không cần tốn thời gian viết unit test cho các button đơn giản và chức năng tiện ích phụ. Điều này sẽ phá vỡ test cho các tính năng bạn đang có.
Nhiều managers và product owners hoặc thậm chí là các senior developer sẽ cảm thấy khó chịu với các số liệu về mức độ phù hợp của code. Code coverage là một quy tắc chung, không phải là một quy tắc bắt buộc. Bằng cách thực thi tỷ lệ Code coverage cao, các lập trình viên phải sử dụng thư viện của bên thứ 3 để tiết kiệm thời gian.
Sử dụng prototypes hoặc MVPs
Dọn dẹp và tái cấu trúc các phần nhỏ hơn sau mỗi tính năng chính
Quy tắc này chỉ có ý nghĩa nếu dự án của bạn sẽ kéo dài hơn một vài tháng. Khi bạn hoàn thành một tính năng chính, hãy thay đổi suy nghĩ của mình và quay lại với nó với một góc nhìn khác. Tìm ra những bottlenecks, caveats và khu vực cần cải thiện, đánh giá những gì cần phải thay đổi và khi nào nên thay đổi
Ví dụ, khi bạn tạo một tập hợp các function, đó là các thuộc tính của một đối tượng JS đã export. Bạn không cần import object mỗi lần vì nó ngăn cản trình garbage collector tích hợp của JavaScript để thực hiện công việc miễn là bạn giữ tham chiếu về nó.
Với một số pure functions, bạn hãy thử 70 impure functions và import 6 vị trí, ứng dụng của bạn sẽ chậm hơn đáng kể. Thay vào đó, hãy xuất các file nhỏ hơn để giảm thiểu rủi ro mang theo hàng chục nghìn dòng mã không sử dụng.
Sử dụng prototypes để test features và tránh tái cấu trúc vô tận (endless refactor)
Sử dụng prototypes để test features là cách để giúp bạn dễ tìm thấy được những đoạn “code xấu”. Ví dụ: nếu lần đầu tiên làm việc với WebRTC, hãy thực hiện nó ở dạng prototype. Sau khi đã xác minh rằng nó đáp ứng các yêu cầu của bạn, đã đến lúc viết code thực sự. Tại thời điểm này, bạn nên có một tầm nhìn rõ ràng hơn nhiều về cách bạn muốn code của mình trông như thế nào và hoạt động ra sao.
Như vậy, qua bài viết này, chắc hẳn các lập trình viên cũng đã bỏ túi cho mình được những kinh nghiệm giá trị trong việc duy trì code JavaScript. Hy vọng những kiến thức này có thể giúp ích cho bạn trong các dự án tương lai.