Các cách thực tế để viết ngôn ngữ lập trình JavaScript tốt hơn (P2)
Chúng ta cần thực hiện code JavaScript một cách logic, chính xác. Đồng thời, bạn cần phải cố gắng để biến những thứ phức tạp thành thứ mà con người có thể hiểu được.
Table of Contents
>> Các cách thực tế để viết ngôn ngữ lập trình JavaScript tốt hơn (P1)
Trong phần trước chúng ta đã tìm hiểu 03 cách để cải thiện các dòng code JavaScript của bạn. Phần này, FUNiX sẽ chia sẻ những phương pháp đơn giản nhưng sẽ mang lại hiệu quả cao trong quá trình viết code. Nếu bạn chưa đọc phần 01 thì có thể tham khảo tại đây.
Sử dụng vòng lặp for (for – loop)
Nhiều lập trình viên thường tối ưu hóa công việc bằng cách viết song song nhiều ứng dụng với nhau. Nếu bạn có bốn lõi (core) khả dụng, nhưng code của bạn chỉ có thể dùng một lõi duy nhất thì 75% tiền năng đang bị lãng phí. JavaScript là ngôn ngữ lập trình đơn luồng, nó không chạy trên nhiều lõi.
Mặc dù ngôn ngữ JavaScript không hoạt động song song, nhưng chúng sẽ cần thực hiện đồng thời với nhau. Khi bạn gửi một yêu cầu HTTP có thể mất vài giây cho đến vài phút. Vì vậy, nếu JavaScript ngừng thực hiện code cho đến khi có kết quả thì ngôn ngữ sẽ không thể dùng được nữa.
JavaScript giải quyết vấn đề này bằng một event loop. Event loop sẽ lặp lại hành động đã đăng ký, thực hiện chúng bằng cách sắp xếp lệnh hoặc yêu cầu theo thứ tự ưu tiên. Với tính năng này sẽ cho phép hàng nghìn yêu cầu HTTP hoặc đọc nhiều tệp cùng một lúc. Nhưng bạn cũng cần lưu ý rằng, JavaScript chỉ thực hiện chức năng này nếu người dùng sử dụng đúng tính năng. Chúng ta xem một ví dụ đơn giản về vòng lặp for:
let sum = 0;
const myArray = [1, 2, 3, 4, 5, … 99, 100];
for (let i = 0; i < myArray.length; i += 1) {
sum += myArray[i];
}
Vòng lặp for là một trong những cấu trúc song song ít tồn tại trong lập trình. Nhà lập trình sẽ phải dành nhiều tháng để chuyển đổi R vòng lặp for truyền thống thành code song song. Nó thực sự là một vấn đề bất khả thi, chúng ta chỉ chờ hệ thống Deep Learning (học sâu) để cải thiện. Khó khăn của việc song song hóa vòng lặp for bắt nguồn từ một vài biến có vấn đề. Vòng lặp này rất hiếm nhưng nếu xuất hiện chúng sẽ khiến việc phân rã trở nên khó khăn:
let runningTotal = 0;
for (let i = 0; i < myArray.length; i += 1) {
if (i === 50 && runningTotal > 50) {
runningTotal = 0;
}
runningTotal += Math.random() + runningTotal;
}
Code ở trên sẽ chỉ tạo ra kết quả nếu nó được thực hiện theo thứ tự và lặp đi lặp lại. Nếu bạn đang cố gắng thực hiện nhiều lần lặp cùng một lúc, bộ xử lý có thể phân nhánh không đúng dựa trên giá trị không chính xác. Điều này làm cho kết quả không có hiệu lực. Trong JavaScript, vòng lặp for truyền thống chỉ nên dùng khi thực sự cần thiết. Nếu không, bạn hãy sử dụng cấu trúc sau:
- Map
// in decreasing relevancy :0
const urls = [‘google.com’, ‘yahoo.com’, ‘aol.com’, ‘netscape.com’];
const resultingPromises = urls.map((url) => makHttpRequest(url));
const results = await Promise.all(resultingPromises);
- map with index
// in decreasing relevancy :0
const urls = [‘google.com’, ‘yahoo.com’, ‘aol.com’, ‘netscape.com’];
const resultingPromises = urls.map((url, index) => makHttpRequest(url, index));
const results = await Promise.all(resultingPromises);
- for-each
onst urls = [‘google.com’, ‘yahoo.com’, ‘aol.com’, ‘netscape.com’];
// note this is non blocking
urls.forEach(async (url) => {
try {
await makHttpRequest(url);
} catch (err) {
console.log(`${err} bad practice`);
}
});
Đây sẽ là một cải tiến cho vòng lặp for truyền thống. Bởi vì cấu trúc như map sẽ lấy tất cả phần tử, gửi chúng dưới dạng event riêng lẻ cho hàm map do người dùng xác định. Hầu hết lần lặp riêng lẻ sẽ không phụ thuộc vào nhau, nên chúng chạy đồng thời với nhau. Có nghĩa là ta không thể thực hiện được điều tương tương tự với vòng lặp for. Bạn theo dõi ví dụ dưới đây để hiểu rõ hơn:
const items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
async function testCall() {
// do async stuff here
}
for (let i = 0; i < 10; i += 1) {
testCall();
}
Như bạn thấy, dù có vòng for thì dòng code vẫn thực hiện hợp lệ nhưng chắc chắn sẽ khá phức tạp. Tiếp theo chúng ta sẽ so sánh nó với phiên bản map dưới đây:
const items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
items.map(async (item) => {
// do async stuff here
});
Lợi ích của map được thể hiện rõ ràng nhất khi bạn thực hiện chặn cho đến khi tất cả đồng bộ riêng lẻ ngừng thực hiện. Với vòng lặp for, bạn sẽ phải tự quản lý mảng. Dưới đây là một ví dụ khi sử dụng map:
const items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const allResults = await Promise.all(items.map(async (item) => {
// do async stuff here
}));
Có rất nhiều trường hợp for sẽ hoạt động tốt hơn map hoặc forEach. Nhưng việc mất một vài chu kỳ sẽ giúp việc thực hiện APT được xác định rõ ràng. Do vậy, bất kỳ cải tiến nào trong tương lai đối với việc triển khai biến truy cập dữ liệu sẽ mang lại lợi ích cho code của bạn. Chúng ta cũng thấy rằng vòng lặp for quá chung chung để tối ưu hóa cho cùng một biến.
Sử dụng Lint và Style (thuộc tính) nhất quán
Nếu code không có một style nhất quán, nó sẽ cực kỳ khó đọc và khó hiểu. Do vậy, vấn đề quan trọng của việc viết code cấp cao bằng bất kỳ ngôn ngữ nào là phải có một Style nhất quán và hợp lý. Hệ sinh thái JavaScript rất phong phú nên có rất nhiều lựa chọn cho Linter và style cụ thể. Chúng ta cần nhấn mạnh rằng, việc dùng một linter và style nhất quán trong suốt quá trình viết quan trọng hơn rất nhiều việc bạn chọn linter / style nào để viết.
Nhiều lập trình viên thắc mắc rằng, họ nên sử dụng eslint hay prettier. Nhưng thực tế chúng lại phục vụ cho mục đích khác nhau nên ta sẽ tận dụng cả hai. Eslint là một linter truyền thống trong phần lớn thời gian, nó sẽ chủ yếu đánh giá tính đúng đắn của code thay vì xem xét liên quan đến style. Ví dụ: Chúng ta triển khai eslint với quy tắc AirBNB và đoạn code sau sẽ buộc bộ ghép nối bị thất bại:
var fooVar = 3; // airbnb rules forebid “var”
Đây cũng sẽ là cách mà eslint thêm giá trị vào chu trình phát triển code của bạn. Về bản chất nó sẽ đảm bảo code luôn thực hiện theo quy tắc cần thiết.
Prettier là một trình định dạng code, nó sẽ xét nhiều về tính đồng bộ và nhất quán của code hơn là tính đúng đắn của code. Prettier không quan tâm đến việc bạn sử dụng var, map hay forEach; nhưng nó sẽ tự động căn chỉnh tất cả dấu ngoặc trong code. Trong quá trình làm việc, lập trình viên cần hoàn thiện sản phẩm đẹp mắt và gọn gàng hơn trước khi gửi sản phẩm lên Git. Trong nhiều trường hợp, việc để Prettier tự động chạy trên mỗi lần cam kết một repo là rất hợp lý. Điều này đảm bảo rằng tất cả code dễ kiểm soát và có cấu trúc nhất quán.
Kiểm tra code của bạn
Thực hiện kiểm tra là phương pháp gián tiếp nhưng mang lại hiệu quả cao khi viết code. Hiện nay, có nhiều công cụ kiểm tra hiệu quả và được thiết lập ngay trong hệ sinh thái JavaScript. Vì vậy, việc lựa chọn công cụ chủ yếu phụ thuộc vào sở thích cá nhân.
Trình kiểm tra Ava
Đây là trình kiểm tra được thiết kế đơn giản là framework cung cấp cấu trúc và tiện ích ở mức cao. Chúng thường được sử dụng cùng với công cụ kiểm tra cụ thể khác. Bạn có thể thay đổi công cụ dựa trên nhu cầu kiểm tra của bạn.
Ava là trình kiểm tra cân bằng giữa sự mô tả và tính ngắn gọn của code. Nhiều lập trình viên ưu tiên sử dụng Ava, bởi vì nó được thiết kế song song và riêng biệt. Ngoài ra, các lần kiểm tra cũng chạy nhanh hơn giúp tiết kiệm thời gian và tiền bạc cho lập trình viên. Ava được thiết kế với rất nhiều tính năng mang lại sự thuận tiện cho người dùng. Bên cạnh đó, FUNiX đã tổng hợp lựa chọn thay thế cho Ava như: Jest, Mocha, Jasmine
Spies and Stubs – Sinon
Spies cung cấp chức năng phân tích hàm. Ví dụ như: Số lần một hàm được gọi, chúng được gọi bằng gì và rất nhiều dữ liệu khác nữa.
Sinon là một thư viện thực hiện nhiều hoạt động, nhưng thực tế chỉ có một số tính năng thực sự mang lại hiệu quả. Spies and Stubs (là bộ tính năng phong phú nhưng cú pháp ngắn gọn) là một trong những ưu điểm vượt trội của Sinon. Điều này đặc biệt quan trọng với tệp sơ khai, vì chúng tồn tại như một phần để tiết kiệm dung lượng.
Mocks – Nock
HTTP Mocking là quá trình giả mạo một số phần của quy trình yêu cầu HTTP, giúp người kiểm tra đưa chúng vào giao diện tùy chỉnh để mô phỏng hành vi của máy chủ.
Nock có thể trực tiếp ghi đè request cài đặt sẵn của nodeJavaScript và chặn yêu cầu HTTP gửi đi. Điều này lại cho phép người dùng kiểm soát hoàn toàn phản hồi.
Tự động hóa web – Selenium
Selenium là trình phổ biến nhất giúp tự động hóa Web, nên nó có hẳn một cộng đồng lớn và một kho tài nguyên khổng lồ để bạn tự do tham khảo. Nhưng đây là một công cụ khá phức tạp, nên việc bạn sử dụng thành thạo nó không phải chuyện dễ dàng. Đồng thời, khi sử dụng nó lại bị phụ thuộc rất nhiều vào thư viện bên ngoài. Bạn có thể lựa chọn Selenium khi đang thực hiện dự án tự động hóa Web cấp doanh nghiệp, còn không thì có thể bỏ qua công cụ này.
Bạn có thể thay thế Selenium bằng công cụ khác như: Cypress, PhantomJS
Viết JavaScript là một hành trình không bao giờ kết thúc
Như với hầu hết ngôn ngữ lập trình khác, nếu muốn viết JavaScript tốt hơn bạn sẽ cần thực hành liên tục. Code luôn có thể thực hiện tốt hơn, nên bạn đừng bao giờ đặt giới hạn cho mục tiêu của mình. Nếu có ý tưởng cho một tính năng độc đáo, ta cần bắt tay vào học hỏi và thực hiện nó. Sau đó, bạn có thể thực hiện vô số bài kiểm tra để tạo ra sản phẩm hoàn hảo nhất.
Đây thực sự là một hành trình không bao giờ kết thúc nếu bạn đã lựa chọn lập trình con đường để phát triển trong tương lai. Đôi khi lập trình viên cảm thấy quá tải vì quá nhiều vấn đề đối với code. Nhưng áp lực là điều tất yếu cho quá trình phát triển của bạn.
Hãy chia ra những bước nhỏ và kiên định với mục tiêu của mình. Những áp lực và sự chán trường chỉ là cảm giác nhất thời. Nếu vượt qua, bạn sẽ trở thành một chuyên gia về JavaScript. Những nỗ lực sẽ được đền đáp bằng các dòng code đẹp, ngắn gọn và đặc biệt sản phẩm bạn tạo ra sẽ mang lại giá trị cho khách hàng.
Hy vọng thông tin mà FUNiX cung cấp sẽ mang lại kiến thức hữu ích cho bạn. Ngoài ra, bạn có thể truy cập Website funix.edu.vn để tìm hiểu nhiều kiến thức thú vị về lập trình.
Công Sơn
Nguồn tham khảo: https://stackoverflow.blog/2019/09/12/practical-ways-to-write-better-javascript/
Bình luận (0
)