Paradigm và ngôn ngữ lập trình

Trước đây, đa phần lập trình viên bình thường chủ yếu làm việc với lập trình hướng đối tượng, thì sự khác biệt giữa paradigm và ngôn ngữ lập trình không thật quan trọng. Tuy nhiên, khi mà lập trình hàm (functional programming) đang ngày một thu hút nhiều sự chú ý, thì việc hiểu rõ sự khác biệt này là khá cần thiết.

Trước hết, bạn thử suy nghĩ, tại sao Java không giống C#, mà người ta lại dạy bạn là hai ngôn ngữ này đều là lập trình hướng đối tượng? Nếu bạn gặp thêm một ngôn ngữ X nào đó, làm sao bạn biết nó có hướng đối tượng? Hay nếu bạn vô tình đọc phải một cuốn như Object Oriented Programming With ANSI-C, bạn có dám nói C là một ngôn ngữ lập trình hướng đối tượng không?

Để trả lời những câu hỏi này, bạn phải hiểu lập trình hướng đối tượng là một paradigm. Paradigm định nghĩa các khái niệm mà chúng ta sẽ dùng để suy nghĩ về một vấn đề nào đó. Một số ngôn ngữ nào đó có thể cung cấp các tính năng cho phép chúng ta ứng dụng paradigm đó để hiện thực một cách dễ dàng, nhưng paradigm không bao giờ quy định cụ thể tính năng đó là gì, cú pháp ra sao, v.v. Chẳng hạn, paradigm cho lập trình hướng đối tượng nêu lên khái niệm encapsulation. Java dùng các modifier như public, private. Những người phát triển C# cho rằng property giúp tăng cường tính encapsulation, và họ đưa property vào những ngôn ngữ này. Những người phát triển Python lại lập luận rằng encapsulation không phải nhiệm vụ của trình dịch, nên trong Python không có cơ chế tạo private method, người ta ngầm quy ước method bắt đầu với “__” là private. Và cả Java, C#, Python đều được người phát triển chúng tuyên bố là có hỗ trợ lập trình hướng đối tượng. Nếu bạn hiểu encapsulation, bạn sẽ việc được code thỏa mãn tương đối tính chất này ở cả ba ngôn ngữ, nhưng nếu bạn chỉ học ngôn ngữ thôi, có thể code của bạn sẽ không có tính encapsulation. Hiểu một paradigm không chỉ giúp bạn khi sử dụng một ngôn ngữ được cho là hỗ trợ nó, mà bạn có thể áp dụng những khái niệm hay từ nó cho các ngôn ngữ khác, để làm cho code của bạn có chất lượng cao hơn (bạn thử nghĩ làm thể nào để tăng encapsulation trong C).

Cần chú ý là trong khi một ngôn ngữ có thể tốt hơn một ngôn ngữ khác, như C# 3.0 so với C# 2.0 (mặc dù so sánh này chỉ là tương đối), bạn không thể so sánh paradigm này có tốt hơn paradigm khác không. Mỗi paradigm đều thích hợp trong một số tình huống, và không thích hợp trong những tình huống khác. Ví dụ, paradigm lập trình hàm cổ vũ cho việc sử dụng immutable object, nhưng không phải mọi bài toán đều giải quyết được chỉ dùng immutable object. Hiểu rõ các paradigm sẽ giúp bạn không áp dụng chúng một cách cứng nhắc, nhờ đó lời giải của bạn cho các vấn đề sẽ trở nên uyển chuyển, hiệu quả hơn (ví dụ này có vẻ hợp). Cũng bởi vì không có paradigm nào là tốt nhất, các ngôn ngữ lập trình hiện đại thường đều ở dạng multiparadigm, trong đó có thể có một paradigm là chủ đạo. Muốn tận dụng tốt nhất các tính năng mà những ngôn ngữ này cung cấp, bạn phải hiểu thế mạnh của các paradigm và nhìn ra những tình huống ứng dụng chúng.

Cuối cùng, cũng như nhiều khái niệm khác như khoa học máy tính và kĩ thuật máy tính, strong typing và weak typing, các paradigm nói chung cũng được định nghĩa một cách tương đối hoặc trừu tượng. Cho nên có thể đôi khi bạn sẽ băn khoăn liệu paradigm này có phải là hệ quả hay là một cách phát biểu khác của paradigm kia, v.v. Trong trường hợp này có lẽ tốt nhất là khỏi phải suy nghĩ nhiều làm gì cho mệt :D, thế giới định nghĩa sao ta chấp nhận thế. Điều quan trọng khi tìm hiểu một paradigm là phải ghi nhớ những khái niệm quan trọng nhất mà nó cổ vũ, và nếu có thể thì học một ngôn ngữ được cho là đại diện cho nó. Như thế, khi đã thành thạo, cho dù bạn không thể định nghĩa paradigm này, bạn vẫn có thể rút ra được những phương pháp và kinh nghiệm hay cho việc lập trình. Có thể xem như paradigm tác động tới thiết kế của các ngôn ngữ, và ngược lại các ngôn ngữ góp phần định nghĩa nên paradigm.

Advertisements

Scheme

Scheme là ngôn ngữ lập trình từng được MIT sử dụng để dạy cho sinh viên (hình như giờ đã thay bằng Python). Mình biết đến Scheme qua một bài viết trên blog Khoa học máy tính. Mặc dù mình chỉ lọ mọ tìm hiểu sơ sơ về nó (chính xác hơn là về Scheme và IDE của MIT), nhưng cũng kịp có vài ấn tượng.

Thứ nhất, Scheme có tương đối ít khái niệm hơn các ngôn ngữ phổ biến, như C#, C++, Java, v.v. Điều này giúp bạn tập trung vào những yếu tố quan trọng khác trong lập trình, thay vì tiêu tốn thời gian và công sức vào những chi tiết cú pháp vụn vặt.

Thứ hai, chương trình dùng Scheme viết ra nhìn rất ngắn gọn và đẹp (nói chung các ngôn ngữ lập trình hàm đều thế). Ví dụ:

(define (even-fibs n) 
(accumulate +  
            0  
            (filter even?   
                    (map fib    
                         (enumerate-interval 0 n)))))

Đoạn mã trên là một phần của chương trình tính tổng các số chẵn trong (n+1) số Fibonacci đầu tiên. Bạn có thể thấy từng bước tính toán nếu đọc ngược từ dưới lên:

  • Liệt kê (enumerate) các số từ 0 đến n,
  • Ánh xạ (map) dãy trên sang dãy Fibonacci. Nôm na là tạo danh sách các số Fibonacci từ thứ 0 đến thứ n,
  • Lọc (filter) các số chẵn trong danh sách,
  • Tính tổng (accumulate) các số vừa được lọc.

Thứ ba, ngay cả một chương trình Scheme cỡ trung bình cũng khá khó viết. Nếu chưa có một phác thảo tương đối rõ ràng về chương trình của mình, thì thậm chí cái bạn viết ra có thể không chạy được chứ chưa nói đến chạy đúng hay sai, nhất là khi dùng IDE của MIT. Có lẽ chính sự quá dễ dàng trong việc viết ra một chương trình “chạy được” bằng các ngôn ngữ như C, C++ (cái này BK chọn để dạy trong môn Kĩ thuật lập trình), Java, C# khiến cho chúng ta nhiễm thói quen “mì ăn liền”, đọc yêu cầu xong là nhảy vào lập trình liền, và kết quả là chương trình rất rối rắm và dễ mắc lỗi.

Nếu quan tâm tới Scheme, bạn có thể tham khảo thêm ở trang web của môn nàyMIT OCW. Quyển sách giáo khoa chính—Structure and Interpretation of Computer Programs—là một trong những quyển sách về máy tính hay nhất mà mình từng đọc. Bạn có thể tìm thấy ở đó không chỉ những hướng dẫn về lập trình Scheme mà còn rất nhiều lí thuyết thú vị, như thiết kế chương trình, tính trừu tượng, tính nondeterministic, v.v. Đọc nó, và bạn sẽ không bao giờ còn băn khoăn liệu mình có chọn sai ngành.