Series lập trình với dữ liệu Array và Object trong Javascript - Xử lý dữ liệu như thế nào cho tốt?

Series lập trình với dữ liệu Array và Object trong Javascript - Xử lý dữ liệu như thế nào cho tốt?

Những mẩu tin ngắn hàng ngày dành cho bạn
  • Tin tức sáng sớm, mọi người còn nhớ vụ kiện của Ryan Dahl - hay nói đúng hơn là của nhóm Deno với Oracle về cái tên JavaScript không?

    Oracle đã phản hồi rằng họ không từ bỏ cái tên JavaScript đâu 🫣

    https://x.com/deno_land/status/1876728474666217739

    » Xem thêm
  • Mọi người nghỉ tết sớm rồi hay sao á? Nhiên cái nguyên tuần nay traffic giảm hẳn luôn 😳. Một mình tuôi nói kể cũng buồn, ai đi ngang qua đọc được thì thả một "còm men" cho vui cửa vui nhà nha. Nói gì cũng được vì ẩn danh cả mà 😇🔥

    » Xem thêm
  • Có người hỏi mình là cập nhật tin tức ở đâu mà nhanh thế, hay là kiếm ra được mấy cái tools, mấy cái projects... ở đâu mà nhiều thế? Thì có một nguồn xa tận chân trời mà gần ngay trước mắt đó chính là trang Github Trending này đây.

    Trang này thống kê lại các kho lưu trữ đang có lượt "star" nhiều nhất theo ngày/tuần/tháng. Nó còn xem theo được ngôn ngữ cơ, mà mỗi ngôn ngữ lại kiểu như một chủ đề á. Ví dụ Python thì hót rần rần về AI, LLMs..., Rust thì bao tools siêu mạnh, còn Go thì... đồ chơi liên tục 😁. Trong khi JavaScript 🫣😑

    » Xem thêm

Vấn đề

Lưu ý: Bài viết dưới đây là những quan điểm cá nhân của tôi về vấn đề xử lý dữ liệu. Điều đó cũng bao gồm những kinh nghiệm của tôi trong các dự án thực tế. Các bạn đọc có thể mang tính chất tham khảo hoặc cũng có thể để lại những ý kiến để mọi người cùng thảo luận nhé.

Ở bài viết trước tôi có giới thiệu cho các bạn một vài cách xử lý dữ liệu thì bài viết ngày hôm nay tôi sẽ tập trung hơn vào việc tôi đã xử lý dữ liệu trong Javascript như thế nào, cũng như cách viết code dễ đọc hơn cho việc bảo trì dự án sau này.

Viết code để chạy được thì nhanh nhưng viết để dễ dàng trong bảo trì sau này đòi hỏi người viết phải có được những kinh nghiệm nhất định, đồng thời việc tổ chức mã, luồng cũng sẽ tốn nhiều thời gian hơn một chút. Thời gian để bảo trì một dự án thường sẽ lớn hơn nhiều so với thời gian để phát hành sản phẩm lần đầu tiên, chưa kể sẽ có những người mới tham gia vào dự án. Vì thế nếu tổ chức mã của bạn tốt sẽ tiết kiệm được kha khá thời gian sau này.

Xử lý dữ liệu là điều thường xuyên trong các chức năng của dự án, các bạn có thể hiểu nó bao gồm các hành động như lọc, ánh xạ, biến đổi dữ liệu trong các tập dữ liệu Array hay Object. 4 kĩ thuật tôi thường hay sử dụng dưới đây góp phần giữ cho code của tôi được rõ ràng hơn.

Bất biến

Bất biến có nghĩa là một khi đã khai báo biến rồi thì tuyệt đối không được thay đổi biến đó nữa. Nếu muốn sửa đổi dữ liệu thì hãy sao chép chúng sang một biến khác. Mới nghe thì có vẻ điều này không hợp lý cho lắm bởi biến trong các ngôn ngữ lập trình được phép thay đổi, gán đi gán lại một cách bình thường. Điều này cũng làm tăng hiệu năng, tiết kiệm bộ nhớ hơn so với việc phải tạo thêm nhiều biến nữa.

Trong Javascript không có định nghĩa kiểu của dữ liệu, việc khai báo một biến với từ khóa var hoặc let giúp cho chúng ta có thể dễ dàng thay đổi dữ liệu hoặc thâm chí là kiểu dữ liệu của nó sau này. Điều này tạo nên sự linh hoạt nhưng tác hại đằng sau sự linh hoạt đó có vẻ là nhiều hơn.

Trong một đoạn mã với hàng chục, hàng trăm dòng code thì việc thay đổi dữ liệu của một biến đôi khi sẽ gây khó khăn trong theo dõi giá trị của biến, bạn sẽ phải phân vân việc liệu giá trị của biến bị thay đổi ở đâu không hay thay đổi những gì... Để giải quyết vấn đề này hãy cố gắng sử dụng khai báo const nhiều nhất có thể, khi sử dụng const bạn sẽ không gán lại giá trị cho biến đó được nữa.

Nhưng mình const là chưa đủ, trong Javascript các kiểu dữ liệu không nguyên thủy như Array, Object... có tính tham chiếu. Dữ liệu đó khi được gán vẫn có thể thay đổi được giá trị của các phần tử, thuộc tính bên trong nó. Vì thế đôi khi chẳng may bạn sửa dữ liệu tham chiếu, các biến khác cũng vô tình bị thay đổi theo. Để tìm hiểu kĩ hơn, các bạn có thể đọc bài viết Đôi điều về Object Reference trong Javascript. Nhiều lúc quên thật phiền toái! của tôi trên estacks.

Thay vì update trực tiếp vào dữ liệu tham chiếu, chúng ta nên sao chép "sâu" (deep copy) dữ liệu có tính chất tham chiếu sang một biến khác để xử lý. Tránh việc thay đổi gây ra những lỗi tiềm ẩn sau này.

Tập trung vào làm gì thay vì làm như thế nào

Để giải thích cho điều này, tôi sẽ lấy một ví dụ về một hàm lấy ra thuộc tính name trong một mảng dữ liệu:

const users = [
  {
    name: "A",
    age: 18
  },
  {
    name: "B",
    age: 19
  },
  {
    name: "C",
    age: 20
  },
];

// cách thứ nhất viết một hàm dùng map để lấy ra name
function usersWithName(users) {
  return users.map(function(user) {
    return {
      name: user.name,
    };
  });
};

// cách thứ hai, vẫn dùng map nhưng ứng dụng curry function
const get = (attribute) => (data) => data[attribute];
const usersWithName = users.map(get("name"));

Trong ví dụ tôi có sử dung Curry function, nếu bạn chưa biết về curry function cũng như ứng dụng của nó thì có thể đọc thêm tại Curry function là gì? Một món "cà ri" ngon và làm sao để thưởng thức nó?.

Trở lại với ví dụ trên, tôi có hai cách viết để cùng đạt được kết quả.

Cách thứ nhất là cách viết thông thường, tôi viết theo dòng suy nghĩ cần phải làm từng bước để có kết quả.

Cách thứ hai, thay vì viết theo dòng suy nghĩ thì tôi tạo ra một hàm get dùng để lấy dữ liệu của thuộc tính trong một object, sau đó đưa nó vào hàm map.

Bằng cách thứ hai, nếu chúng ta tạo thói quen định nghĩa những hàm như get sẽ giúp tạo sự thống nhất trong toàn dự án mặt khác người đọc khi thấy get họ cũng hiểu được đoạn mã đó đang làm gì.

Mã tái sử dụng càng nhiều càng tốt

Hãy cố gắng tạo ra những đoạn mã chỉ tập trung vào một chức năng nào đó sẽ giúp cho mã của bạn có thể tái sử dụng lại. Đồng thời nó cũng tạo sự thống nhất trong toàn dự án, điều đó cũng đồng nghĩa với việc khi bạn thấy nó, bạn có thể biết được nó đang làm gì.

Nhìn vào ví trụ trên ở cách thứ hai, hàm get có thể tái sử dụng nhiều lần, thay vì get("name") tôi có thể get("age")... Hơn nữa mỗi khi nhìn thấy hàm get chúng ta có thể biết ngay là nó "lấy giá trị của thuộc tính" thay vì phải đọc một đoạn code dài như cách một để hiểu được người viết đang muốn làm gì.

Áp dụng những thư viện xử lý dữ liệu phổ biến

Những lợi ích của việc tạo ra những đoạn mã có thể tái sử dụng được nhiều lần đã được cộng đồng phát hiện từ rất lâu về trước. Họ đã tạo ra những thư viện gồm có tập hợp của các hàm giúp chúng ta trong việc xử lý dữ liệu. Một trong số đó có thể kể đến như underscore, lodash, ramda... Chúng cũng được sử dụng rộng rãi trong các dự án trên github, cũng như có số lượng commit và collaborators rất lớn.

Một ví dụ như trong lodash, có đến gần 50 hàm tiện ích để xử lý dữ liệu là Object. Trong đó có cả những hàm tương tự như get ở trong ví dụ trên của tôi và hầu như bạn muốn làm gì cũng có hàm có thể đáp ứng.

Ví dụ tôi sẽ kết hợp các hàm trong lodash để giải quyết ví dụ ban đầu, hơn nữa còn thêm một điều kiện là thứ tự name được lấy ra sắp xếp theo mức độ giảm dần của age:

_.chain(users).orderBy("age", "desc").map("name").value();
Cao cấp
Hello

5 bài học sâu sắc

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (0)

Nội dung bình luận...
Bấm hoặc cuộn mạnh để sang bài mới