16/08/2018, 11:06

Triết lý Unix và Node.js

Tại hội nghị TxJS vừa rồi, tôi đã có một bài trình bày trong đó có đề cập rằng Triết lý Unix là một phần quan trọng của mô hình, quan điểm, và văn hóa của Node.js. Như thường lệ, tôi đã đăng tải slide bài trình bày đó lên internet trước khi có thêm một video bàn về vấn đề này. Vì một ...

Tại hội nghị TxJS vừa rồi, tôi đã có một bài trình bày trong đó có đề cập rằng Triết lý Unix là một phần quan trọng của mô hình, quan điểm, và văn hóa của Node.js. Như thường lệ, tôi đã đăng tải slide bài trình bày đó lên internet trước khi có thêm một video bàn về vấn đề này.

Vì một vài lý do, sự đề cập ngắn gọn đó về “Triết lý Unix” đã khiến cho một số người giận dữ. Vì tôi chỉ có 25 phút để trình bày trong bài nói chuyện đó, và tất cả các slide có lẽ cũng đã có thể chuyển tải được toàn bộ nội dung cần nói, bởi vì tôi đã trau chuốt khá tỉ mỉ. Rất có thể, cái video tiếp theo này sẽ không bổ sung thêm gì nhiều cho ngữ cảnh đó. Nhưng mục đích của nó là để gợi ra câu chuyện cần bàn luận, như vậy có lẽ nó sẽ thành công nếu mời gọi được những lời chỉ trích. Nói cho cùng thì tất cả những việc này cũng chỉ vì mục đích học tập, chỉ là một lời mời cho giáo dục, vì vậy tôi nghĩ rằng mình muốn được có lời giải thích.

Eric S. Raymond đã tổng hợp một số những lời giải thích tốt nhất về Triết lý Unix trong cuốn sách của mình có tên là, The Art of Unix Programming (Nghệ thuật của lập trình Unix). Ông đã đề cập về 17 nguyên tắc cụ thể, nhưng công thức yêu thích của tôi về Triết lý Unix là lời giải thích ngắn gọn từ Doug McIlroy và đã được trích dẫn trong cuốn sách A Century Quarter of Unix (Một phần tư thế kỷ của Unix).

Đây là triết lý Unix:

  • Viết ra các chương trình mà mỗi cái chỉ làm một việc và phải làm thật tốt.
  • Viết ra các chương trình để làm việc với nhau.
  • Viết ra các chương trình có thể xử lý dòng văn bản (text stream), bởi vì đó là một giao diện phổ quát.

Công thức 4 điểm ban đầu của McIlroy dài hơn một chút, có nội dung như sau:

  1. Hãy khiến cho mỗi chương trình làm một việc thật tốt. Để làm một việc mới, hãy xây dựng lại từ đầu chứ đừng làm phức tạp hóa các chương trình cũ bằng cách thêm thắt các tính năng mới.
  2. Mong chờ đầu ra của mỗi chương trình sẽ trở thành đầu vào của chương trình khác, đó là những chương trình chưa được biết trước. Đừng làm lộn xộn đầu ra với những thông tin không liên quan. Tránh các định dạng đầu vào nghiêm ngặt kiểu cột hoặc nhị phân. Không nhấn mạnh đầu vào tương tác.
  3. Thiết kế và xây dựng phần mềm, thậm chí các hệ điều hành, phải được dùng thử sớm, tốt nhất là trong vòng vài tuần. Đừng ngần ngại vứt bỏ những phần chưa tốt và xây dựng lại chúng.
  4. Sử dụng các công cụ ưa thích để giúp đỡ làm giảm nhẹ các công việc trong một tác vụ lập trình, ngay cả khi bạn phải đi đường vòng để xây dựng các công cụ và có thể phải bỏ đi một vài công cụ trong số đó sau khi bạn đã hoàn tất việc sử dụng chúng.

Mike Gancarz, người đã làm việc trên hệ thống X Window, tổng kết lại Triết lý Unix trong 9 điểm sau:

  1. Nhỏ là đẹp.
  2. Hãy khiến cho mỗi chương trình làm một việc thật tốt.
  3. Xây dựng một nguyên mẫu (prototype) càng sớm càng tốt.
  4. Lựa chọn khả năng di động (portability) hơn là hiệu suất.
  5. Lưu trữ dữ liệu trong các file text.
  6. Sử dụng phần mềm để gia tăng lợi thế của bạn.
  7. Sử dụng các shell script để làm tăng lợi thế và tính di động (portability).
  8. Tránh những giao diện người dùng bị fix cứng.
  9. Tạo cho mỗi chương trình một bộ lọc (filter).

Quan điểm cuối cùng thực sự tạo ra tiếng vang với những gì mà Ryan Dahl đã thường nói, “Mỗi chương trình là một proxy.” Ba điểm đầu tiên về cơ bản là các quy tắc của James Halliday trong cuộc sống.

Mọi người thường có những cách hiểu sai về Triết lý Unix, và họ chủ yếu chỉ thấy cây mà không thấy rừng. Triết lý Unix không phải là về một sự thực thi cụ thể, hoặc bất cứ điều gì nhất thiết phải là duy nhất cho bất kỳ hệ điều hành Unix hoặc chương trình nào cả. Nó không phải là về file descriptors, pipes, sockets, hoặc signals. Những lời phàn nàn đó thì giống như việc nói rằng một người nào đó không phải là một phật tử, trừ khi họ nói chuyện bằng tiếng Pali (một thứ tiếng địa phương tại Ấn Độ, cái nôi của Phật giáo).

Triết lý Unix là một triển vọng trong phát triển phần mềm, không phải bất kỳ sự phát triển kỹ thuật cụ thể nào trong phần mềm cả. Đó là một điểm lý tưởng cần vươn tới, và có lẽ mỉa mai thay, đó là một lý tưởng chỉ thị cho chúng ta thỉnh thoảng phải tránh chủ nghĩa duy tâm và ủng hộ thực tiễn.

Trong Node, các khối xây dựng cơ bản mà mọi người chia sẻ và tương tác với nhau không phải là một số nhị phân trên dòng lệnh, mà là một module được nạp bằng phương thức require(). Các giao diện phổ quát một dòng văn bản (text stream), nhưng đó là một đối tượng JavaScript Stream, chứ không phải là một stdio pipe. (Các stdio pipe tất nhiên là đại diện bởi các JavaScript stream, bởi vì đó là giao diện phổ quát của chúng ta, liệu chúng ta sẽ sử dụng cái gì khác?)

Vì vậy, sau đây là cách tôi diễn đạt Triết lý Unix theo các khái niệm của Node.js. Than ôi, tôi không phải là McIlroy, và tôi thiếu thời gian hoặc kỹ năng để viết cho triết lý này ngắn hơn.

  • Viết các module làm một việc thật tốt. Viết một module mới chứ không nên làm phức tạp một module cũ.
  • Viết các module khuyến khích các thành phần hơn là mở rộng.
  • Viết các module xử lý Streams dữ liệu, bởi vì đó là giao diện phổ quát.
  • Viết các module mà không biết về các nguồn đầu vào hoặc đích đầu ra của chúng.
  • Viết các module để giải quyết một vấn đề bạn biết, vì vậy bạn có thể tìm hiểu về những thứ bạn chưa biết.
  • Viết các module có kích thước nhỏ. Lặp lại một cách nhanh chóng. Cấu trúc lại một cách không thương tiếc. Viết lại nó một cách dũng cảm.
  • Viết các module một cách nhanh chóng, để đáp ứng nhu cầu của bạn, chỉ với một vài kiểm thử cho phù hợp. Tránh các thông số kỹ thuật rộng rãi. Bổ sung thêm một kiểm thử cho mỗi bug mà bạn fix.
  • Viết các module ở dạng để xuất bản, thậm chí nếu bạn chỉ sử dụng chúng với mục đích riêng tư. Trong tương lai, bạn sẽ đánh giá cao những tài liệu mà mình đã viết cho nó.
  • Làm việc được thì tốt hơn là hoàn hảo.
  • Tập trung thì tốt hơn so với nhiều tính năng.
  • Khả năng tương thích thì tốt hơn so với sự thuần khiết.
  • Đơn giản thì tốt hơn so với bất cứ điều gì.

Triết lý Unix là một hệ tư tưởng của chủ nghĩa thực dụng. Nó cần cân bằng giữa 2 điểm là nhu cầu của việc viết ra phần mềm tốt, và viết ra bất kỳ phần mềm kiểu gì. Đó là một tập lời khuyên thực tiễn trong việc đánh đổi giữa sự gia tăng vừa phải trong chi phí phát triển và cần phải giảm nhiều hơn trong chi phí bảo trì.

Trong thế giới thực, chúng ta phải đối mặt với những khó khăn hoàn toàn không công bằng của con người trong khi viết chương trình và gỡ lỗi cho chúng, và không có chi phí nào trong số này có thể giảm xuống được bằng 0. Hệ tư tưởng này là theo ngữ cảnh, và có thể được áp dụng ở tất cả các cấp độ của quá trình phát triển phần mềm. Nó là một sự thừa nhận khách quan rằng chúng ta đang thực sự không đủ thông minh để biết làm thế nào viết ra phần mềm mà chúng ta cần trong lần thử đầu tiên, bởi vì chúng ta thường chỉ có thể hiểu đầy đủ các vấn đề của mình một khi chúng ta đã hoàn thành việc giải quyết chúng.

Không cái nào trong số các quy tắc này là bất khả xâm phạm cả! Trong thực tế, trong nhiều trường hợp, chúng có thể trở nên mâu thuẫn, hoặc thậm chí hoàn toàn trái ngược nhau. Tuy nhiên, nếu chúng ta giữ cho các đơn vị trong lập trình (units of programming) của mình đủ nhỏ, với giao diện đơn giản và phổ quát, chúng ta có thể lợi dụng cấu trúc từng phần này như một cơ cấu có chất lượng, bỏ đi những phần không tốt trong quá trình phát triển của mình.

Không có gì về Triết lý Unix liên quan rõ ràng đến văn hoá chia sẻ phần mềm cả. Tuy nhiên, nó đừng trở nên huyền bí ở các cộng đồng phát triển phần mềm nơi mà chúng ta tranh cãi dai dẳng về cách tốt nhất để làm cho các chương trình của mình Miễn Phí đúng cách. Phần mềm đó nên được phát triển theo những nguyên tắc là dễ dàng hơn để chia sẻ, tái sử dụng, tái cấu trúc, và duy trì.

Techtalk via Techmaster

0