SICP: Cuốn sách khoa học máy tính duy nhất đáng đọc hai lần? (2010)
(simondobson.org)- Từ việc cho một sinh viên mượn sách đọc mùa hè, Simon Dobson một lần nữa xác nhận rằng SICP là cuốn sách khoa học máy tính có ảnh hưởng lớn nhất đến sự nghiệp và mối quan tâm nghiên cứu của ông
- Khác với cách dạy nhập môn xoay quanh Pascal, cuốn sách bắt đầu từ giá trị, tên, binding và điều khiển để cho thấy lập trình có thể trở thành điều gì
- Trong Scheme, sách kết nối từ trừu tượng lambda, tính toán bậc cao, stream, đánh giá lười, trình thông dịch và trình biên dịch, garbage collection, bộ nhớ ảo, mã máy, cho đến ngôn ngữ chuyên biệt theo miền
- Ảnh hưởng lớn nhất nằm ở thiết kế phân tầng, tức xây dựng các hệ thống phức tạp bằng nhiều lớp ngôn ngữ, và ở góc nhìn xem khoa học máy tính là ngành học về “làm như thế nào” hơn là “là gì”
- Cuốn sách mua năm 1988 đến năm 2010 vẫn đáng đọc lại một cách thực dụng, và SICP vẫn là một sách nền tảng bền vững trong khoa học máy tính
Lần đầu gặp SICP
- Sau khi cho một sinh viên mượn Structure and Interpretation of Computer Programs để đọc trong mùa hè, Simon Dobson nhớ lại rằng cuốn sách này gần như là tác phẩm nền tảng nhất đối với ông trong toàn bộ khoa học máy tính
- Tựa đầy đủ là Structure and Interpretation of Computer Programs của Hal Abelson và Jerry Sussman, do MIT Press xuất bản năm 1984, và cũng được gọi là SICP
- Cuốn sách vẫn còn được xuất bản, và toàn văn được cung cấp trực tuyến
- Dobson biết đến cuốn sách này như giáo trình được khuyến nghị sau khi hoàn thành khóa lập trình đầu tiên vào năm thứ hai của bậc đại học thứ nhất tại Newcastle upon Tyne
- Với ông khi đó, một người đang tìm đường trong khoa học máy tính, SICP không phải là “lập trình của thời ấy” được đại diện bởi Pascal, mà là cuốn sách cho thấy những hình thái lập trình có thể có
Những khái niệm được xây dựng bên trong Scheme
- SICP bắt đầu từ các yếu tố cơ bản của lập trình như giá trị, tên, binding và điều khiển, rồi mở rộng sang nhiều chủ đề
- trừu tượng lambda và tính toán bậc cao
- cấu trúc dữ liệu phức tạp chứa nội dung tính toán
- tính mô-đun, khả năng thay đổi
- stream
- đánh giá lười
- xây dựng trình thông dịch và trình biên dịch
- quản lý lưu trữ, garbage collection, bộ nhớ ảo
- mã máy
- ngôn ngữ chuyên biệt theo miền
- Phạm vi đề cập rộng đến mức dễ gây choáng ngợp, nhưng nhờ cách viết và cách tổ chức của các tác giả, cuốn sách vẫn giữ được tính nhất quán
- Đặc biệt, mọi khái niệm đều được xử lý trong một framework ngôn ngữ duy nhất là Scheme, và khái niệm sau được xây dựng trên nền những gì đã học trước đó
Thiết kế chương trình nhìn từ thiết kế ngôn ngữ
- Đặc điểm thứ hai có ảnh hưởng lớn trong SICP là Hal Abelson và Jerry Sussman xem mọi thứ như một bài thực hành thiết kế ngôn ngữ
- Cuốn sách nhấn mạnh thiết kế phân tầng, tức tổ chức các hệ thống phức tạp bằng nhiều cấp độ ngôn ngữ
- Mỗi cấp độ được cấu thành bằng cách kết hợp các bộ phận được xem là nguyên thủy ở cấp độ đó
- Các bộ phận được tạo ra ở một cấp độ sẽ được dùng làm phần tử nguyên thủy cho cấp độ tiếp theo
- Ngôn ngữ của mỗi cấp độ có các phần tử nguyên thủy, phương tiện kết hợp và phương tiện trừu tượng hóa phù hợp với mức chi tiết tương ứng
- Bản thân trừu tượng hóa phân cấp vốn quen thuộc với các nhà khoa học máy tính, nhưng khác biệt quan trọng ở đây là quan điểm rằng mỗi tầng phải có thể lập trình được
- Theo góc nhìn này, tầng không chỉ là một thiết bị che giấu thông tin, mà là phương tiện để xử lý tính toán và biến đổi
- Trong các ngôn ngữ lập trình chủ lưu, kiểu phân tầng này khó dẫn đến việc mở rộng bản thân ngôn ngữ
- Java từ trên xuống dưới vẫn là Java; có class và thư viện, nhưng không có cấu trúc điều khiển mới
- Ngay cả khi một cấu trúc ngôn ngữ riêng cho một miền cụ thể là hữu ích, cũng khó thêm nó một cách dễ dàng bên trong ngôn ngữ
- Ngược lại, nếu muốn cấm dùng một cấu trúc nào đó trong một miền nhất định, cũng không thể loại bỏ nó trong ngôn ngữ
- Java-ME đã lược bớt một số tính năng để chạy trên thiết bị nhỏ, nhưng đó không phải là cách có thể làm mà không viết lại trình biên dịch
“Làm như thế nào” hơn là “là gì”
- Ảnh hưởng quan trọng thứ ba là góc nhìn của SICP về việc khoa học máy tính thực sự xử lý điều gì
- SICP xem cuộc cách mạng máy tính là một cuộc cách mạng trong cách suy nghĩ và cách biểu đạt suy nghĩ
- Cuốn sách giải thích điều này bằng nhận thức luận thủ tục (procedural epistemology)
- Nếu toán học cổ điển cung cấp một khuôn khổ để xử lý chính xác câu hỏi “là gì”
- thì tính toán cung cấp một khuôn khổ để xử lý chính xác câu hỏi “làm như thế nào”
- Dobson từng tiếp nhận quan điểm rằng máy tính giống như một chiếc kính hiển vi mới, vừa hỗ trợ các cách tiếp cận hiện có vừa mở ra khoa học mới
- Khía cạnh “làm như thế nào” của khoa học máy tính xuất hiện trở lại trong nhiều lĩnh vực
- mô tả hoạt động của mạng cảm biến có thể thích nghi trong khi liên tục phản ánh các hiện tượng nơi chúng được triển khai
- diễn giải dữ liệu quy mô lớn được khai phá và kết hợp trên toàn web
- nắm bắt các phương pháp và quy trình khoa học để tự động hóa
- Sự phong phú của những lĩnh vực này khuyến khích tích hợp thông qua ngôn ngữ lập trình hơn là phần mềm đóng gói, giúp giữ giao diện và cấu trúc linh hoạt và có thể thử nghiệm bằng các ngôn ngữ như R
Vì sao một cuốn sách cũ vẫn được đọc
- Bên trong cuốn sách của Dobson có ghi ngày mua là tháng 9 năm 1988, và tính đến năm 2010, cuốn sách gần 22 năm tuổi này vẫn còn liên quan
- Ông xem SICP gần như là cuốn sách khoa học máy tính duy nhất ở độ tuổi đó có thể đọc lại một cách hữu ích, chứ không chỉ vì giá trị quan tâm lịch sử
- Trong sách toán, nội dung bền lâu không phải là hiếm, nhưng trong khoa học máy tính, nơi ý tưởng chuyển động nhanh và có nhiều chủ đề nhất thời, điều này rất khó thấy
- Việc nội dung của SICP hầu như không lỗi thời cho thấy cuốn sách đã nắm bắt tốt các khái niệm cốt lõi của khoa học máy tính
- Vì vậy, SICP là một trong số ít sách khoa học máy tính đáng đọc hơn một lần, và được đánh giá là cuốn sách đã chắt lọc bản chất của lĩnh vực theo cách dễ tiếp cận và vượt qua thử thách của thời gian, giống như Lectures on Physics của Feynman trong vật lý
- Bản cập nhật ngày 27/1/2024 cho biết cuốn sách này cũng được đưa vào annotated Lisp bibliography với mục Structure and interpretation of computer programs
1 bình luận
Các ý kiến trên Hacker News
Những “kinh điển” như SICP nói về thiết kế chương trình, nhưng ngày nay thiết kế hệ thống có vẻ là năng lực quan trọng hơn nhiều
Không rõ hệ thống phân tán có được tính vào “khoa học máy tính” hay không, nhưng trên thực tế đó là vấn đề phải giải quyết thường xuyên hơn
Tôi thường làm hệ thống đơn giản nhất có thể, dùng công cụ observability để tìm những điểm thiết kế còn thiếu, rồi khi cần mới lôi cấu trúc dữ liệu hoặc các giải pháp “mang màu sắc khoa học máy tính” ra dùng
Trong phần lớn trường hợp, ký pháp Big-O và độ phức tạp thời gian chạy không quan trọng, và có thể giải quyết nhiều vấn đề bằng mảng cùng CPU nhanh
Ngay cả khi có vấn đề hiệu năng, trước tiên cũng phải profiling để tìm bottleneck
Khoa học máy tính không dạy kỹ cách cache bộ nhớ của CPU hoạt động
Một thuật toán đồ thị đẹp có thể có độ phức tạp thời gian chạy tốt, nhưng lại phá hỏng CPU cache, nên có thể chậm hơn một mảng tận dụng cache tốt
Những vấn đề phổ biến hơn trong thực tế là xử lý chịu lỗi, tính đúng đắn của khóa phân tán và hàng đợi, cùng khả năng mở rộng hệ thống
Có thể tôi thiên lệch vì có nền tảng kỹ thuật máy tính/kỹ thuật điện
Tôi đã học về cache bộ nhớ CPU bằng sách của Hennessy và Patterson ngay học kỳ đầu bậc cử nhân CS cách đây 30 năm, và theo tôi biết thì hiện vẫn còn được dùng
Chịu lỗi, tính đúng đắn của khóa phân tán và hàng đợi, khả năng mở rộng hệ thống cũng được dạy trong CS bậc cử nhân, chứ không cần nền tảng kỹ thuật máy tính/kỹ thuật điện đặc biệt nào
Vẫn có những công việc làm framework, engine cơ sở dữ liệu, công cụ quản lý phiên bản, và các việc này hằng ngày đòi hỏi kiến thức CS sâu như thuật toán và cấu trúc dữ liệu
Nhưng những vị trí như vậy đã ít hơn trước, và trong nhiều trường hợp người ta dùng Postgres thay vì tự triển khai DB engine cho ứng dụng
Phần lớn công việc là triển khai logic nghiệp vụ; nếu hiểu cơ sở dữ liệu hoạt động bên trong ra sao thì sẽ tạo ra kết quả tốt hơn, nhưng vẫn có thể làm ra rất nhiều phần mềm chạy được mà không biết index được lưu trên đĩa như thế nào
Nhiều sinh viên tốt nghiệp CS nhầm tưởng công việc của mình là viết framework, nhưng thực tế là dùng các framework hiện có và triển khai logic nghiệp vụ, đồng thời dùng nền tảng CS để hiểu sâu các framework đó
Dữ liệu tồn tại dưới dạng “page” trên đĩa, còn trong RAM có một số cố định “page slot”
Việc di chuyển page giữa đĩa và RAM rất chậm, nên phải giảm tối đa
Vì vậy ngay cả những vấn đề tưởng nhỏ nhặt cũng trở nên thú vị. Trong khoa học máy tính cổ điển không có riêng khái niệm “join”, vì nó không đủ phức tạp để cần đặt tên
Dễ nghĩ nghiên cứu thuật toán như một bản chất thuần túy, nhưng cũng có thể xem hiệu quả thuật toán chỉ có ý nghĩa trong bối cảnh dữ liệu và phần cứng cụ thể
Nhờ vậy công việc trở nên thú vị, và vì không thể chỉ áp dụng thư viện hay các lời giải kiểu sách dạy nấu ăn ở mọi nơi, chuyên môn thuật toán vẫn hữu ích
Hiện tôi đang khổ sở với một component phụ trách một thay đổi nhỏ, vì nó có quá nhiều state không cần thiết và xử lý đồng thời hai abstraction
Khi xử lý file, nó dùng cả file system và cơ sở dữ liệu để lưu state; thiết kế quá lộn xộn đến mức tôi thấy kinh ngạc
Tôi đã mất vài ngày để tránh làm theo kiểu cũ là chồng thêm vào và khiến nó khó hiểu hơn
Văn hóa pull request dường như khiến người ta approve bất kỳ thứ rác rưởi nào mà không có thời gian suy nghĩ sâu về code thực tế
Tôi mong code review trực tiếp quay trở lại
Một cuốn sách xuất bản năm 2021
Liên kết tới bản miễn phí của bài viết đã bị hỏng
https://mitp-content-server.mit.edu/books/content/sectbyfn/b...
https://web.mit.edu/6.001/6.037/sicp.pdf
Mãi đến hôm nay tôi mới thấy bản PDF chính thức
Khoảng năm 2001 thì chỉ có bản HTML là miễn phí, và ai đó đã chuyển nó sang TeXinfo: https://www.neilvandyke.org/sicp-texi/
Nếu bây giờ muốn học theo SICP, bạn có thể chạy code bằng MIT Scheme hoặc DrRacket: https://www.neilvandyke.org/racket/sicp/
Bản phát hành hiện tại (v12.1) chạy được trên Mac dùng CPU Intel chạy Sequoia, hoặc trên Apple silicon thông qua Rosetta
Tuy vậy trình biên dịch mã native có hơi hỏng, và có lẽ không cần cho SICP
Tôi nghĩ nó từng chạy được trên macOS trước Monterey, nên có thể các phụ thuộc do Apple cung cấp đã thay đổi, nhưng tôi chưa lần theo
Nếu không nhất thiết cần MIT Scheme và không muốn khổ sở với việc biên dịch, Racket có thể là lựa chọn tốt hơn
Theo tôi biết thì nó có chế độ SICP rõ ràng
Tôi từng học bằng GNU Guile, nhưng có những khác biệt cú pháp nhỏ giữa Guile và MIT Scheme nên khá phiền
Định dạng tốt hơn bản gốc của MIT: https://sarabander.github.io/sicp/
Trước đây từng có một package, nhưng đã gần 20 năm không được bảo trì
Ngược lại, DrRacket có package riêng để giải các bài đó
Có thể xem các bài giảng được ghi hình năm 1986 trong đó Abelson và Sussman giảng nội dung cuốn sách này
Phần giải thích về cách tạo và kết nối nhiều tầng trừu tượng đến giờ vẫn hữu ích với tôi, cả cho cá nhân lẫn khi mentoring
Trong video là lesson 3A, đoạn 1:07:55
https://m.youtube.com/playlist?list=PLE18841CABEA24090
The Elements of Programming Style đáng đọc ba lần, và tôi đã hưởng lợi từ việc đọc nó còn nhiều lần hơn thế
Nếu quan tâm, đây là bài review tôi viết năm 2010: https://reprog.wordpress.com/2010/03/06/programming-books-pa...
https://elementsofprogramming.com/
Phần tôi thích nhất trong SICP và vẫn nhớ suốt nhiều năm là ý tưởng lập trình theo mong muốn
Đó là cách xây dựng thứ gì đó từ trên xuống, như thể các routine cấp thấp đã tồn tại sẵn
Sau đó bạn thực sự tạo ra các routine cấp thấp đó và đi dần xuống đáy
Tôi thấy lối tư duy này rất hợp với phát triển hướng kiểm thử
Bạn viết test trước cho chức năng mình ước là có, rồi đi hiện thực hóa điều ước đó
Có vẻ hầu hết lập trình viên xây từ dưới lên, rồi cuối cùng nhận được một thứ mà chẳng ai từng muốn
Bạn có thể tình cờ ước một đối tượng mà mình chưa biết bản chất thật sự của nó, và khi đó sẽ tạo ra một mớ hỗn độn mong manh ở đáy
Thường thì chuyện là vậy, vì bản chất thuật toán của sự vật hiếm khi trực quan
Bắt đầu từ dưới lên giống như bắt đầu từ các quark mà bạn thực sự có, chứ không phải từ “giá mà phép màu tồn tại”
Không có phép màu; khi chạm đáy thì thứ bạn có là quark chứ không phải hạt ma thuật, và trong quá trình đó bạn cũng đánh mất các manh mối ngữ cảnh có thể giúp chuyển đổi giữa hai nền vật lý
Cả hai cách tiếp cận đều hữu ích. Để giải những vấn đề sâu, đôi khi bạn phải mạnh dạn ước
Nhưng cá nhân tôi thích đặt phép màu ở tầng ngay dưới tầng cao nhất
Tức là xây từ dưới lên, rồi ngay trước business logic thì tạo một tầng phép màu tiện dụng để chuyển đổi qua lại với ngôn ngữ nghiệp vụ
Như vậy có thể điều chỉnh được, và không tạo ra một mớ rối rắm đan xen xuống tận đáy
Trước hết ông viết ra cách định dạng/gắn thẻ có vẻ phù hợp, rồi hình dung một cách lập trình phù hợp với markup—vì vậy là macro—sau đó mới đi vào triển khai
Tôi cũng đang thử một cách tương tự trong công việc tạo thư viện mô hình hóa G-code bằng OpenSCAD
Gần đây tôi đã viết lại bằng OpenPythonSCAD “thuần”, hy vọng nó sẽ trở nên dùng được
Nên thử Pharo
SICP là cuốn sách phù hợp nhất để đọc như cuốn đầu tiên khi học khoa học máy tính
Sau nhiều năm lập trình như một sở thích, tiếp xúc với sách về lập trình có cấu trúc và nhiều ngôn ngữ từ Pascal đến Common LISP, tôi dùng Abelson & Sussman trong chương trình khoa học máy tính bậc đại học, và cảm giác như được khai sáng
Nó cho thấy sự đơn giản, vẻ đẹp và tính tương tác của Scheme, đồng thời dạy rằng khoa học máy tính là việc xếp chồng nhiều loại trừu tượng hóa thành từng lớp
Bắt đầu từ trừu tượng hóa thủ tục và trừu tượng hóa dữ liệu, rồi đi tới việc tự định nghĩa ngôn ngữ chuyên biệt miền, triển khai trình biên dịch cho nó, và thậm chí định nghĩa phần cứng mới bên trong phần mềm
Mọi thứ trông quá tự nhiên, và chỉ một bậc thầy thực sự mới có thể khiến nó trông như vậy
Tuy nhiên, nên mua ấn bản thứ 2, không phải ấn bản đầu hay các bản gần đây hơn
Bản gần đây dùng Python thay cho Scheme, và không hay lắm
Tôi đã rất muốn thật sự thích SICP, nhưng Lisp lại cản trở
Tôi thích Haskell và Standard ML
Tôi tò mò không biết có ai từng có trải nghiệm tương tự không
Sẽ rất thú vị nếu có cuốn sách nào có tinh thần giống SICP nhưng dùng một ngôn ngữ khác làm phương tiện
Tôi không muốn học SICP bằng JavaScript
Tác giả đề xuất dùng KRC hoặc Miranda thay cho Scheme
Tôi không rõ về KRC, nhưng Miranda là một ngôn ngữ lập trình hàm kiểu tĩnh đã ảnh hưởng đến Haskell
Một cuốn sách giống SICP mà không dùng Scheme hay Lisp có lẽ sẽ hoàn toàn khác SICP, hoặc ít nhất sẽ không thể dạy cùng những điều đó
Theo kinh nghiệm của tôi, Haskell và ML khó hiểu hơn Scheme rất nhiều, nên tôi tò mò là bạn thấy khó ở điểm nào
Tôi bắt đầu đọc tháng trước và cảm thấy nó bao quát quá rộng
Nó lướt qua quá nhiều nguyên lý toán học thú vị, và vừa đến lúc bắt đầu hấp dẫn thì lại chuyển sang chủ đề tiếp theo
Nói cách khác là quá nông
Nhìn lại thì việc tôi đã xem khá nhiều bài giảng và tài liệu phái sinh từ SICP cũng không giúp ích, vì mỗi khi một chủ đề được giới thiệu, tôi lại nghĩ “lại cái này nữa à”
Dù vậy tôi vẫn cố làm đến cùng, và chính vì không đủ thông minh để xử lý Lisp nên tôi lại học được cực kỳ nhiều
Nhờ mất quá nhiều thời gian đọc code, tôi cảm thấy mình học được nhiều hơn so với khi dùng một ngôn ngữ quen thuộc
Cũng có phiên bản SICP bằng Python
Tôi không tự làm đến cùng mà chỉ lướt qua, nên đây không phải là lời khuyên dùng, chỉ để lại liên kết như bằng chứng rằng nó tồn tại
https://wizardforcel.gitbooks.io/sicp-in-python/content/0.ht...
Trên giá sách của tôi hai cuốn này cũng nằm cạnh nhau, và chắc chắn đáng đọc
Lần đọc thứ hai, tôi đào sâu vào các chú thích cuối trang và tài liệu tham khảo, và ở đó cũng có cả một thế giới rộng lớn tuyệt đẹp
Nếu tôi nhớ không nhầm, có một bài báo của Sussman và nhóm thiết kế bộ xử lý lập trình được tùy chỉnh để tính các tính chất của thiên thể, tức quỹ đạo
Như thường lệ, nội dung đó khiến đầu óc choáng ngợp
SICP đã giúp tôi, khi còn ở bậc đại học và mới chỉ học một số mô hình hạn chế, sớm hiểu rằng có nhiều mô hình lập trình khác nhau
Đây là một trong những cuốn sách cho tôi cảm giác rằng dù đọc tài liệu của bất kỳ ngôn ngữ, thư viện hay framework nào, tôi cũng có thể định hướng được
Bên cạnh SICP, tôi cũng xếp toàn bộ bộ The Little * vào nhóm tài liệu đáng đọc ít nhất hai lần
Types and Programming Languages cũng hay
Đó là khoa học máy tính có thể áp dụng vào công việc của tôi, nhưng không thể chỉ đọc mà còn phải triển khai
Nếu không lặp lại, bạn sẽ quên một phần
Có thể vì cá nhân tôi biết và kính trọng ông ấy, nhưng tôi khá thường xuyên đọc lại sách và bài viết của Dijkstra
Giờ đây khó áp dụng trực tiếp, nhưng tốt cho tư duy, và cá nhân tôi xem ông là một cây bút xuất sắc