TÍNH TRỪU TƯỢNG


Tính trừu tượng – mới nghe đã thấy mệt mỏi rồi 🥴.

Như trong những bài viết trước, ta đã thấy trừu tượng là khái niệm mà chúng ta luôn cố gắng hiện thực khi xây dựng phần mềm.

Nói một cách đơn giản, trừu tượng cho phép ta làm việc với các thành phần khác mà không cần quan tâm chúng được xây dựng như thế nào, không cần biết bên trong một lớp người ta viết gì và chúng ta không cần phải quan tâm đằng sau chúng có những thành phần nào để chạy.

Trong OOP, với bài toán quản lý sinh viên, ta tạo ra một lớp cha StudentStore, trong đó có 2 phương thức Find and Save, dùng để tìm và lưu trữ thông tin về các sinh viên.Trong phiên bản đầu tiên, Find và Save sẽ đọc và lưu lại thông tin vào các file trên đĩa. Nhưng đến khi bạn học sang phần Sql Server, bạn muốn lưu trữ vào cơ sở dữ liệu thay cho file, vì tất nhiên làm việc với dữ liệu trên file sẽ cực nhọc và kém hiệu quả hơn nhiều. Lúc đó bạn sẽ làm gì?

– Đổi tên lớp cũ StudentStore thành StudentFileStore.

– Tạo một lớp mới là StudentSqlStore để làm việc với cơ sở dữ liệu.- Tương ứng với lựa chọn khi setup, bạn sẽ new một đối tượng StudentFileStore hoặc StudentSqlStore.- Biên dịch và chạy lại chương trình.Mọi vấn đề có vẻ ổn, nhưng nếu bạn lại thêm vào lớp thứ 3, 4, 5, 6… bạn sẽ phải tiếp tục thêm vào, dịch lại… các khối if else bắt đầu phình to và dần khó kiểm soát. Nhưng thôi, nếu sức bạn “trâu” thì vẫn có thể gánh tiếp lớp 7,8,9…Bây giờ bạn bán phần mềm cho khách hàng, có ông kia lại nghĩ thêm ra cần lưu thông tin sinh viên vào MongoDB, ông nọ vào LDAP, lại thêm ông nữa dùng api của riêng ông ấy. Vấn đề bây giờ trở nên vô cùng phức tạp vì:

👉 Có quá nhiều bài toán phải giải quyết vì nhu cần mỗi khách hàng một khác, ngay cả dùng api thì mỗi api lại khác nhau, cấu trúc và mô hình triển khai cơ sở dữ liệu cũng khác.

👉 Có khách hàng muốn tự phát triển phần tương tác với dữ liệu, vì đây là bí mật thương mại riêng của họ.

👉 Mỗi lần thêm mới vào bạn lại phải dịch lại chương trình từ đầu, và phải phát hành lại. Hãy tưởng tượng mỗi lần Microsoft viết thêm driver cho một loại máy in, họ phải thêm code vào, dịch lại cả Windows rồi phát hành một phiên bản mới. Quy trình chắc chắn sẽ phức tạp hơn nhiều so với việc dịch lại chương trình quản lý sinh viên của bạn.Trừu tượng chỉ là một khái niệm, và có nhiều kỹ thuật để hiện thực khái niệm này trong OOP:

👉 Function/operator overloading: cho phép xây dựng các phương thức với những kiểu tham số khác nhau.

👉 Sử dụng thừa kế với các phương thức virtual (Xem lại bài đa hình).

👉 Sử dụng các interface: Với người lập trình Java và .NET. điều dễ nhận thấy là bạn không thể thừa kế từ nhiều lớp, nhưng có thể implement nhiều interface. Với người lập trình C++ thì ngược lại, bạn có đa thừa kế nhưng lại không có interface. Chính vì đa thừa kế quá phức tạp mà người ta đã loại bỏ nó, rồi thay thế vào đó là interface, vốn đơn giản và dễ hiểu hơn nhiều. Một interface chỉ là một bản khai báo những gì cần có, nó như một cam kết mà mỗi lớp hiện thực nó phải cung cấp, vì vậy chỉ cần biết một lớp nào đó implement một interface là bạn có thể dùng các hàm mà interface đó cung cấp, mà không cần nhìn thấy nội dung, hay các khía cạnh khác của lớp đó.Dùng đa thừa kế hoàn toàn có thể làm được những gì mà interface làm được, thông qua các abstract method, hoặc abstract class. Nhưng interface lại làm được một điều mà đa thừa kế không có, đó chính là sự đơn giản. Phần mềm càng lớn, càng phức tạp, bạn lại càng có nhu cầu đơn giản hóa các thành phần của nó, phức tạp có vẻ hay, nhưng chỉ hay với người nghe thôi, còn đối với người viết chương trình nó lại là thảm họa.

“Cái đống này thà đập đi làm lại từ đầu có khi còn nhanh hơn” – Tôi dám cá nếu bạn đã từng nhận phát triển hoặc duy trì một sự án có sẵn, chắc chắc bạn đã nghe hoặc thậm chí thốt ra câu này.Vậy trừu tượng mang lại những ưu điểm gì?

👉 Giảm mức độ phụ thuộc giữa các thành phần: Khi lớp C thừa kế từ A và B, bạn bắt buộc phải liên kết cả B vào chương trình ngay cả khi bạn chỉ dùng các phương thức được thừa kế từ A. Mức độ phụ thuộc lẫn nhau càng thấp, các lỗi sẽ càng ít có nguy cơ lan rộng, việc thay đổi cập nhật về sau càng dễ.

👉 Xây dựng các thành phần có thể test được: Testable tức là bạn có thể viết các chương trình/script/unit test để kiểm thử được một cách tự động. Bạn bắt buộc phải kiểm thử tự động vì:* Nếu test bằng tay sẽ rất khó tạo ra được các trường hợp (test case) đặc biệt, vốn ít xuất hiện trong thực tế.* Dễ dàng tạo lại (reproduce) lỗi. Nếu ngay cả người test cũng không biết làm sao để lỗi xuất hiện lại thì người sửa sẽ không biết đường nào mà fix.* Có thể kiểm thử tất cả các trường hợp nhanh chóng. Bạn cũng biết đôi khi thay đổi một chỗ này lại làm xuất hiện lỗi ở một chỗ khác, người lập trình sẽ thường chỉ kiểm tra chỗ họ đang làm, và chỉ kiểm tra những trường hợp biết chắc không bị lỗi 😃, nên việc kiểm thử lại toàn bộ, kể cả các thành phần không bị thay đổi là cần thiết.* Có thể áp dụng được DevOps: DevOps là quá trình tích hợp từ phát triển đến triển khai tự động, sẽ chẳng ai dám áp dụng tự động cài đặt một module vừa phát triển mà không thông qua các bài test kỹ lưỡng.

👉 Dễ dàng mở rộng: Như ở phía trên đã nói, bạn hoàn toàn có thể viết thêm module mới, triển khai thêm tính năng cho các phần mềm đã có một cách dễ dàng.

ℹ️ Để hiểu được tính trừu tượng là gì, sẽ dễ dàng hơn nếu bạn đặt câu hỏi “Tại sao ta cần nó?” hơn là “Nó là cái gì”, khi đã biết tại sao, ta sẽ thấy interface, overloading, overriding… chỉ là những công cụ.Thực chất OOP không hề khó hiểu, cũng không hề trừu tượng, chỉ là vì bạn chưa có đủ trải nghiệm, do vậy tôi luôn khuyên những bạn đang học lập trình là tìm một bài toán trong thực tế, và xây dựng một ứng dụng để giải quyết nó, từ đầu đến cuối, cả frontend, backend, thiết kế DB, cài đặt và triển khai… lúc đó bạn mới thấy được những vẫn đề mà bình thường không gặp. ❤️ Trồng một cánh rừng chắc chắn phải khác so với trồng một khu vườn ❤️

One thought on “TÍNH TRỪU TƯỢNG

  1. Nhưng e thấy đa phần người viết về Abstraction trong C# thường họ nói ntn “Abstraction is a process of identifying essential entities (classes) and their characteristics (class members) and leaving irrelevant information from the business requirement to prepare a higher-level application design.”

    A giải thích thêm cho e được ko.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s