1 kiểu dữ liệu trừu tượng là gì năm 2024
Lập trình hướng đối tượng (tiếng Anh: Object-oriented programming, viết tắt: OOP) là một mẫu hình lập trình dựa trên khái niệm "công nghệ đối tượng", mà trong đó, đối tượng chứa đựng các dữ liệu, trên các trường, thường được gọi là các thuộc tính; và mã nguồn, được tổ chức thành các phương thức. Phương thức giúp cho đối tượng có thể truy xuất và hiệu chỉnh các trường dữ liệu của đối tượng khác, mà đối tượng hiện tại có tương tác (đối tượng được hỗ trợ các phương thức "this" hoặc "self"). Trong lập trình hướng đối tượng, chương trình máy tính được thiết kế bằng cách tách nó ra khỏi phạm vi các đối tượng tương tác với nhau.[1][2] Ngôn ngữ lập trình hướng đối tượng khá đa dạng, phần lớn là các ngôn ngữ lập trình theo lớp, nghĩa là các đối tượng trong các ngôn ngữ này được xem như thực thể của một lớp, được dùng để định nghĩa một kiểu dữ liệu. (theo wiki) Show Bốn tính chất của OOPLập trình hướng đối tượng là một phương pháp lập trình có 4 tính chất chính sau:
Tính trừu tượng còn thể hiện qua việc một đối tượng ban đầu có thể có một số đặc điểm chung cho nhiều đối tượng khác như là sự mở rộng của nó nhưng bản thân đối tượng ban đầu này có thể không có các biện pháp thi hành. Tính trừu tượng này thường được xác định trong khái niệm gọi là lớp trừu tượng hay lớp cơ sở trừu tượng.
Ví dụ khi định nghĩa hai đối tượng "hinh_vuong" và "hinh_tron" thì có một phương thức chung là "chu_vi". Khi gọi phương thức này thì nếu đối tượng là "hinh_vuong" nó sẽ tính theo công thức khác với khi đối tượng là "hinh_tron".
Tính trừu tượng và tư duy trong lập trình OOPThầy giáo dạy công nghệ phần mềm trước đây của tôi đã từng nói một câu đại loại rằng: Khả năng yếu nhất của lập trình viên Việt Nam là tính trừu tượng hoá. Thời điểm đó tôi không thực sự tán thành, nhưng trớ trêu thay càng ngày tôi càng mất đi những lý lẽ đủ thuyết phục để phản biện lại nhận xét này. Tôi đã từng làm việc ở khá nhiều công ty về công nghệ, từ những tập đoàn lớn cho tới những startup chỉ khoảng vài ba người, từ outsourcing cho tới những công ty làm về product, ERP hay dịch vụ tài chính. Ở đâu tôi cũng tình cờ gặp những đoạn code kiểu dạng như sau: Một ngày nọ chúng tôi được yêu cầu triển khai chức năng cho phép gửi email cho khách hàng khi phát sinh biến động về tài chính trong tài khoản cá nhân. Ai đó ngay lập tức tạo class
Một thời gian sau, chúng tôi được yêu cầu tiếp tục triển khai thêm chức năng gửi SMS vào luồng xử lý hiện tại. Một vài người đề xuất tạo thêm phương thức
Mọi chuyện có vẻ vẫn ổn, cho đến khi chúng tôi tiếp tục được đề nghị triển khai chức năng gửi notification vào trang cá nhân của khách hàng. Một vài người vẫn cố chấp tin tưởng rằng nên tiếp tục tạo thêm class với tên gọi Notification, một vài người khác bắt đầu lờ mờ nhận ra rằng họ đã sai ngay từ những thiết kế ban đầu, nhưng bởi đã có quá nhiều Bất cứ lập trình viên nào hiểu biết về OOP đều có thể nhận thức được rằng, tất cả những gì nên được tạo ra là class Sai lầm phổ biến trong design hệ thống là người ta quá tin tưởng và những gì mình biết và khẳng định sẽ không có sự thay đổi. Nhưng không! chúng ta không hiểu rõ như chúng ta tưởng. Tôi đã từng đọc được một câu nói (nào đó), của một người nổi tiếng (nào đó không nhớ tên), đại loại là: Sau một thời gian triển khai, chúng tôi nhận ra rằng thứ mình tạo ra hoàn toàn khác so với những tưởng tượng ban đầu về chúng. Nếu không thể biết trước những gì sẽ thay đổi, hãy trừu tượng hoá nó nhiều nhất có thể. Abstraction luôn là một trong những yếu tố quan trọng nhất của OOP, nhưng không nhiều người thực sự nhận thức được điều này. Nhưng ngay cả khi chúng ta hiểu được điều đó, liệu đã là đủ? Tôi đã từng thấy một lập trình viên "có kinh nghiệm" triển khai class Sender với những phương thức sau:
Rõ ràng rằng email, phoneNumber hay content nên là những thuộc tính của object và chỉ được phép tương tác thông qua method get(), set() hay contructor(). Vấn đề ngay lập tức phát sinh khi tôi muốn lưu trữ lại email và phoneNumber vào một temp table nào đó. Một vài người sẽ vã thẳng đoạn code lưu trữ này vào từng method (f***), một vài người khác tạo một method mới kiểu dạng như: `sendEmail()`3 Nhưng rõ ràng cách làm này ẩn chứa nhiều nguy cơ conflict dữ liệu không đáng có. Chúng ta vẫn thường ra rả nói về OOP, trong khi lại thường xuyên vi phạm nghiêm trọng tính encapsulation của đối tượng. Lượm lặt đâu đó, bạn có thể gặp một vài người sử dụng strategy pattern, bản thân tôi thì thích observer pattern hơn. Tư duy trong lập trình là thứ có thể dễ dàng thay đổi, nhưng nghiệt ngã ở chỗ, thuyết phục được một người thay đổi tư duy lại khó khăn hơn gấp bội. Tôi đã nhiều lần gặp những lập trình viên phủ định ngay những ý tưởng mới, ngay cả khi họ chưa hiểu rõ ý tưởng đó là gì. Tiếc thay, những lời biện hộ lại có vẻ rất thuyết phục như "tôi cho rằng thiết kế này là phù hợp với chức năng hiện có" hay "các hệ thống đang có đều thiết kế như vậy". Chúng ta thường vận dụng những tư duy cũ cho một hệ thống mới và hy vọng vào một sự chuyển biến mang chiều hướng tích cực. Nhưng sự thuyết phục để thay đổi là vô cùng khó khăn khi mà ngay cả loose coupling hay high cohesion vẫn còn là những ý niệm hết sức mơ hồ. Insanity is doing the same thing over and over again, but expecting different results. (lần này thì nhớ tên: Albert Einstein) |