Avada Coding Standard
Giới thiệu tổng quan
Avada Development team là team phát triển sản phẩm cho Avada dựa trên các công nghệ mới như NodeJS, React, Firebase Google Cloud. Vì các công nghệ còn rất mới nên việc tiếp cận với các chuẩn về coding thời gian đầu gặp nhiều trở ngại và thiếu tính nhất quán. Do đó, trong documentation này, chúng ta sẽ cùng thống nhất lại các coding standard mà team Avada nhằm mục đích giúp quá trình viết code được đồng nhất về mặt cú pháp, thiết kế, tính sử dụng lại và hiệu quả tối ưu nhất.
Các phần chính
Trong document này, chúng ta sẽ chia ra làm 5 phần chính gồm:
- Thống nhất coding standard cho JS và Nodejs.
- Thống nhất coding standard cho ReactJS
- Thống nhất coding standard và hiệu năng khi sử dụng Firebase Cloud.
- Thống nhất một số quy tắc clean code chính
- 1 số vấn đề về key và bảo mật
Code style standard cơ bản (JS)
Sử dụng chuẩn của Eslint và Prettier
Trong bất kì project nào của Avada đều đã có cài sẵn prettier
và eslint
trong list dependency, trong quá trình code m.n lưu ý sử dụng prettier để format lại code, bằng gõ npm run eslint-fix
để chạy toàn bộ project.
Ngoài ra nếu sử dụng Webstorm, có thể sử dụng nút chạy eslint ngay trong IDE. Nút này cũng có thể sử dụng với cả thư mục.
Optimize Imports
Sau nhiều lần thêm thắt chỉnh sửa code có thể dẫn đến việc các phần import bị thừa, cần phải được xóa đi để code được clean, không bị thừa thãi. Tuy nhiên việc làm thủ công có thể dẫn đến việc mất thời gian, không cần thiết. Ở đây khuyên nên sử dụng tính năng Optimize imports của Webstorm để tiết kiệm thời gian.
Để sử dụng, chúng ta chọn vào thư mục src
của project, sau đó chọn Optimize imports. Lưu ý chỉ nên optimize import ở thư mục source code, tránh optimize import chạy ở cả project, bao gồm node_modules sẽ dẫn đến mất thời gian.
Đặt tên hàm và biến.
Sử dụng camelCase cho function, variable và properties.
Trong việc khai báo function, variable hay properties phải sử dụng camelCase, không được viết thường hay viết hoa không đồng nhất, dẫn đến khó hiểu cho người đọc. Đối với việc đặt tên hàm chỉ có ngoại lệ với ReactJS component. Điều này ta sẽ đề cập sau.
Sai:
Đúng:
Sử dụng UpperCamelCase cho class
Tuy ở trong NodeJS, chúng ta sử dụng Functional Programming (FP), nhưng cũng ko ít trường hợp ta vẫn phải khai báo class. Và đương nhiên là vẫn sẽ phải theo chuẩn. Với class. Chúng ta phải sử dụng UpperCamelCase và ngược lại không dùng UpperCamelCase với variable, hay function, sẽ gây ra sự khó hiểu cho người đọc code.
Sử dụng UPPERCASE cho hằng số (constant)
Nếu có một giá trị không đổi trong code, cần phải refactor biến này thành constant, việc đặt tên cho constant phải theo chuẩn sử dụng UPPERCASE.
Đặt tên hàm và biến có ý nghĩa, tránh việc đặt tên khó hiểu
Việc đặt tên có vẻ sẽ là việc gây bí cho khá nhiều dev vì nhiều khi vốn từ thiếu, khó tìm cách đặt tên sao cho dễ hiểu. Tuy nhiên, đây là một standard cần tuân theo nên khi code, mọi người cần chịu khó đặt tên cho đúng ngữ cảnh, rèn luyện dần dần. Một số quy tắc cơ bản trong việc đặt tên biến như sau:
- Tên của function phải bắt đầu bằng động từ. Thí dụ: hàm phải tên là doSomething, chứ ko phải something, hay somethingDo.
- Tên của boolean phải bắt đầu bằng is, has. Ví dụ như:
const isActive = true
,const hasPaid = false
. - Tên của variable khác nên là danh từ.
Sử dụng const thay vì let
Trong functional programming nói chung hay NodeJS nói riêng, việc hạn chế gán lại giá trị cho 1 biến là cần thiết, nó giúp lập trình viên sẽ chỉ có thể khai báo 1 biến với 1 tên 1 lần mỗi block.
Ví dụ, việc sử dụng const như cách dưới và hạn chế việc code thiếu tường minh và buộc lập trình viên phải đặt tên biến có ý nghĩa hơn. Đây cũng là ý avoid mutations trong functional programming.
Import ở đầu file, không import ở trong thân hàm
Rule này áp dụng với bất kì ngôn ngữ lập trình nào, toàn bộ việc import các module khác từ thư viện hay trong source code đều phải ở phía trên cùng của file, không được viết trong thân hàm hay phía giữa file, dẫn đến khó tìm, performance leakage.
Sử dụng toán tử === thay vì ==
Toán tử === sẽ check cả việc so sánh hai giá trị có cùng loại dữ liệu chứ không chỉ dừng lại ở giá trị không thôi. Ví dụ sau:
Sử dụng async/await thay vì Promise hay callback
Trong quá trình code, việc NodeJS từ bản 8 đã hỗ trợ async/await, còn ở phía browse đã có Babel transpile code, nên việc sử dụng async await là cần thiết, giúp code bất đồng bộ dễ đọc hơn.
Tìm hiểu sự tiến hóa trong cách tiếp cập bất đồng bộ tại bài guide này.
Sử dụng arrow function: () =>
Từ bản cập nhật ES6, arrow function đã trở thành 1 tính năng mới phổ biến trong JS và NodeJS. Việc sử dụng arrow function giúp code gọn hơn. Nhìn vào ví dụ phía dưới để thấy thu gọn code sau khi 3 lần sử dụng arrow function.
Ngoài ra, khi return giá trị trực tiếp, arrow function còn có cú pháp viết tắt như sau. Cách viết này sẽ được thấy nhiều ở trong React.
Hạn chế nhiều parameter cho 1 functions
Nếu một hàm có nhiều hơn 3 params phải chuyển qua input param kiểu object và destruct. Với cách viết này, việc truyền vào sẽ ko phải quan tâm tới thứ tự truyền vào param như cách 1 giúp cho việc sử dụng các hàm có nhiều param trở nên dễ sử dụng hơn. Quy tắc này áp chung cho JS và NodeJS, và cũng như React.
Đặt param mặc định cho function khi là boolean
Khi giá trị mặc định là boolean, chúng ta phải luôn ưu tiên đặt giá trị mặc định là false
. Như ví dụ dưới đây, nếu trong trường hợp NoSQL database, field hasPaid trong document user không tồn tại dẫn đến việc truyền vào param hasPaid có giá tị undefined. Với undefined truyền vào giá trị mặc định sẽ được sử dụng, nên do đó hàm dưới nghiễm nghiên trả về kết quả user có thể sử dụng dịch vụ mà chưa trả tiền.