Archimedes cùng lối suy nghĩ đầu vào - đầu ra trong lập trình

Archimedes cùng lối suy nghĩ đầu vào - đầu ra trong lập trình

Tin ngắn hàng ngày dành cho bạn
  • Hơn 1 tuần nay mình không đăng bài, không phải không có gì để viết mà đang tìm cách để phân phối nội dung có giá trị hơn trong thời đại AI đang bùng nổ mạnh mẽ như thế này.

    Như từ hồi đầu năm đã chia sẻ, số lượng người truy cập vào trang blog của mình đang dần ít đi. Khi xem thống kê, lượng người dùng trong 6 tháng đầu năm 2025 đã giảm 30% so với cùng kì năm ngoái, 15% so với 6 tháng cuối năm 2024. Như vậy một sự thật là người dùng đang rời bỏ dần đi. Nguyên nhân do đâu?

    Mình nghĩ lý do lớn nhất là thói quen của người dùng đã thay đổi. Họ tìm thấy blog chủ yếu qua các công cụ tìm kiếm, trong đó lớn nhất là Google. Gần 1/2 số lượng người dùng quay trở lại blog mà không cần thông qua bước tìm kiếm. Đó là một tín hiệu đáng mừng nhưng vẫn không đủ để tăng lượng người dùng mới. Chưa kể giờ đây, Google đã ra mắt tính năng AI Search Labs - tức là AI hiển thị luôn nội dung tổng hợp khi người dùng tìm kiếm, điều đó càng khiến cho khả năng người dùng truy cập vào trang web thấp hơn. Một điều thú vị là khi Search Labs được giới thiệu, thì các bài viết bằng tiếng Anh đã soán ngôi trong bảng xếp hạng truy cập nhiều nhất.

    Một bài viết của mình thường rất dài, có khi lên đến cả 2000 chữ. Mà để viết ra được một bài như thế tốn nhiều thời gian. Nhiều bài viết ra chẳng có ai đọc là điều bình thường. Mình biết và chấp nhận vì không phải ai cũng gặp phải vấn đề đang nói đến. Viết đối với mình như một cách để rèn luyện sự kiên nhẫn và cả tư duy. Viết ra mà giúp được cả ai đó là một điều tuyệt vời.

    Vậy nên mình đang nghĩ sẽ tập trung vào nội dung ngắn và trung bình để viết được nhiều hơn. Nội dung dài chỉ khi muốn viết chi tiết hoặc đi sâu về một chủ đề nào đó. Nên là đang tìm cách thiết kế lại trang blog. Mọi người cùng chờ nha 😄

    » Xem thêm
  • CloudFlare đã giới thiệu tính năng pay per crawl để tính phí cho mỗi lần AI "cào" dữ liệu trên trang web của bạn. Là sao ta 🤔?

    Mục đích của SEO là giúp các công cụ tìm kiếm nhìn thấy trang web. Khi người dùng tìm kiếm nội dung mà có liên quan thì nó hiển thị trang web của bạn ra kết quả tìm kiếm. Điều này gần như là đôi bên cùng có lợi khi Google giúp nhiều người biết đến trang web hơn, còn Google thì được nhiều người dùng hơn.

    Bây giờ cuộc chơi với các AI Agents thì lại khác. AI Agents phải chủ động đi tìm kiếm nguồn thông tin và tiện thể "cào" luôn dữ liệu của bạn về, rồi xào nấu hay làm gì đó mà chúng ta cũng chẳng thể biết được. Vậy đây gần như là cuộc chơi chỉ mang lại lợi ích cho 1 bên 🤔!?

    Nước đi của CloudFlare là bắt AI Agents phải trả tiền cho mỗi lần lấy dữ liệu từ trang web của bạn. Nếu không trả tiền thì tôi không cho ông đọc dữ liệu của tôi. Kiểu vậy. Hãy chờ thêm một thời gian nữa xem sao 🤓.

    » Xem thêm
  • Lúc khái niệm "Vibe Code" bùng nổ mình cũng tò và tìm hiểu xem nó là gì. Hoá ra là chỉ cách lập trình mới: Lập trình viên ra lệnh và để cho LLM tự viết mã. Sau đó là hàng loạt các bài viết nói về cách họ đã xây dựng ứng dụng mà không cần phải viết một dòng mã nào, hoặc 100% là do AI viết...

    Mình không có ý kiến gì vì mỗi người một sở thích. Nhưng nếu tiếp xúc với nhiều thông tin như vậy thì ít nhiều thế hệ lập trình viên mới sẽ "ám ảnh". Khi làm việc với ngôn ngữ lập trình, chúng ta đang tiếp xúc ở bề nổi rồi. Đằng sau đó còn nhiều lớp khác che giấu sự phức tạp. Ví dụ biết viết JavaScript nhưng có biết nó chạy như thế nào không 🤔? Trên thực tế bạn chẳng cần phải biết nó chạy như thế nào mà chỉ cần biết cú pháp là viết được chương trình chạy ngon ơ.

    LLMs giờ đây lại thêm một lớp ảo hoá cho việc viết mã. Tức là nơi chúng ta không cần trực tiếp viết mà là ra lệnh. Làm việc sẽ nhanh hơn nhưng khi gặp vấn đề thì nhiều khả năng phải vận dụng kiến thức của tầng thấp hơn để giải quyết.

    Mình dùng Cursor, nhưng tính năng thích nhất và dùng nhiều nhất là Autocomplete & Suggestions. Thi thoảng cũng dùng Agents để bảo nó viết tiếp đoạn mã đang dở, thường thì nó làm rất tốt. Hoặc khi gặp lỗi thì hỏi, có lúc giải quyết được, lúc thì không. Nhìn chung nó đang làm thay nhiệm vụ của Google & Stack Overflow, giúp tiết kiệm thời gian 😆

    LLMs như một cuốn bách khoa toàn thư rất khủng khiếp. Hỏi gì cũng biết, cũng trả lời được nhưng có một sự thật là nó chỉ là mô hình đoán chữ (đoán tokens). Thế nên nếu vấn đề phổ biến thì nó sẽ làm rất tốt, nhưng vấn đề ít phổ biến hơn thì nó lại rất tệ, hoặc thậm chí là đưa ra thông tin sai lệch, nhiễu... Tóm lại, cần phải biết cách khai thác thông tin, mà để biết thì buộc người dùng phải có một lượng kiến thức nhất định, tránh rơi vào cái bẫy thiên kiến uy quyền (tin tưởng tuyệt đối vào ai đó) hoặc thiên kiến xác nhận (xác nhận niềm tin sẵn có bằng cách chỉ tìm bằng chứng xác nhận niềm tin đó).

    Tại thấy bài viết này nên lại nổi hứng viết vài dòng 🤓 Why I'm Dialing Back My LLM Usage

    » Xem thêm

Vấn đề

"Hãy cho tôi một điểm tựa, tôi sẽ nhấc bổng quả đất lên" là câu nói nổi tiếng của Archimedes. Nhiều minh chứng cho rằng kể cả có cho ông ta điểm tựa thì cũng phải mất nhiều nghìn năm mới có thể nhấc được. Chưa kể, một đòn bẩy có độ dài không thể tưởng tượng được thì lấy đâu ra. Nhưng trong bài viết này tôi không bàn luận về tính đúng sai của câu nói, có một điều mà tôi thấy suy nghĩ của ông hết sức thú vị: Hãy cho tôi...tôi sẽ...

Hãy cho tôi x, tôi sẽ trả về y là một suy nghĩ đầu vào - đầu ra trong lập trình. Đây là một lối tư duy giải quyết vấn đề rất thông dụng. Thay vì bắt tay ngay vào viết mã, hãy dành thời gian để đánh giá và xem chỗ nào có thể áp dụng được cách hỏi "hãy cho tôi x, tôi sẽ trả về y". Nghe thì quen đấy, có phải bạn từng nghe đến trong bài viết Code thì cứ code nhưng đã bao giờ bạn dành thời gian khai phá tư duy lập trình của mình chưa?.

Một ví dụ đơn giản

Cho dễ hình dung, tôi lấy một ví dụ về tính năng mua hàng đơn giản. Logic của nó trông như thế này:

function createOrder(product, quantity, customer) {
  // tìm thông tin product
  const productInfo = ProductModel.findOne({
    where: {
      product_id: product,
    }
  });
  if (!productInfo) {
    throw new Error('Product not found');
  }

  // kiểm tra số lượng tồn kho
  if (productInfo.quantity < 1) {
    throw new Error('Not enough product in stock');
  }

  // tạo order
  const order = OrderModel.create({
    customer: customer,
    product_id: product,
    quantity: quantity,
    total_price: productInfo.price * quantity,
  });

  return order;
}

Nếu suy nghĩ đầu vào - đầu ra, bạn có thể làm cho mã bên trên trông ngắn gọn và có thể tái sử dụng được. Để làm được điều đó, hãy nghĩ cách tách các phần logic càng nhỏ càng tốt, sao cho chúng thành Pure function được thì càng tốt. Nếu chưa biết đến "hàm thuần khiết" là gì, bài viết Pure Function trong Javascript. Tại sao chúng ta nên biết càng sớm càng tốt? là dành cho bạn.

Ví dụ trên, chúng ta thấy có 3 logic rất rạch ròi: lấy thông tin sản phẩm, kiểm tra số lượng tồn kho và cuối cùng là tạo đơn. Từ đó tách ra thành 3 hàm nhỏ hơn.

Cho tôi id sản phẩm, tôi sẽ trả về thông tin của sản phẩm đó.

function getProductInfo(product) {
  return ProductModel.findOne({
    where: {
      product_id: product,
    },
  });
}

Cho tôi thông tin sản phẩm, tôi sẽ kiểm tra được hàng còn tồn kho không

function checkProduct(productInfo) {
  return productInfo.quantity > 0;
}

Cho tôi tin tin tạo đơn hàng, tôi sẽ tạo đơn hàng và trả về nó.

function createOrder(productInfo, customer) {
  return OrderModel.create({
    customer: customer,
    product_id: productInfo.id,
    total_price: productInfo.price,
  });
}

3 hàm với 3 mục đích rõ rệt, giúp bạn tái sử dụng chúng. Bất cứ khi nào lấy thông tin sản phẩm thì dùng getProductInfo, kiểm tra lượng hàng tồn kho thì dùng checkProduct... Có người hỏi tại sao checkProduct lại phải nhận cả producInfo chứ không phải là mỗi thuộc tính quantity thôi? Để trả lời cho câu hỏi này còn phụ thuộc vào kinh nghiệm của bạn trong dự án. Việc nhận cả productInfo giúp tăng khả năng mở rộng sau này. Ví dụ sau này phát sinh thêm logic phải những sản phẩm có thời gian tạo sau một tuần mới được tạo đơn.

function checkProduct(productInfo) {
  return productInfo.quantity > 0 && productInfo.created_at < moment().subtract(7, "d").toISOString();
}

Dĩ nhiên, bạn có thể tiếp tục tách checkProduct thành những hàm nhỏ hơn nữa nếu đánh giá là cần thiết.

function checkProduct(productInfo) {
  return checkQuantity(productInfo.quantity) && checkDate(productInfo.created_at);
}

Lợi ích của viết hàm đầu vào đầu ra là rất dễ tạo unittest. Vì không có thành phần phụ thuộc (ví dụ như trong hàm lại sử dụng một biến nào đó ở bên ngoài hàm) nên bạn có thể viết các trường hợp để kiểm tra tính đúng đắn của hàm.

Ví dụ, để kiểm tra xem checkProduct có hoạt động đúng như mong đợi, chỉ cần truyền vào productInfo có các trường quantitycreated_at, hàm sẽ trả về kết quả là true/false. Với một đầu vào sẽ cho một đầu ra tương ứng, không phải lo lắng liệu hàm có dùng biến bên ngoài hàm hoặc side effect hay không.

Tóm lại, việc suy nghĩ đầu vào - đầu ra, cùng với khả năng tạo ra các Pure function, hạn chế side effect giúp chúng ta viết ra được chức năng có tính tái sử dụng và dễ unittest.

Cho đến bây giờ, câu nói của Archimedes vẫn không ai kiểm chứng được liệu ông có nhấc được quả đất lên khi có đủ các điều kiện cần hay không. Nhưng hàm của bạn viết ra, chắc chắn có thể kiểm chứng được tính đúng đắn một cách dễ dàng hơn bao giờ hết.

Làm thế nào để suy nghĩ đầu vào đầu ra?

Có một một số cách để giúp bạn rèn luyện suy nghĩ đầu vào - đầu ra. Sau khi đọc những gợi ý dưới đây, điều quan trọng là bạn phải luyện tập bằng cách áp dụng nó thật nhiều trong dự án cá nhân hoặc dự án mà bạn tham gia.

Thứ nhất, dành thời gian để tìm hiểu xem Pure function là gì? Lợi ích của nó mang lại là như thế nào.

Thứ hai, trước khi bắt tay vào làm bất cứ điều gì, hãy dành thời gian đánh giá lại tính năng chuẩn bị triển khai. Tôi đã có bài viết về 4 bước rèn luyện tại Code thì cứ code nhưng đã bao giờ bạn dành thời gian khai phá tư duy lập trình của mình chưa?.

Trong quá trình viết mã, hãy viết một cách tự nhiên. Sau đó kiểm tra lại xem liệu có logic nào có thể tách ra được không? Nếu được thì tách thành Pure function càng tốt.

Lặp lại các bước trên, dần dần bạn sẽ hình thành lối viết đầu vào đầu ra. Sau này, khi chuẩn bị làm một tính năng mới hoặc có tính tương tự như trước, lối tư duy đó ùa về giúp bạn tiết kiệm thời gian khi bắt đầu đánh giá và viết mã.

Tổng kết

Suy nghĩ đầu vào đầu ra không mới, có thể bạn từng sử dụng rồi nhưng chưa để ý đến mà thôi, hy vọng qua bài viết này giúp bạn đọc nhận ra tầm quan trọng của phương pháp suy nghĩ này, từ đó rút ngắn thời gian viết mã và tổ chức mã được tốt hơn.

Cao cấp
Hello

Bí mật ngăn xếp của Blog

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, 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...