5 điểm bởi GN⁺ 2025-10-26 | 2 bình luận | Chia sẻ qua WhatsApp
  • So sánh Backbone của đầu những năm 2010 với React của năm 2025, đồng thời nhìn lại xem frontend đã thực sự tiến bộ được bao nhiêu trong 15 năm qua
  • React bề ngoài có vẻ gọn gàng và hiện đại, nhưng bên trong lại giả lập sự đơn giản thông qua các tầng trừu tượng phức tạp
  • Backbone tuy dài dòng hơn, nhưng luồng sự kiện và thao tác DOM đều tường minh, nên ngay cả lập trình viên mới cũng dễ dàng lần theo cách nó hoạt động
  • React có cấu trúc khiến việc debug trở nên khó khăn nếu không hiểu cơ chế bên trong, do các vấn đề như quản lý state, mảng dependency, closure
  • Cuối cùng, bài viết gợi nhắc lại bản chất “event + state = UI”, đồng thời đặt ra nhu cầu về một mô hình mới vừa đơn giản vừa dễ can thiệp (hackable)

15 năm tiến bộ

  • Một ví dụ về ô nhập mật khẩu, một bên được viết bằng framework của thập niên 2010 (Backbone), bên còn lại bằng React đã phát triển hơn 10 năm
    • Hai cách triển khai có độ dài tương tự và chức năng cũng giống nhau
    • React được hậu thuẫn bởi rất nhiều thời gian của lập trình viên và một hệ sinh thái khổng lồ
    • Tuy vậy, tác giả cho rằng điều thú vị hơn không phải là “React đã cải thiện đến đâu” mà là “nó tiến bộ ít đến mức nào
  • React mang lại ảo giác về sự đơn giản ở bề mặt, nhưng trên thực tế lại khó hiểu hơn do các lớp trừu tượng phức tạp
    • Backbone biểu đạt rõ ràng luồng đơn giản: sự kiện xảy ra → chạy handler → tạo HTML → chèn vào DOM
    • Trong khi đó React che giấu hoạt động nội bộ, và khi vượt qua các ví dụ đơn giản sẽ xuất hiện những vấn đề chỉ có thể giải quyết nếu hiểu cơ chế bên trong

Ảo giác về sự đơn giản (The Illusion of Simplicity)

  • Mã React trông sạch sẽ, nhưng đó là kết quả của việc chọn độ phức tạp trừu tượng thay cho sự đơn giản tường minh
    • Backbone dài dòng hơn, nhưng cho thấy rõ “điều gì xảy ra và xảy ra khi nào”
    • Ngay cả lập trình viên mới cũng có thể dễ dàng lần theo luồng mã
  • Trong React, state nội bộ và logic render bị che giấu nên bug ngoài dự kiến xuất hiện khá thường xuyên
    • Ví dụ: nếu đổi key của một mục trong danh sách thành index, React sẽ nhận đó là một component khác và reset state
    • Khi value đổi thành undefined, sẽ xảy ra hiện tượng chuyển từ uncontrolled sang controlled component, khiến giá trị input bị reset
  • Khi dùng useEffect, vấn đề vòng lặp vô hạn cũng rất phổ biến
    • Nếu mảng dependency chứa một object được tạo mới ở mỗi lần render, React sẽ coi đó là thay đổi
    • Để tránh điều này, cần dùng useMemo, useCallback để ổn định identity (stabilize identities)
    • Điều này tạo thêm gánh nặng phải chú ý tới những khái niệm mà trước đây không cần bận tâm
  • Ngoài ra còn có vấn đề click handler tham chiếu tới state cũ (stale state)
    • Vì hàm sẽ capture state tại thời điểm nó được tạo ra
    • Cách giải quyết là đưa state vào mảng dependency, hoặc dùng functional update như setState(x => x + 1)
    • Nhưng cả hai cách đều mang lại cảm giác như một biện pháp chắp vá (workaround)

Cái giá của phép màu (Magic Has a High Price)

  • Những vấn đề này không phải ngoại lệ, mà là các vấn đề phổ biến thường gặp ở ứng dụng từ quy mô trung bình trở lên
    • Để debug, cần hiểu thuật toán reconciliation, render phase, và scheduler (batch update)
    • React là kiểu cấu trúc “vẫn chạy dù không biết vì sao nó chạy”, nhưng khi có sự cố thì bắt buộc phải hiểu bên trong mới xử lý được
  • React phức tạp đến mức có câu nói rằng “muốn thật sự hiểu React thì phải tự tay xây nó”
    • Có những tutorial như “Build your own React”
    • Tuy nhiên, việc phải hiểu virtual DOM, mức ưu tiên scheduling, và concurrent rendering chỉ để làm một trình kiểm tra mật khẩu là một hàm ý đáng để phê phán
  • Backbone và jQuery có cấu trúc trung thực và dễ can thiệp
    • Có thể xem trực tiếp source code và chỉnh sửa
    • Dựa trên các phương thức DOM nên dễ hiểu và dễ mở rộng
    • Ngược lại, tầng trừu tượng của React khiến việc truy cập và chỉnh sửa nội bộ trở nên khó khăn

Bước tiếp theo là gì (So, What's Next?)

  • Xét cho cùng, cả React lẫn Backbone đều là những nỗ lực nhằm giải quyết cùng một bài toán: “event + state = UI”
  • Ở các ứng dụng lớn, sự phức tạp của React có thể là điều hợp lý, nhưng với phần lớn ứng dụng nhỏ và vừa thì đó là gánh nặng quá mức
  • Cần một mô hình UI mới có sự đơn giản và tính minh bạch
    • Một hệ thống vững chắc nhưng trực quan như DOM
    • Hướng tới một cấu trúc có thể hiểu và sửa được ngay lập tức như Backbone hay jQuery

2 bình luận

 
shakespeares 2025-10-26

Với các ứng dụng nhỏ và vừa, có vẻ việc thiết kế JavaScript Class sẽ là tư thế chuẩn bị cho tương lai hơn là dùng Backbone hay JQuery.
Việc phải học lại rồi triển khai theo các template có trong JQuery hay Backbone giống như đang thụt lùi.

 
GN⁺ 2025-10-26
Ý kiến Hacker News
  • Đã dùng hết Backbone, Angular 1, Ember cho đến React
    Không nên bỏ qua lý do vì sao React trở nên phổ biến. React đã giải quyết những vấn đề cố hữu của các framework trước đó ở các mặt như kết hợp component, xử lý sự kiện, quản lý trạng thái, cập nhật DOM hiệu quả
    Backbone khiến việc quản lý vòng đời DOM trở nên phức tạp, lại phải chỉ định event handler bằng chuỗi nên rất khó bảo trì. React đơn giản hóa các vấn đề này bằng luồng trạng thái một chiều và virtual DOM
    Nếu là bây giờ, khi muốn dùng JS thuần, tôi nghĩ một giải pháp template như lit-html tốt hơn Backbone rất nhiều

    • Cảm thấy ví dụ này không thực tế. Nếu muốn so sánh thì TodoMVC mới là đại diện tiêu biểu. Nhìn vào đoạn code này của bản Backbone thì đúng là ác mộng bảo trì. Bản React (link) rõ ràng hơn nhiều
      Frontend trước đây đã phức tạp, bây giờ cũng vẫn phức tạp, nhưng giờ đỡ đau hơn rất nhiều
    • Đồng ý. React cũng không hoàn hảo, nhưng rốt cuộc đây là bài toán đánh đổi. Dùng công cụ nào thì lập trình viên cũng phải gánh độ phức tạp đó. Điều quan trọng là liệu chúng ta có đang chọn đúng điểm cân bằng hay không
    • Dạo này ngoài React cũng có nhiều framework cung cấp các tính năng như vậy. Đó không còn là đặc quyền riêng của React
  • Độ phức tạp của ứng dụng không đến từ số lượng component mà đến từ quản lý trạng thái
    Tôi thường xuyên gặp vấn đề UI bị treo vì luồng dữ liệu hai chiều của Backbone Store. Đột phá của React là kiến trúc Flux lấy luồng dữ liệu một chiều làm trung tâm
    Tôi nghĩ một framework tốt là công cụ tự nhiên dẫn người dùng vào “cái bẫy thành công (Pit of Success)”. React đã làm tốt vai trò đó

    • Trước thời React/Flux/Redux, phát triển frontend thực sự là hỗn loạn. Ngay cả với code chưa tới 1000 dòng cũng bùng ra vấn đề quản lý trạng thái
    • Tôi là tác giả bài viết. Đúng là luồng dữ liệu một chiều đã giải quyết được vấn đề, nhưng React cũng mang đến độ phức tạp mới
      Ví dụ như các vấn đề stale closure, vòng lặp useEffect vô hạn, input bị reset do thay đổi key là những thứ Backbone không có
      Vấn đề của Backbone thì lộ rõ và dễ debug, còn vấn đề của React lại ẩn sau tầng trừu tượng
      Phần lớn ứng dụng không ở quy mô Facebook, nên cách tiếp cận tường minh và đơn giản đôi khi còn tốt hơn
    • Tôi làm Angular lâu năm rồi quay lại React, và dù không hoàn hảo, React vẫn dẫn lập trình viên code theo hướng đúng hơn
    • Component bản thân nó cũng là một loại độ phức tạp khác. Markup, event, business logic, accessibility đều bị bó lại thành một cấu trúc khổng lồ. Rốt cuộc đó chỉ là độ phức tạp để đổi lấy sự tiện lợi, chứ sự đơn giản không bao giờ miễn phí
    • “Luồng dữ liệu một chiều” thực ra chẳng phải khá giống cách DOM vốn hoạt động hay sao? Thứ mà đội React tạo ra là Flux, không phải Flow
  • Việc khẳng định một công nghệ phổ biến là “tệ” nghe giống một kiểu kiêu ngạo ngây thơ
    Tất nhiên, độ phổ biến không đảm bảo chất lượng, nhưng cho rằng tất cả những kỹ sư giỏi trên thế giới đều bị lừa thì hơi quá

    • Công nghệ phổ biến không phải lúc nào cũng đúng. Chỉ cần nhớ lại các làn sóng MongoDB, Kafka, Microservice là đủ
      Khi doanh nghiệp lớn và marketing cùng đẩy mạnh, các CTO sẽ chấp nhận nó, và khi sự nghiệp bị ràng buộc vào đó thì chẳng ai muốn nói “cái này không ổn”. Phổ biến ≠ phù hợp
    • Tôi là tác giả bài viết. Phép ví von với “paleo influencer” khá thú vị, nhưng không phải cứ mới là tốt
      React không thắng chỉ nhờ ưu thế kỹ thuật mà còn nhờ marketing của Facebook và sự tự củng cố của hệ sinh thái
      Dù đã 15 năm trôi qua, độ dài và độ phức tạp của code vẫn không giảm đi bao nhiêu. Chỉ là nó trở nên phức tạp theo cách khác mà thôi
      Việc nhìn lại quá khứ không phải vì hoài niệm, mà để kiểm tra xem liệu chúng ta có đang thêm vào độ phức tạp không tương xứng hay không
    • React hay Tailwind có điểm mạnh là thân thiện với tuyển dụng. Lý do không hẳn nằm ở tính hoàn hảo về kỹ thuật mà ở sự dễ dàng khi onboarding
      Web vẫn giống như miền Tây hoang dã của các design pattern. Chấp nhận điều đó xong thì tôi thấy nhẹ đầu hơn
    • Việc kết luận React là “ngu ngốc” trông như sự pha trộn giữa kiêu ngạo và thiếu hiểu biết. Có lý do để hàng triệu lập trình viên dùng nó. Phủ định sạch trơn như vậy là thái độ phớt lờ Chesterton’s Fence
    • Có lẽ không phải kiêu ngạo mà là trải nghiệm từ một góc nhìn khác. Có người thích hệ sinh thái React, cũng có người ghét vì lượng JS quá nhiều
      Cuối cùng, mỗi dự án vẫn phải đánh giá lại các trade-off
  • Lập luận “việc đơn giản thì không cần React” là một ngụy biện React (React fallacy) rất phổ biến
    Đánh giá React bằng các ví dụ đơn giản cũng giống như “đánh giá một ngôn ngữ qua độ dài của Hello World”
    Lý do dùng React cho cả việc đơn giản là vì nó cũng được dùng cho việc phức tạp. Bộ công cụ nhất quán có lợi cho bảo trì

    • “Đã dùng cho việc phức tạp thì cũng dùng cho việc đơn giản” nghe giống như lái xe tải đi mua đồ. Rốt cuộc mấu chốt vẫn là chọn đúng công cụ
  • Backbone là kiểu “trông như framework nhưng thực chất là một đống glue code”
    Chiến thắng thực sự của React là không còn cần thao tác DOM trực tiếp và có thể quản lý trạng thái theo kiểu reactive. Hai điều này đã nâng năng suất phát triển lên đáng kể

    • Là người từng viết rất nhiều tutorial Backbone ngày trước, tôi cũng có chút hoài niệm
      Link tutorial cũ, bản lưu trữ
      Giờ tôi quan tâm hơn đến việc LLM hiểu code như thế nào. Cú pháp khai báo như JSX khá thân thiện với LLM
      Nhưng React sau thời useEffect lại cho cảm giác mờ hơn về mặt biểu đạt và tính tường minh
    • Marionette đã giúp giảm khá nhiều boilerplate của Backbone
    • Có người hỏi liệu React có quản lý trạng thái tích hợp sẵn hay không
  • Điều này cho thấy khá rõ vì sao React trở nên phổ biến
    Code React phần lớn chỉ là JS thuần và HTML, và cốt lõi chỉ là useState. Nó trực quan đến mức có thể hiểu mà không cần tài liệu
    Backbone phụ thuộc vào các string selector như .space-y-2, nên bảo trì đúng là địa ngục. Chỉ cần đổi một class name là nửa ứng dụng có thể hỏng
    React đã giải quyết vấn đề này theo cách có tính cấu trúc

    • Có câu đùa rằng “bài đó chắc không phải tự viết mà là bảo Claude viết hộ”
  • Code Backbone cho thấy rõ “việc gì xảy ra khi nào”, còn React thì phải hiểu được cơ chế nội bộ của nó
    Tôi cũng đã phải đọc đi đọc lại hướng dẫn useEffect của Dan Abramovblog của Mark Erikson để hiểu thời điểm React hoạt động như thế nào
    Code Backbone thì dù 10 năm sau nhìn lại vẫn hiểu ngay

  • Sáu năm trước chúng tôi chuyển team từ Backbone sang Angular
    Backbone có cấu trúc trực quan và không có ma thuật, nên khá phù hợp cho junior, nhưng cuối cùng TypeScript và Angular vẫn bài bản hơn
    Hiện tại chúng tôi dùng NG20 và thấy hài lòng. Nếu một ngày nào đó trình duyệt mặc định hỗ trợ nhiều thứ hơn, có lẽ chúng tôi sẽ lại quay về cách làm đơn giản hơn

  • Chúng ta luôn lập trình trên các tầng trừu tượng
    Điều quan trọng là tầng trừu tượng đó có mang lại lợi ích năng suất tương xứng với độ phức tạp hay không, và liệu nó có đáng tin cậy hay không
    Ít nhất trong trường hợp xấu nhất vẫn phải debug được

  • Trường input của React xử lý thao tác Undo tự nhiên hơn so với Backbone
    Backbone hoàn tác từng ký tự một, còn React hoàn tác theo từng từ

    • Tôi không hiểu vì sao việc ghi đè hành vi mặc định của trình duyệt lại được xem là tốt hơn. Nó giống như một thư viện JS phá hỏng cuộn trang tự nhiên vậy
    • Điều thú vị là trên Chrome thì khác, nhưng trên Firefox thì cả hai framework đều hoạt động giống nhau
    • Tôi nghĩ cách của Backbone tốt hơn
    • Rốt cuộc hành vi nào mới là “đúng” thì vẫn là vấn đề của sở thích cá nhân