5 điểm bởi GN⁺ 2023-07-04 | 1 bình luận | Chia sẻ qua WhatsApp
  • Phiên bản trực tuyến của Data-Oriented Design là tài liệu được công bố để độc giả muốn học về thiết kế hướng dữ liệu có thể xem miễn phí các nội dung cốt lõi
  • Một số chương không cốt lõi của toàn bộ cuốn sách đã được lược bỏ, nhưng nội dung được cấu thành xoay quanh những phần thiết yếu cần cho việc học
  • Vì đây là tài liệu được tự động chuyển đổi từ LaTeX sang HTML nên có thể vẫn còn lỗi định dạng, hình ảnh bị hỏng và danh sách mã nguồn bị lỗi
  • Với các danh sách mã nguồn bị hỏng, có thể xem mã tham chiếu trong kho lưu trữ GitHub riêng
  • Việc mua sách giấy vừa là cách đọc với định dạng tốt hơn, vừa giúp duy trì phiên bản trực tuyến dành cho những độc giả khó có điều kiện mua sách

Tính chất của phiên bản trực tuyến

  • Data-Oriented Design được cung cấp dưới dạng bản rút gọn trực tuyến miễn phí về thiết kế hướng dữ liệu
  • Dù một số chương không cốt lõi đã bị loại bỏ, dòng chảy nội dung cốt lõi cần thiết cho tài liệu học tập vẫn được giữ lại
  • Tài liệu phù hợp với độc giả muốn làm quen với cách tiếp cận xem xét thiết kế với dữ liệu là trung tâm

Chất lượng chuyển đổi tài liệu và tham chiếu mã

  • Tài liệu trực tuyến được tạo tự động nên một số định dạng có thể chưa tự nhiên
  • Công cụ chuyển đổi từ LaTeX sang HTML chưa hoàn hảo nên hình ảnh hoặc danh sách mã nguồn có thể bị hỏng
  • Nếu danh sách mã nguồn bị lỗi, có thể tìm mã tham chiếu trên GitHub

Sách giấy và phản hồi

  • Sách giấy cho trải nghiệm đọc với định dạng tốt hơn so với bản trực tuyến
  • Việc mua sách giấy giúp tiếp tục duy trì phiên bản trực tuyến cho những độc giả không đủ khả năng mua sách
  • Có thể gửi phản hồi tới support@dataorienteddesign.com

1 bình luận

 
GN⁺ 2023-07-04
Ý kiến trên Hacker News
  • Một trong những lời khuyên hay nhất mà tôi từng nhận được để viết code hiệu năng cao và có thể kết hợp linh hoạt là “hãy làm việc với cấu trúc của các mảng, không phải mảng các cấu trúc”, và bài viết này cũng gợi lại rất nhiều điều tương tự
    Hóa ra kiến trúc entity-component không chỉ hợp với game mà còn rất phù hợp với cả các ứng dụng nghiệp vụ
    Tuy vậy, nhiều lập trình viên ở doanh nghiệp đã quá quen với mô hình CRUD kiểu lưu trữ bản ghi nên gặp khó khăn khi nghĩ theo cột thay vì theo hàng, và thường thấy không tự nhiên với ý tưởng đưa ID của thực thể vào bảng published thay vì chỉ đổi trường boolean published thành true
    Nhưng một khi đã nhận ra cách này mở rộng đa hình dễ đến mức nào, bạn sẽ muốn áp dụng cách tiếp cận đó cho mọi dữ liệu. Khi ấy sẽ xuất hiện những cơ hội mới để tận dụng chéo dữ liệu giữa các component, và bạn sẽ bắt đầu thắc mắc vì sao hệ thống lại cho phép giao diện mạng có ngày sinh, hóa đơn có địa chỉ IPv6, mèo nằm trong DHCP pool, còn limegreen thì bị xóa và thứ Ba có giá 5 đô la — mà đó mới là một nửa cái vui của nó
    Tôi không đồng ý với nhận định rằng cách này hoàn toàn không tương thích với lập trình hướng đối tượng. Tôi từng áp dụng cách tiếp cận này cả với Active Record của Ruby, và nó hoạt động tốt ngay cả trong những lĩnh vực vốn không thường gắn với chữ “hiệu năng cao”. Nó đặc biệt hợp với Ruby vì hệ thống đối tượng của Ruby gần với Smalltalk hơn là C++/Java, nên đề cao composition hơn là kế thừa

    • Nó không xung đột với các cơ chế của lập trình hướng đối tượng, nhưng lập trình viên phải thay đổi cách nhìn vấn đề
      Trong các ngôn ngữ hướng đối tượng, ta thường tập trung vào một “đối tượng mình muốn nghĩ tới” như người dùng, bài blog, giao dịch tiền bạc, rồi tách nó ra khỏi phần còn lại để triển khai, ẩn dữ liệu đi và suy nghĩ xem nên lộ ra những phương thức nào cho các phần khác của hệ thống. Khái niệm đóng gói rất mạnh
      Trong thiết kế hướng dữ liệu, việc dữ liệu từ các domain khác nhau có thể được truy cập và các subsystem chọn lấy những gì chúng cần cho công việc của mình là điều phổ biến hơn. Java hay Ruby không ngăn cản điều đó, nhưng với lập trình viên thì rõ ràng vẫn có một rào cản tâm lý
    • Bài “Array of Structure (AoS) and Structure of Arrays (SoA)” trên Wikipedia giải thích sự đánh đổi giữa SoA về mặt hiệu năng và AoS về mặt trực quan/hỗ trợ ngôn ngữ: https://en.wikipedia.org/wiki/AoS_and_SoA
      Bài này cũng đề cập đến hỗ trợ phần mềm giúp truy cập SoA như thể AoS, chẳng hạn data frame của R, Pandas của Python, hay DataFrames.jl của Julia
    • Trong thế giới dữ liệu, “cấu trúc của các mảng” tương ứng với chỉ mục dạng cột như Snowflake hay OLAP, còn “mảng các cấu trúc” tương ứng với cơ sở dữ liệu quan hệ dùng chỉ mục theo trang/hàng
      Tôi rất thích Snowflake và nghĩ rằng nó sẽ giành mất miếng ăn của các đối thủ khác. Cũng thú vị là Snowflake “hỗ trợ” khóa ngoại nhưng không ép buộc. Nói cách khác, Snowflake là mức “NoSQL” mà tôi có thể chấp nhận được
    • Tôi nghĩ có hai loại thiết kế hướng dữ liệu. Một loại là cách như đã nói ở trên: làm việc với “cấu trúc của các mảng, không phải mảng các cấu trúc”
      Loại còn lại là từ bỏ đóng gói, tách dữ liệu khỏi các phương thức xử lý dữ liệu đó, và mô hình hóa toàn bộ ứng dụng theo dòng chảy của dữ liệu để dễ hiểu và dễ thay đổi hơn. Nếu muốn tăng tính chính xác, có thể dùng cấu trúc dữ liệu bất biến và các hàm thuần
    • Tôi đã thử đưa ECS vào cả những ứng dụng không phải game, và một công ty tài chính ở London cũng đã tiếp nhận lời khuyên này để quản lý độ phức tạp của hệ thống. Nó thực sự rất phù hợp
      Đây là một bài giới thiệu ECS cực ngắn cho ai quan tâm: https://dev.to/ovid/the-unknown-design-pattern-1l64
  • “Bố cục dữ liệu có được định nghĩa bởi một cách diễn giải duy nhất xuất phát từ một góc nhìn hay không?” có thể là câu hỏi quan trọng nhất ở thời điểm lựa chọn công nghệ và kiến trúc. Thông thường, để trả lời câu hỏi này thì phải nói chuyện với khối kinh doanh và khách hàng
    Nếu bạn tin chắc rằng chỉ có đúng một “view” hợp lệ duy nhất cho dữ liệu để dùng trên toàn bộ hệ thống, thì việc khắc điều đó vào code cũng có lý. Nếu có dù chỉ một chút không chắc chắn, mô hình kiểu quan hệ có khả năng sẽ phù hợp hơn. Nhiều công ty cuối cùng đều quay về SQL khi họ nhận ra lý thuyết trò chơi của vấn đề này
    Mọi người đều thắc mắc vì sao ai cũng có vẻ như đã rời xa một cơ sở dữ liệu SQL lớn duy nhất. Có những trường hợp biên “web scale” đe dọa khả năng mở rộng theo chiều dọc của tác vụ ghi, nhưng tôi cho rằng phần lớn công ty, kể cả doanh nghiệp F100, cũng sẽ không bao giờ chạm đến mức đó

    • Ở một công ty công nghệ F100 trước đây, tôi từng nhận được chỉ thị là cấm RDBMS nếu không có phê duyệt rõ ràng
      Điều đó không liên quan đến cách mô hình hóa tốt nhất cho một tập dữ liệu cụ thể hay hiệu năng tốt nhất, mà hoàn toàn do tiền sử sự cố gây ra bởi tính linh hoạt của schema và các lần migration schema thất bại. Với thiết kế NoSQL thì những vấn đề đó không xảy ra, và các lợi ích của cơ sở dữ liệu SQL cũng không đủ để bù lại ưu thế lớn của NoSQL là không có schema cứng nhắc
      Tất nhiên, nếu dùng sai kho key-value thì hiệu năng và chi phí có thể tệ hại nghiêm trọng. Trên các nền tảng đám mây như DynamoDB, tôi đã thấy nhiều trường hợp dữ liệu được cấu trúc không đúng cách, dẫn đến thực hiện hàng loạt scan và chi phí tăng vọt
    • Không hẳn là đã rời bỏ hoàn toàn một cơ sở dữ liệu SQL lớn duy nhất, nhưng chúng tôi đang gặp một nhóm vấn đề có vẻ gắn với kiến trúc đó
      Vì là một tập đoàn lớn lâu đời, thường có nhiều giải pháp kỹ thuật do người không thuộc khối kỹ thuật tạo ra trong quá khứ đã bị đóng cứng và buộc phải tiếp tục duy trì. Có tồn tại 5 giai đoạn biến đổi dữ liệu SQL, bắt đầu từ cơ sở dữ liệu vận hành rồi kéo dài qua nhiều thế hệ mô hình dữ liệu khác nhau mỗi khi loại hình kinh doanh thay đổi
      Càng nhiều lớp thì càng tiếp tục chồng lên các lớp trước đó. Nếu một ứng dụng được xây 10 năm trước trên lớp trừu tượng 2 giờ lại cần dữ liệu của lớp 4, người ta sẽ viết script để đưa dữ liệu đó quay ngược về lớp cũ rồi tiếp tục. Cuối cùng nó trở thành một khối khổng lồ gồm các bảng và view phụ thuộc lẫn nhau, đọc dữ liệu theo những cách kỳ quặc và thiếu trực quan, còn dự án dọn dẹp thì bị đánh giá là quá đắt nên bị hoãn đến tận thập niên 2030
      Tôi hiểu vì sao người ta nhìn vào những vấn đề như vậy rồi tự hỏi lẽ ra đã có thể tránh bằng cách nào. Nhưng vì lý do nào đó, có vẻ như không thể áp dụng kiểu kỷ luật cần thiết với kỹ sư phần mềm, nên phải tìm cách khiến họ không thể tạo ra spaghetti bằng cách nào đó. Đó là lúc sự tách biệt xuất hiện. Nếu không thể đọc dữ liệu của dịch vụ khác, bạn sẽ không thể tạo ra kiểu spaghetti giết chết tốc độ của cả hai phía
      Sự tách biệt theo chiều dọc của ứng dụng trở thành một lời giải phần mềm cho vấn đề con người là kỷ luật kỹ thuật yếu kém trong doanh nghiệp
    • Hacker News không đại diện cho toàn bộ hệ sinh thái công nghệ. Tôi cho rằng phần lớn ứng dụng vẫn đang dùng một cơ sở dữ liệu SQL lớn duy nhất
      Gần đây tôi đã công bố một framework mã nguồn mở hoàn toàn dựa trên thiết kế hướng dữ liệu, và nhận được rất nhiều phản hồi rằng cách thiết kế này cực kỳ phù hợp. Khi đặt toàn bộ dữ liệu vào một chỗ, có thật sự rất nhiều việc trở nên dễ dàng hơn
      https://sql.ophir.dev
    • Ở những nơi tôi từng làm việc, lý do là thế này: họ đã chuyển sang microservices, một cơ sở dữ liệu khổng lồ làm chậm hiệu năng, và việc vận hành cũng như bảo trì một DB lớn là cực kỳ khó khăn
      Trong DB khổng lồ đó có rất nhiều phần tồn dư mà chẳng ai dùng, cũng không ai biết vì sao nó còn ở đó, nhưng vẫn chưa chắc có còn cần hay không; đồng thời việc đọc và ghi lại cần các chiến lược tối ưu hóa khác nhau
      Ngoài ra, để các nhóm có thể di chuyển nhanh, họ cần có quyền sở hữu đối với cơ sở dữ liệu và kho lưu trữ dữ liệu của mình, thay vì phải chờ DBA trả lời ticket
    • Tôi cho rằng nguyên nhân cũng giống như lý do microservices và DevOps nổi lên. Chính trị trở nên dễ xử hơn
      Khi làm ở các công ty lớn lâu đời, phần lớn vấn đề tôi gặp đều là vấn đề chính trị và hành chính. Một cơ sở dữ liệu SQL lớn duy nhất thì hiệu quả, nhưng ngay khi tổ chức sở hữu nó không đồng ý với chiến lược mới của CTO hoặc với một bộ phận kinh doanh cốt lõi khác, thì vấn đề bắt đầu xuất hiện
      Khi cộng thêm các sự cố cho thấy mô hình này có khả năng phục hồi thấp, nó nhanh chóng trở thành một cơn đau đầu về chính trị, và dù giải pháp kỹ thuật với mọi người vẫn có vẻ quá hiển nhiên, việc thúc đẩy thực hiện lại rất khó
  • Toàn bộ lời khuyên này phụ thuộc vào ngữ cảnh
    Chỉ là trong game có nhiều phép toán cần cách tiếp cận theo cột, chứ không phải mọi miền bài toán đều như vậy. Nếu mù quáng áp các best practice của game sang lĩnh vực khác, bạn chỉ khiến cuộc sống của mọi người khó khăn hơn và làm phần lớn hệ thống trở nên tệ hơn

    • Đây không chỉ là vấn đề riêng của cách tiếp cận theo cột. Nếu biến dữ liệu thành dạng mảng-cấu-trúc, bạn sẽ có cơ hội đóng gói dữ liệu hiệu quả hơn và giảm mạnh mức sử dụng bộ nhớ của ứng dụng
      Các trường boolean trong struct có thể trở thành bitset, các trường có thể null có thể trở thành map thưa hoặc map dày, còn các trường con trỏ hoặc tham chiếu có thể trở thành các mảng số nguyên với độ rộng nhỏ hơn để đánh chỉ mục vào pool
      Trong môi trường mà CPU thường xuyên bị khựng vì truy cập bộ nhớ, không thể đánh giá thấp tác động của những thay đổi như vậy. Chênh lệch độ trễ giữa cache L3 và RAM có thể vào khoảng 10 lần
    • Lời khuyên giữ dữ liệu được truy cập thường xuyên liền kề trong bộ nhớ gần như áp dụng cho mọi thứ trên phần cứng hiện đại
      Với bất kỳ chương trình nào mà hiệu năng dù chỉ hơi là vấn đề, đây rất có thể là một trong những cách để đảm bảo hiệu năng tốt
    • Việc game có nhiều phép toán cần cách tiếp cận theo cột cũng hoàn toàn không rõ ràng vào thời điểm ECS mới xuất hiện. Đã mất rất nhiều thời gian để thuyết phục mọi người rời khỏi cách làm hướng đối tượng
    • Tôi ngày càng có cảm giác đây là cách duy nhất để viết mã hiệu năng cao
      Thứ duy nhất có thể kỳ vọng tiếp tục mở rộng trên phần cứng hiện đại là mật độ logic. SRAM và kích thước cache không còn mở rộng tốt trên công nghệ quang khắc hiện đại nữa, còn băng thông RAM thì cũng đã không tăng nhiều từ khá lâu rồi. Tôi thậm chí cho rằng băng thông trên mỗi lõi có thể còn đã giảm. Truy cập bộ nhớ đã là nút thắt cổ chai trong một thời gian dài
    • Ngay cả trong nhiều vùng mã của game thông thường, cách tiếp cận theo cột cũng không phải lúc nào cũng đúng, mà chỉ áp dụng cho những phần phải xử lý ít nhất hàng nghìn “đối tượng”. Ví dụ như hệ thống hạt hoặc hệ thống điều hướng và va chạm
      Thiết kế hướng dữ liệu là một cách tiếp cận rất hợp lý bên trong các hệ thống con cụ thể, nhưng với mã gameplay cấp cao thì, trừ một số thể loại nhất định, chưa chắc đã như vậy
  • Tôi cho rằng bài thuyết trình Data-Oriented Design and C++ của Mike Acton tại CppCon 2014 là bài nói về lập trình hay nhất từng có. Rất đáng xem: https://youtu.be/rX0ItVEVjHc

    • Thật sự xuất sắc và cũng là bài thuyết trình tôi thích nhất. Cá nhân tôi xem Mike Acton là nhân vật chủ chốt đã phổ biến thiết kế hướng dữ liệu và kiến trúc ECS
      Trước đây ông ấy cũng dẫn dắt Unity DOTS, nhưng đáng tiếc là hiện tại Unity có vẻ đang chao đảo. Bản thân công việc về DOTS dù chưa hoàn thiện nhưng vẫn rất vững chắc
    • Nếu muốn hình dung cách hiệu năng đẳng cấp thế giới được hiện thực hóa như thế nào thì hãy xem video này
      Tôi đã dành phần lớn sự nghiệp để viết web app, nhưng sau khi xem bài nói này tôi mới hiểu “vì sao lại có người dùng C?”
  • Andrew Kelley cũng có một bài thuyết trình hữu ích và thú vị giải thích thiết kế hướng dữ liệu đã ảnh hưởng thế nào đến công việc xây dựng trình biên dịch Zig của anh ấy: https://vimeo.com/649009599

  • Ngay cả người mới bắt đầu cũng có thể học lập trình theo cách tiếp cận hướng dữ liệu từ đầu
    Các cuốn sách dạy phong cách này cho người mới có How to Design ProgramsA Data-Centric Introduction to Computing
    https://htdp.org/
    https://dcic-world.org/

    • Những cuốn này không phải là thứ đang được nói tới ở đây
  • Tôi đã tìm được một bài đánh giá trực tuyến về cuốn sách: https://gist.github.com/seece/25ed1b2108cf5782718b026382f2c5...

    • Câu sau đây khá thú vị và có vẻ đi ngược với lời khuyên thông thường
      “Thủ phạm đã hành hạ và làm chậm trễ nhiều dự án là sự khăng khăng rằng không nên tối ưu hóa quá sớm. Lý do tối ưu hóa ở giai đoạn muộn lại khó đến vậy là vì rất nhiều phần mềm được chồng chất lên nhau theo kiểu đặt các object instance khắp nơi, ngay cả khi không cần đến chúng.”
      Rõ ràng có những ứng dụng mà hiệu năng là ưu tiên số một, và cũng có những ứng dụng không phải vậy. Điều này khiến tôi tự hỏi liệu với các app mà hiệu năng quan trọng thì tối ưu hóa sớm cũng có thể chấp nhận được hay không. Không biết đọc như vậy có đúng không
      Cũng có khái niệm Data-Oriented Programming: https://www.manning.com/books/data-oriented-programming
      Tôi tự hỏi hai khái niệm này có phải là một không
  • Thiết kế hướng dữ liệu khá thân thiện với người mới bắt đầu. Vì nó chỉ xử lý tính thuần khiết của việc mô hình hóa dữ liệu, thay vì phải xử lý con người và doanh nghiệp
    Hồi nhỏ, bước đầu tiên của một dự án mới là vẽ mô hình thực thể - quan hệ, và đó là nền tảng cho mọi thứ
    Ngày nay, trước khi bắt đầu với mô hình dữ liệu, người ta sẽ cố hiểu vấn đề và domain trước, rồi suy nghĩ về các capability cùng cách gom nhóm và đặt ranh giới cho chúng

    • Khi đã có kinh nghiệm, bạn sẽ nhận ra tình yêu dành cho dữ liệu và lập trình thường bị yêu cầu kinh doanh đẩy sang một bên
      Tuy vậy, bài viết này dường như muốn nói rằng nếu tập trung vào việc thu thập yêu cầu dữ liệu ngay từ đầu thì bản thân cuộc thảo luận về yêu cầu kinh doanh cũng có thể bớt cần thiết hơn
  • Một trong những khái niệm cốt lõi khi dùng DoD là không giấu dữ liệu sau các lớp trừu tượng. Theo hướng càng ít càng tốt
    Nhưng khi tôi đọc lướt bài giới thiệu thì lại có cảm giác ngược hẳn. Nó nói quá nhiều và lại trừu tượng hóa chính các khái niệm cốt lõi. Tôi không biết có phải chỉ mình tôi thấy mỉa mai như thể tác giả không tự uống rượu của mình không

  • Đoạn mở đầu khá xuất sắc. Văn phong mượt mà và ý tưởng hấp dẫn khiến tôi muốn đọc tiếp
    “Dữ liệu là tất cả những gì chúng ta có. Dữ liệu là thứ chúng ta phải biến đổi để tạo ra trải nghiệm người dùng. Thứ được đọc vào khi mở tài liệu cũng là dữ liệu. Đồ họa trên màn hình, xung từ nút bấm trên gamepad, nguyên nhân khiến loa tạo ra sóng trong không khí, cách lên level, cách kẻ địch biết vị trí của bạn để bắn, tất cả đều là dữ liệu. Thời gian để thỏi dynamite phát nổ và số vòng nhẫn bị mất khi rơi vào chông cũng là dữ liệu. Mọi vị trí và vận tốc hiện tại của từng hạt trong cảnh đẹp sau khi bạn hoàn thành trò chơi cũng là dữ liệu; đó là kết quả của những biến đổi được thực hiện bởi cỗ máy chạy trên các chỉ lệnh đã được giải mã, vốn được tạo ra từ mã nguồn đưa vào trình biên dịch và các lệnh do assembler chỉ định, tất cả được đọc từ đĩa rồi đi vào cuộc sống của bạn.”

    • Tôi thấy kiểu ý tưởng này rất nhiều trong tài liệu về thiết kế hướng dữ liệu, và lúc nào cũng cảm thấy nó giản lược quá mức một cách không cần thiết
      Nó có thể hữu ích như một “gáo nước lạnh” để dựng bối cảnh và giúp người ta thoát khỏi lối tư duy trừu tượng hướng đối tượng. Nhưng ngoài ra, nó có vẻ chỉ hữu ích đến mức một kỹ sư nói rằng “Hãy nhìn xung quanh đi! Mọi thứ đều được tạo thành từ nguyên tử! Kỹ thuật về cơ bản là việc di chuyển các nguyên tử!”
      Điều đó không sai, nhưng cũng không thực sự giúp ích nhiều cho việc làm kỹ thuật trong thực tế