Sự phát triển của các ngôn ngữ lập trình

Bài viết được sự cho phép của tác giả Edward Thien Hoang

Ngôn ngữ lập trình bản thân chúng không phải là 1 thành phần trong kiến trúc nhưng sẽ là thiếu sót nếu chúng ta không đề cập đến chúng trong loạt bài viết này.

Cùng điểm sơ qua lịch sử phát triển của các ngôn ngữ lập trình cùng các mô hình lập trình (programming paradigm) qua thời gian và các vấn đề mà chúng giải quyết.

  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java
  10 ngôn ngữ phát triển nhanh nhất theo GitHub thống kê năm 2024

1950S – NON-STRUCTURED PROGRAMMING (LẬP TRÌNH PHI CẤU TRÚC)

Assembly ~1951
Vào thời điểm sơ khai của lĩnh vực phát triển phần mềm, Assembly là ngôn ngữ hot nhất thời điểm bấy giờ. Nó sử dụng các lời gọi hàm bậc thấp như add, sub, goto và thao tác trực tiếp trên thanh nhớ. Mất khá nhiều thời gian chỉ để build 1 ứng dụng đơn giản. Để thực hiện một lệnh IF, ta cần đến vài dòng code, và sẽ là vài chục dòng code cho vòng loop… Lúc này, khả năng tái sử dụng và cấu trúc các thành phần hầu như là rất khó vì độ phức tạp của ngôn ngữ, các dòng lệnh chủ yếu được thực thi một cách tuần tự, nếu muốn sử dụng logic này ở chỗ khác thì chỉ có cách copy-paste.

1960S – STRUCTURED PROGRAMMING (LẬP TRÌNH CẤU TRÚC)

Algol ~1958
Lập trình cấu trúc là bước tiến hóa tiếp theo sau đó. Nó mang đến khả năng cấu trúc các dòng lệnh theo block, cung cấp các giao diện (key word) để sử dụng các lệnh if, else, loop, case, … và các sub-routines (giống như global method để reuse). Từ đây chúng ta có thể tập trung vào việc lập trình các flow của chương trình (thay vì phải đau đầu với các “mật mã” assembly). Ý tưởng về re-useable code cũng khởi nguồn ở giai đoạn này.

1970S – PROCEDURAL & FUNCTIONAL PROGRAMMING (LẬP TRÌNH THỦ TỤC & CHỨC NĂNG)

Pascal ~1970, C ~1972
Lập trình thủ tục và lập trình chức năng được giới thiệu vào những năm đầu của thập niên 70, với các đặc điểm như:
Procedures: Tập các dòng lệnh để thực hiện một công việc gì đó và không trả về dữ liệu
Functions: Tập các dòng lệnh dùng để tính toán trả về dữ liệu
Data structures: dùng để diễn đạt thông tin của một sự vật, sự việc, hoặc để nhóm các thông tin có cùng một mục đích vào trong đó. (Lưu ý lúc này vẫn chưa có OOP nên mình tránh dùng từ đối tượng ở đây)
Modules: Các file code hoặc tập tin đã được biên dịch có thể dùng cho những chỗ khác.

Trong giai đoạn này, ý tưởng về Event Oriented Programming cũng đã xuất hiện trong một báo cáo về MVC (sử dụng các event) của Trygve Reenskaug.

Như vậy, trong giai đoạn này, các ngôn ngữ lập trình đã làm tăng tính tái sử dụng các module, cũng như cho phép tạo ra các cấu trúc để gom nhóm data cũng như việc sử dụng event để phân tách các thành phần với nhau. (Key work cần nhớ: decoupling and modularity)

1980S – OBJECT ORIENTED PROGRAMMING

C++ ~1980, Erlang ~1986, Perl ~1987,
Phyton ~1991, Ruby ~1993, Delphi, Java, Javascript, PHP ~1995
Một trong những mô hình lập trình linh hoạt và theo tôi là tốt nhất cho đến thời điểm hiện tại đó là OOP. Lập trình hướng đối tượng cho phép chúng ta phân tích các bài toán thành các thực thể được gọi là các đối tượng và xây dựng các dữ liệu, các hàm xung quanh các đối tượng này. Dữ liệu được liên kết với các hàm thành các vùng riêng mà chỉ có các hàm đó tác động lên, các hàm bên ngoài không được truy cập vào. Các đối tượng có thể tác động và trao đổi thông tin với nhau thông qua các thông điệp.

MỘT SỐ KHÁI NIỆM TRONG LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG

ĐỐI TƯỢNG

Đối tượng là sự kết hợp giữa dữ liệu và thủ tục (còn gọi là phương thức) thao tác trên dữ liệu đó. Ta có công thức:
Đối tượng = Dữ liệu + Phương thức

LỚP

Lớp là một tập các đối tượng cùng loại (có cấu trúc dữ liệu và phương thức giống nhau). Một đối tượng sẽ thể hiện cụ thể từng lớp. Trong lập trình mỗi lớp được xem là một kiểu, còn các đối tượng sẽ là các biến có kiểu lớp khác.

ĐÓNG GÓI DỮ LIỆU

Trong lập trình cấu trúc các hàm được sử dụng mà không cần biết cụ thể nội dung. Người dùng chỉ cần biết chức năng của hàm cũng như các tham số để chạy hàm, không cần quan tâm đến những lệnh cụ thể bên trong. Người ta gọi chức năng đó là đóng gói dữ liệu.

Trong lập trình hướng đối tượng, cả chức năng và dữ liệu đều phải được đóng gói, mỗi đối tượng sẽ không thể truy cập trực tiếp vào các thành phần dữ liệu mà phải thông qua các thành phần chức năng để làm việc đó. Như vậy, đóng gói cho phép dữ liệu của đối tượng sẽ bị che đi một phần khi nhìn từ bên ngoài.

KẾ THỪA

Kế thừa là khả năng cho phép xây dựng một lớp mới dựa trên các cơ sở (định nghĩa) của một lớp có sẵn và có bổ sung phương thức hay thành phần dữ liệu. Khả năng sử dụng kế thừa các module chương trình rất dễ dàng mà không cần thay đổi module khác.

ĐA HÌNH

Tính đa hình sẽ xuất hiện khi có khái niệm kế thừa và có khả năng cho phép gửi cùng một thông điệp đến những đối tượng khác nhau mà không cần biết đối tượng nhận thuộc lớp dữ liệu nào, chỉ cần tập hợp các đối tượng nhận có chung hoặc gắn liền với một tính chất nào đó.

1990S – SUBJECT & ASPECT ORIENTED PROGRAMMING

Subject Oriented Programming gọi cho các biểu diễn khác nhau của các đối tượng, theo người đang “nhìn” vào nó. Ví dụ, trong khi con người có thể nhìn thấy gỗ khi nhìn vào cái cây, một con chim có thể thấy một lượng thức ăn và nơi trú ẩn. Để mô hình hóa việc đó trong lập trình, nó có nghĩa là thuộc tính và hành vi của đối tượng có thể khác nhau, tuỳ thuộc vào ai gửi thông điệp đến đối tượng.

Aspect Oriented Programming (AOP) – lập trình hướng khía cạnh: là một kỹ thuật lập trình (kiểu như lập trình hướng đối tượng) nhằm phân tách chương trình thành cách moudule riêng rẽ, phân biệt, không phụ thuộc nhau.
Khi hoạt động, chương trình sẽ kết hợp các module lại để thực hiện các chức năng nhưng khi sửa đổi 1 chức năng thì chỉ cần sửa 1 module.
AOP không phải dùng để thay thế OOP mà để bổ sung cho OOP.

SAU OOP

Sau OOP thì hầu như không có mô hình lập trình mới nào đáng chú ý. Tất cả đổ dồn vào việc tùy biến các ngôn ngữ lập trình hiện tại để tối ưu cho các mục đích cụ thể nhất định, các framework, ngôn ngữ dành riêng cho phát triển web, mobile hoặc 1 nền tảng nào đó như Go cho Google, Hack của Facebook, …

KẾT LUẬN

Chúng ta đã điểm qua sơ bộ về một số mô hình lập trình chính, tất nhiên là tôi không quá chú trọng về nội dung chi tiết, vì chúng đã được nhắc đến rất nhiều trên mạng internet. Phần tôi muốn nhấn mạnh ở đây chính là chiều hướng phát triển của các mô hình lập trình, chúng tiến hóa theo chiều hướng của Modularity (low coupling – liên kết lỏng lẽo) và Encapsulation (high cohesion – độ gắn kết cao). Trong những bài viết tiếp theo, chúng ta sẽ tiếp tục thấy sự phát triển của các mô hình kiến trúc cũng theo chiều hướng nhằm đạt được tối đa 2 tính chất quan trọng NHẤT vừa đề cập.

Nếu bạn muốn hiểu rõ hơn về low coupling và high cohension, tôi khuyến nghị nên đọc thêm về nó ở đây trước khi bắt đầu vào loạt bài tiếp theo.

Đây là bài viết trong loạt bài viết về “Tổng quan về sự phát triển của kiến trúc phần mềm“. Đây là loạt bài viết chủ yếu giới thiệu về một số mô hình kiến trúc phần mềm hay nói đúng hơn là sự phát triển của chúng qua từng giai đoạn, qua đó giúp chúng ta có cái nhìn tổng quát, up-to-date và là roadmap để bắt đầu hành trình chinh phục (đào sâu) thế giới của những bản thiết kế với vai trò là những kỹ sư và kiến trúc sư phần mềm đam mê với nghề.

Bài viết được tham khảo từ:

Programming Language evolution

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com

Có thể bạn quan tâm:

Xem thêm các việc làm Developer hấp dẫn tại TopDev