Thiết kế hướng dữ liệu (2018)
(dataorienteddesign.com)- 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
Ý 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
publishedthay vì chỉ đổi trường booleanpublishedthànhtrueNhư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
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 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
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
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
Đâ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 đó
Đ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
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
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
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
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
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
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
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
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
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
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 Programs và A Data-Centric Introduction to Computing
https://htdp.org/
https://dcic-world.org/
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...
“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
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.”
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ế