7 điểm bởi GN⁺ 2023-12-27 | 1 bình luận | Chia sẻ qua WhatsApp
  • Nếu khó chọn dự án phụ, những dự án càng làm lại càng mở rộng phạm vi học hỏi như trình soạn thảo văn bản, game 2D, compiler, hệ điều hành mini sẽ là điểm khởi đầu tốt
  • Trình soạn thảo văn bản giúp bạn tự triển khai cấu trúc lưu tài liệu, hành vi con trỏ, undo/redo, xuống dòng, qua đó học cấu trúc dữ liệu và trừu tượng hóa
  • Ngay cả một game 2D đơn giản như Space Invaders cũng bộc lộ cấu trúc cơ bản của lập trình game, từ vẽ màn hình, xử lý input, game loop, quản lý trạng thái đối tượng, AI kẻ địch, âm thanh, shader đến networking
  • Compiler Tiny BASIC và hệ điều hành mini lần lượt buộc bạn trực tiếp xử lý các khái niệm cấp thấp như lexing, parsing, phân tích ngữ nghĩa, sinh mã, cross compile, bootloading, quản lý bộ nhớ, scheduling
  • Spreadsheet và console emulator kết hợp độ khó của các dự án trước đó, rồi mở rộng thành bước tạo cả máy ảo mô phỏng hành vi thực tế

Những dự án đáng làm đi làm lại

  • Khi cần dự án phụ hoặc muốn học một ngôn ngữ lập trình/framework mới, bạn có thể làm cùng một dự án nhiều lần mà lần nào cũng học được điều khác
  • Các dự án được đề xuất khác nhau về độ khó và lĩnh vực học tập
    • Trình soạn thảo văn bản: cấu trúc dữ liệu, hành vi con trỏ, undo/redo, biểu diễn màn hình
    • Game 2D: vẽ màn hình, xử lý input, game loop, quản lý đối tượng và trạng thái
    • Compiler: lexing, parsing, phân tích ngữ nghĩa, sinh mã
    • Hệ điều hành mini: booting, quản lý bộ nhớ, scheduling, file system
    • Spreadsheet và console emulator: kết hợp các khái niệm của những dự án trước trong một cấu trúc lớn hơn

Trình soạn thảo văn bản

  • Trình soạn thảo văn bản là công cụ dùng hằng ngày, nhưng nếu tự triển khai mà không dùng component textbox cơ bản, bạn sẽ phải xử lý chi tiết các hành vi như di chuyển con trỏ, chọn, chèn và xóa
  • Thử thách lớn nhất là cách lưu tài liệu văn bản trong bộ nhớ
    • Mảng đơn giản có hiệu năng kém khi chèn văn bản vào vị trí không phải cuối tài liệu
    • Các cấu trúc có thể so sánh gồm mảng, rope, gap buffer, piece table
  • Con trỏ không chỉ đơn giản di chuyển lên xuống
    • Khi chuyển sang dòng ngắn, nó đi tới vị trí có thể; sau đó khi gặp dòng đủ dài, nó có hành vi ghi nhớ cột để quay lại cột ban đầu
  • Sau trình soạn thảo cơ bản, bạn có thể thêm undo/redo và xuống dòng
    • Undo/redo khiến bạn so sánh các thiết kế như mảng trạng thái trước đó, memento, mẫu command
    • Xuống dòng buộc bạn tách biểu diễn trực quan của dòng văn bản khỏi biểu diễn trong bộ nhớ
  • Tài liệu tham khảo

Game 2D - Space Invaders

  • Ngay cả game đơn giản cũng đòi hỏi cấu trúc dữ liệu và design pattern riêng
  • Dùng thư viện đồ họa 2D cơ bản như SDL, SFML, PyGame thay vì engine game lớn sẽ không che mất những phần thú vị
  • Game tạo hiệu ứng vật thể chuyển động bằng cách xóa màn hình rồi nhanh chóng vẽ lại từng thành phần
  • Luồng thực tế là cấu trúc lặp lại việc vẽ, nhận input từ người dùng và xử lý logic game trong game loop
  • Xử lý input cần xét đến các hành vi chi tiết như phím hoặc nút chuột được nhấn lần đầu, đang giữ, thả ra, double-click
    • Nếu chỉ liên tục kiểm tra input, các phần còn lại của game sẽ bị dừng
  • Bạn cũng phải trực tiếp xử lý đối tượng game và quản lý trạng thái
    • factory pattern hữu ích để tạo kẻ địch tăng động
    • Có thể áp dụng state machine cho AI kẻ địch
  • Sau game cơ bản, bạn có thể thêm menu tiêu đề, màn hình game over, xử lý để game chạy cùng tốc độ trên các máy khác nhau, và AI kẻ địch thú vị hơn
  • Mở rộng hơn nữa, bạn có thể triển khai hiệu ứng shader, âm thanh và multiplayer online
  • Tài liệu tham khảo

Compiler - Tiny BASIC

Hệ điều hành mini

  • Thuật toán và cấu trúc dữ liệu của hệ điều hành có thể trông trừu tượng hoặc vô dụng trong lớp học, nhưng cũng có thể áp dụng cho nhiều lĩnh vực như game hoặc mô hình dự đoán hành vi con người
  • Khi tự triển khai, bạn sẽ hiểu sâu hơn những gì diễn ra bên trong hệ điều hành
  • Do phụ thuộc phần cứng nên có rào cản bắt đầu và đường cong học tập, nhưng nếu theo sách hoặc tutorial, bạn có thể tạo một OS có thể boot để chạy chương trình do mình viết
  • Các mục cần học gồm
  • Tài liệu tham khảo

Dự án khó hơn: spreadsheet và console emulator

  • Ứng dụng spreadsheet như Excel kết hợp thử thách của trình soạn thảo văn bản và compiler
    • Cần biểu diễn nội dung ô trong bộ nhớ
    • Cần triển khai interpreter cho ngôn ngữ lập trình dùng trong công thức
  • Tài liệu tham khảo về spreadsheet
  • Emulator console trò chơi điện tử là dự án gộp khó khăn của việc triển khai compiler, hệ điều hành và game engine vào một
  • Để emulate một console thật, bạn phải viết máy ảo hoạt động như CPU và các thành phần phần cứng khác
    • Bạn có thể chạy game dành cho console đó trên máy ảo này
  • Là điểm khởi đầu, nên emulate CHIP-8, một console ảo đơn giản hơn console thật
  • NES, SNES, Gameboy, Gameboy Advance cũng có thể emulate và có khá nhiều tài liệu cùng emulator mã nguồn mở, nhưng mỗi console đều có những đặc điểm thú vị riêng
    • Một số game cụ thể có thể phụ thuộc vào bug hoặc tính năng chưa được tài liệu hóa của phần cứng cụ thể
  • PICO-8 đã trở thành một console “fantasy” có lợi nhuận
  • Tài liệu tham khảo về emulator

Các dự án được đề xuất thêm

  • Ý tưởng dự án bổ sung được thu thập từ Hacker News, Reddit, Twitter và email
    • Database viết từ đầu
    • Ray tracer
    • Clone MS Paint
    • Trình chỉnh sửa đồ họa vector
    • Image decoder
    • Web app phòng chat
    • Trình tính các chữ số của số pi
    • Tiện ích terminal thông thường như grep
    • FTP client và server

1 bình luận

 
GN⁺ 2023-12-27
Ý kiến trên Hacker News
  • Việc tạo trình soạn thảo văn bản, trình biên dịch, hệ điều hành, ray tracer có thể giúp bạn trở thành lập trình viên giỏi hơn, nhưng không có nghĩa là trở thành kỹ sư phần mềm giỏi hơn
    Trái lại, bạn có thể thấm nhuần giáo điều “Not Invented Here” tai hại và trở nên tệ hơn trong kỹ nghệ phần mềm
    Hacker thường ám ảnh với các lý thuyết cao siêu như Big-O, cấu trúc dữ liệu, HoTT, nhưng những thứ thiết yếu trong kỹ nghệ thực tế như “phán đoán cái gì nên tự làm và cái gì nên dùng thư viện”, “nhận diện thư viện và framework tốt”, “xác định điểm nào đáng tối ưu”, “viết code mà vài năm sau vẫn đọc được”, “nhìn dự án như một hệ thống phức tạp quy mô lớn gồm cả phụ thuộc phần mềm lẫn phi phần mềm” thì hầu như không được bàn tới hay luyện tập
    Vì vậy, tôi đề xuất công cụ tìm kiếm web như một bài tập thay thế. Những thứ như thuật toán khớp chuỗi đã có người khác làm rồi nên đừng bận tâm; lúc đầu, dù chỉ hỗ trợ một phần của web và 1 người dùng đồng thời, cứ “đơn giản” làm một công cụ tìm kiếm và crawler thật sự chạy được là đủ

    • Tôi không hiểu vì sao công cụ tìm kiếm lại được cho là đặc biệt đòi hỏi “kỹ năng kỹ nghệ thật sự” như chọn thư viện hay nhận ra cơ hội tối ưu hóa
      Trình soạn thảo văn bản, trình biên dịch, hệ điều hành, ray tracer cũng có thể rèn luyện tất cả những hoạt động đó như nhau
      Từ góc nhìn của người từng làm ray tracer được dùng trong nhiều phim điện ảnh dài, tất cả các mục nêu trên đều áp dụng cho dự án đó
      Rốt cuộc, khác biệt có vẻ nằm ở chỗ bạn làm thứ nhỏ và thú vị, hay áp nguyên các ràng buộc bào mòn tâm hồn như khi được công ty trả tiền để làm và làm mất hết niềm vui
    • Lời khuyên đó nghe có vẻ hợp lý, nhưng có vấn đề khi làm phần mềm chỉ từ các khối dựng sẵn
      Thứ nhất, các khối dựng sẵn nhìn chung thường tệ hơn nhiều, và kết quả là phần mềm cũng phản ánh sự tệ đó; cuộc sống không còn là dùng phần mềm nữa mà là bảo trì và dỗ dành những thứ tệ hại đó
      Thứ hai, ngay cả khi chất lượng khối tốt, chúng vẫn giới hạn loại phần mềm có thể tạo ra. Lý tưởng là tưởng tượng hành vi mong muốn, viết phần mềm để làm điều đó, và trong quá trình ấy tạo ra các khối
      Nếu chỉ dùng khối dựng sẵn, rất nhiều phần mềm xuất sắc sẽ không thể được tạo ra ngay từ đầu; tôi nghĩ đó cũng là lý do thực tế quanh ta không có nhiều phần mềm xuất sắc
      Nếu bạn làm “phần mềm gần như giống những thứ vẫn thường thấy” thì vấn đề thứ hai ít áp dụng hơn, và vấn đề thứ nhất cũng có thể chịu được vì chủ yếu chỉ đi theo happy path. Nhưng loại phần mềm đó chẳng bao lâu nữa sẽ được AI dùng, chứ không phải con người
    • Điều này giống như nói với một học sinh học nhạc cụ rằng vì trong dàn nhạc còn cần những kỹ năng khác nên đừng luyện âm giai hay etude
      Những kỹ năng đó cũng quan trọng, nhưng đến một lúc nào đó bạn phải xây nền tảng cơ bản, và việc trở thành lập trình viên giỏi hơn chắc chắn cũng giúp ích cho toàn bộ các kỹ năng nêu trên
    • Bài viết nói là lập trình viên, không phải kỹ sư phần mềm
      Cá nhân tôi xem kỹ nghệ phần mềm là việc làm để trả hóa đơn, còn lập trình là việc tôi bắt đầu vì thấy vui
      Các dự án trong bài này thuộc loại tôi muốn làm cho vui nếu có thời gian
  • Nếu nhìn từ góc độ UI/Web, ngoài bảng tính vốn rất hữu ích để hiểu hệ thống luồng dữ liệu, tôi đề xuất những thứ sau
    Làm một trò chơi điện tử đơn giản bằng Unity hoặc Unreal sẽ giúp bạn hiểu các ràng buộc hiệu năng trong game, nơi 30–60fps là quan trọng, và cũng giúp tạo giao diện nhanh ở những nơi khác, kể cả web
    Tạo một framework JavaScript đơn giản tương tự React sẽ giúp hiểu luồng dữ liệu và xử lý sự kiện
    Tự làm một thư viện HTTP bọc XMLHTTPRequest sẽ giúp bạn hiểu từ đầu cách gửi và đọc HTTP request, dù hiện nay đã có fetch, và về sau hữu ích khi debug các vấn đề như CORS hay request OPTIONS

    • Với mục đích này, Godot có thể là lựa chọn tốt hơn Unity hoặc Unreal. Không chỉ không cần rơi vào giấy phép độc quyền, bạn còn có thể xem bên trong đang diễn ra chuyện gì
  • Khi đó cũng đã có thảo luận
    Challenging projects every programmer should try - https://news.ycombinator.com/item?id=21790779 - Dec 2019 (297 comments)
    Cũng có bài liên quan
    More challenging projects every programmer should try - https://news.ycombinator.com/item?id=25489879 - Dec 2020 (223 comments)

    • Liên kết ngoài của bài thứ hai trả về 404
  • +1 cho hệ điều hành mini
    Lập trình viên ứng dụng phụ thuộc vào rất nhiều chức năng hệ điều hành như quản lý bộ nhớ, hệ thống tệp, v.v., và cuối cùng sẽ tự hỏi “những thứ này chạy phía sau như thế nào?”
    Vì vậy, tôi đã nghịch xv6(https://github.com/mit-pdos/xv6-public) trong thời gian rảnh
    Học nhiều thuật toán lập lịch tiến trình trong giáo trình và tự tay triển khai chúng là hai việc hoàn toàn khác nhau, và tôi học được rất nhiều
    Với tư cách lập trình viên ứng dụng di động, khả năng kiến thức này liên quan đến công việc gần như bằng 0, nhưng chắc chắn là rất vui

  • Việc từng phát triển game 2D mà không dùng engine là trải nghiệm khiến tôi khiêm nhường nhất, vì nó giúp tôi nhận ra máy tính đã trở nên nhanh đến mức phi lý thế nào
    Ngay cả khi làm những việc mà bạn chắc mẩm là sẽ quá chậm, trên Game Boy cũng có thể thực hiện một triệu phép toán mỗi giây, nên nó cứ chạy thôi. Hóa ra một triệu là con số lớn hơn mình tưởng
    Bạn có thể nghĩ: “Khoan đã, mỗi lần đều tìm và vẽ toàn bộ sprite ư? Không có phép tính sai khác thông minh để chỉ biết những gì cần thay đổi, cũng không có buffer thứ hai tham chiếu frame trước để giảm việc phải làm sao?”, rồi còn ngạc nhiên hơn khi nhìn vào những game phức tạp hơn nhiều về sau mới bắt đầu thật sự dùng các kỹ thuật này

    • Ngày xưa cũng có những mẹo thú vị ở cả phía ứng dụng lẫn phần cứng để hỗ trợ các vấn đề như vậy
      Chẳng hạn sprite atlas là cách điển hình mà kiểu cấu trúc dữ liệu này được tận dụng. Không có lý do gì phải tải lên từng sprite thường được render theo một cách có thể dự đoán được mỗi lần; chỉ cần tải một ảnh lớn rồi sample một phần của nó là được
      Theo tiêu chuẩn ngày nay thì đúng là vậy. Với phần cứng thương mại phổ thông, thậm chí không cần là PC chơi game, gần như mọi thứ của khoảng 15 năm trước đều có thể xử lý bằng kiểu render “thô bạo” là vẽ cảnh rồi vẽ lại
    • Tôi bắt đầu bằng việc làm game 2D trên TRS-80 Color Computer, và điều đó cho tôi nền tảng hiểu biết khá tốt về máy tính
      Vì chỉ có phần cứng thuần và assembly, nên phải tự làm mọi thứ như đồ họa, âm thanh, nhập liệu, quản lý bộ nhớ, v.v.
      Nếu có một môi trường được đơn giản hóa, nơi lập trình viên mới có thể xử lý tất cả những thứ này để làm game 2D, nhưng giảm bớt gánh nặng quá mức chỉ để khiến nó chạy được, thì đó có lẽ sẽ là cách nhập môn lý tưởng
  • Nếu bạn nghĩ cần factory pattern để làm Space Invaders thì có gì đó sai rồi
    Tôi cho rằng gần như không có khả năng bản gốc có các khái niệm thiết kế như vậy

    • Đó là kết quả của 30 năm lập trình hướng đối tượng và design pattern
      Một khi bộ não bị nhiễm nó, nó bắt đầu tìm cách lây lan sự nhiễm đó
    • Không có chỗ nào trong bài viết nói hay ám chỉ rằng cần factory pattern để triển khai Space Invaders
      Hay là chúng ta đã đọc hai bài khác nhau?
  • Tôi muốn thử thứ gì đó mang tính vật lý hơn nhiều, như mô phỏng chính xác động lực học bay của robot, drone tự lái, hoặc tàu vũ trụ có các tham số GNC có thể lập trình
    Tôi có cuốn “Fundamentals of Astrodynamics” của Bate, Mueller, v.v., và muốn thử làm gì đó trong kỳ nghỉ này
    Phần còn lại có vẻ sẽ tốn kém nên tôi đang nói đến mô phỏng. Tôi thật sự rất quan tâm đến khía cạnh GNC của robot, và sẽ rất thích nếu có tài liệu hay được gợi ý

    • https://ksp-kos.github.io/KOS/ Kerbal Space Program có thể không mô phỏng khí động học thực tế đến mức bạn muốn, nhưng có vẻ nhiều người thích viết phần mềm GNC trong đó
    • Robot hai bánh tự cân bằng có vẻ là một dự án thú vị và tương đối an toàn
      Ý tôi là một thứ giống Segway có thể đứng yên một chỗ mà không bị ngã hoặc lao khỏi bàn
      Có lẽ sẽ cần vi điều khiển, IMU, bộ điều khiển động cơ bước, động cơ, bánh LEGO, và có thể một khúc gỗ
      Tôi chưa tự làm nên có thể đoán sai khá nhiều
    • Tôi tò mò bạn định làm gì với “Fundamentals of Astrodynamics”
      Rất muốn nghe thêm cuốn sách đó nói về gì và có thể thử những dự án nào
    • Cùng cảm giác đó. Các dự án cá nhân của tôi hầu như đều có yếu tố phần cứng
      Sau khi làm việc với phần mềm cả ngày, thật sự rất tuyệt khi làm việc hướng tới một vật thể vật lý
  • Tôi nghĩ một ray tracer đồ chơi nhỏ cũng là một bài tập rất đáng thử
    Chỉ cần xử lý hình cầu, vài nguồn sáng, phản xạ khuếch tán và phản xạ gương rồi xuất đồ họa bitmap là đủ
    Nếu không mở rộng quá đà, đây có thể là một dự án có phạm vi tương đối được giới hạn tốt

  • Đây là một danh sách thú vị, và dù còn tùy xu hướng cá nhân cùng hoàn cảnh, nó là điểm khởi đầu tốt nếu bạn đang tìm ý tưởng
    Tôi sẽ không nói rằng mọi lập trình viên đều nên thử điều gì đó, nên chỉ ghi lại những thứ cá nhân tôi đã chọn làm
    Trên Sinclair ZX Spectrum, tôi đã làm một trình biên tập khuông nhạc và tracker rất thô sơ, còn game 2D thì làm một bản Space Invaders chỉ có một kẻ xâm lược
    Chiếc máy tính đó thậm chí không phải của tôi. Trên chiếc 386, máy tính đầu tiên của tôi, tôi đã làm bộ nén Huffman, chỉ mục B-Tree nhanh hơn DBase/Clipper, trình tạo form hướng đối tượng, và nhiều chương trình nền DOS; một trong số đó về sau được dùng trong quy trình cài đặt của một công ty lớn
    Vài năm sau, tôi còn làm trình kiểm tra email qua dial-up, parser thủ công để tô sáng cú pháp, một thứ giống bảng tính, và đến giờ tôi vẫn làm việc đó. Chắc chắn còn có những thứ tôi đã bỏ sót

  • Danh sách hay. Sẽ tốt nếu duy trì nó như một danh sách sống, để có thể cùng phát triển theo thời gian
    Tôi muốn bổ sung hai điều
    Nếu xây dựng một memcached gọn nhẹ, bạn sẽ cần kết hợp các thuật toán cơ bản với các thực hành thiết kế hệ thống tốt. Đây là một vấn đề “đơn giản”, nhưng cần suy nghĩ kỹ từ nhiều góc độ như vô hiệu hóa cache, tính đồng thời, quản lý bộ nhớ, v.v.
    Tự tạo Docker của riêng mình cũng là một ý hay. Nó không phức tạp như nghe có vẻ, và cho bạn cơ hội hiểu các nền tảng của lập trình hệ điều hành, thứ mà các kỹ sư ngày nay không còn dùng nhiều trong công việc hằng ngày