----> Lời khuyên cho các bạn bắt đầu học lập trình: nếu có tham khảo code trên mạng thì các bạn nên xem nó và tự viết lại rồi tìm hiểu xem từng phần trong code ý nó có mục đích là gì chứ đừng nên copy và paste một cách máy móc mà mình chả hiểu được code ý nó viết gì.
Tất cả các ngôn ngữ lập trình đều sinh ra để hỗ trợ một hoặc một số phong cách lập trình hay một mô hình lập trình nào đó (programming paradigm). Vì vậy trước khi bắt tay vào học ngôn ngữ ta nên tìm hiểu sơ lược về mô hình lập trình được ngôn ngữ hỗ trợ mà ta dự định viết chương trình theo mô hình đó. Cụ thể, nói “lập trình hướng đối tượng với C++” thì ta phải biết sơ sơ về hướng đối tượng trước khi “ngâm cứu” C++. Vì vậy bài đầu tiên này mình muốn dành để nói về lập trình hướng đối tượng là gì, và quan điểm của giới lập trình về nó như thế nào, tại sao nó lại là một mô hình tiên tiến và bạn sẽ không phải hối hận khi bỏ thời gian và công sức ra để học nó.
Ngày xửa ngày xưa, khoảng ba chục năm về trước, quy mô các của các dự án phần mềm còn nhỏ, các lập trình viên gần như có thể viết ngay được chương trình mà không cần suy nghĩ nhiều (giả sử rằng không có lập trình viên nào bị thiểu năng về trí tuệ ). Thời đó lập trình cấu trúc (structured programming) hay còn gọi lập trình thủ tục (procedural programing) là kỹ thuật lập trình chủ yếu. Tớ sẽ nói sơ qua một chút về kỹ thuật này (trong phạm vi hiểu biết). Theo quan điểm của lập trình cấu trúc, người ta xem chương trình là một “công việc lớn” cần phải xử lý. Để giải quyết “công việc lớn” này, người ta tìm cách chia thành các phần công việc nhỏ hơn và mỗi phần này sẽ được quẳng cho một hàm đảm nhiệm. Chương trình chính sẽ gọi đến mỗi hàm vào những thời điểm cần thiết. Trong mỗi hàm, nếu như phần công việc vẫn còn lớn, thì ta lại chia nhỏ tiếp cho tới khi vấn đề trở nên đủ đơn giản. Và dĩ nhiên để giải quyết những phần con đó ta cũng phải quẳng chúng cho các hàm tương ứng. Quá trình này được gọi là “làm mịn” hay “tinh chế từng bước” (stepwise refinement). Việc trao đổi dữ liệu giữa các hàm được thực hiện thông qua việc truyền đối số hoặc các biến, mảng toàn cục. Như vậy có thể coi chương trình là một tập hợp các hàm được thiết kế để xử lý các phần công việc được giao. Các ngôn ngữ lập trình hướng thủ tục thường gặp là C, Pascal, FORTRAN … và cả C++. Tuy nhiên C++ còn được thiết kế để hỗ trợ cả lập trình hướng đối tượng nữa. Một chương trình viết theo hướng cấu trúc sẽ tập trung vào quá trình xử lý. Nghĩa là mỗi câu lệnh chỉ dẫn cho máy tính làm một việc gì đó, kiểu như: nhận 2 số nguyên từ bàn phím, cộng chúng lại với nhau, rồi đem chia đôi, hiển thị kết quả lên màn hình. Một chương trình là một tập các chỉ dẫn. Lập trình cấu trúc tỏ ra khá hiệu quả khi quy mô chương trình còn nhỏ, nhưng khi quy mô chương trình lớn dần lên và phức tạp hơn thì nó bộc lộ nhiều khiếm khuyết. Có thể nêu ra một số vấn đề sau:
Nói chung mình chỉ mới bới ra được có thế thôi, ai biết thêm cái nào thì bổ sung nhé. Rõ ràng với nhiều hạn chế như vậy thì lập trình cấu trúc không phải là giải phải pháp tốt. Và những nỗ lực để vá những lỗ hổng này dẫn đến sự ra đời của một kỹ thuật lập trình mới lập trình hướng đối tượng (object oriented programming – OOP). Mình cũng nói sơ qua một chút về OOP. Khác với lập trình cấu trúc, OOP coi chương trình là tập hợp của các đối tượng có quan hệ nào đó với nhau. Mỗi đối tượng có dữ liệu và phương thức của riêng mình. Ví dụ một đối tượng Human sẽ có các dữ liệu như: tên, ngày sinh, tuổi, số chứng minh nhân dân, nghề nghiệp, … blah blah … và được đóng gói cùng các phương thức đi kèm ví dụ phương thức set_name() sẽ cho phép nhập tên , get_name() sẽ cho phép lấy tên của đối tượng, tương tự ta cũng cho các phương thức như set_ID(), get_ID() cho chứng minh nhân dân … Các đối tượng sử dụng những phương thức này để giao tiếp với bên ngoài. Việc này trước giúp dữ liệu được quan tâm đúng mức, và an toàn hơn. Mọi truy cập đến dữ liệu đều được kiểm soát thông qua các phương thức được cung cấp sẵn nên hạn chế được những truy cập bất hợp pháp. Tức là đã giải quyết được ba hạn chế đầu tiên của lập trình cấu trúc. Thứ hai, những thay đổi nào đó về dữ liệu chỉ ảnh hưởng đến một số lượng hàm nhất định và thay vì phải viết lại hầu hết các hàm thì ta chỉ phải viết lại một số hàm có liên quan trực tiếp đến sự thay đổi đó. Ví dụ thành phần dữ liệu name biểu thị tên của một đối tượng Human vì một lý do nào đó được đổi thành full_name thì những hàm liên quan trực tiếp đến name như set_name() hay get_name() mới phải viết lại, còn những hàm như set_ID(), get_ID() hay thậm chí những hàm gọi hàm set_name() và get_name() thì chẳng việc gì cả. Điều này thuận lợi cho việc nâng cấp và bảo trì. Tức là hạn chế thứ tư đã được giải quyết. OOP cũng cung cấp những khái niệm về kế thừa và đa hình giúp tận dụng tối đa khả năng sử dụng lại mã nguồn để giảm bớt vất vả cho lập trình viên cũng như tăng chất lượng phần mềm. Ví dụ chúng ta có thể tạo ra một lớp (class) mới là Girl, kế thừa từ lớp Human. Khi đó, một đối tượng thuộc lớp Girl sẽ có đầy đủ các thuộc tính và phương thức của Human, và ta chỉ cần bổ sung thêm những phần khác như số đo ba vòng: round_1, round_2, round_3 … Vì thể không phải viết lại toàn bộ code cho lớp Girl. Cụ thể như thế nào thì mình sẽ đề cập trong những bài post sau. Đây chỉ là bài mở đầu để giúp mọi người so sánh giữa kỹ thuật OOP với kỹ thuật lập trình cấu trúc truyền thống và có những hình dung cơ bản về OOP, những ưu điểm mà nó mang lại, và vì sao nó lại là một kỹ thuật được ưa chuộng nhất hiện nay. Trong những năm gần đây, lập trình đã dịch chuyển từ hướng cấu trúc sang hướng đối tượng vì những ưu điểm và khả năng mạnh mẽ của nó. Thực tế hiện nay OOP được sử dụng rộng rãi trong các dự án phần mềm, còn lập trình cấu trúc chỉ chiếm một phần rất nhỏ thường là giải quyết những vấn đề có quy mô nhỏ hoặc dùng trong giảng dạy để giúp người học bước đầu làm quen với lập trình. Đấy là mình cũng chỉ nghe thiên hạ nói thế thôi chứ cũng mới học OOP nên cũng không biết là thực tế doanh nghiệp bây giờ nó viết phần mềm bằng ngôn ngữ gì cả. Nhưng có điều mình cảm nhận được đúng là OOP lập trình sướng hơn hơn lập trình cấu trúc nhiều, ít ra là cái khoản thiết kế nó trực quan hơn, rõ ràng hơn, thật hơn. Còn nếu để ý kỹ thì những cài đặt chi tiết trong hướng đối tượng suy cho cùng vẫn là lập trình cấu trúc, có điều chúng được tổ chức tốt hơn và được phủ lên một giao diện mang tính hướng đối tượng mà thôi.