5 nguyên tắc của SOLID(phần 1)
Nguồn gốc của nguyên lý SOLID là gì?
Lập trình hướng đối tượng còn được gọi là Object Oriented Programming (OOP). OOP là phương thức lập trình cho phép lập trình viên sử dụng các code để trừu tượng hóa một đối tượng bất kỳ. Quá trình này sẽ giúp tạo ra các đối tượng nhất định. Đây là một trong những phương thức lập trình được sử dụng phổ biến nhất hiện nay. Nó phù hợp với hầu hết các loại ngôn ngữ lập trình khác nhau.Hiệu năng của OOP được quyết định dựa trên 4 yếu tố khác nhau:
- Tính trừu tượng (abstraction): Bằng việc sử dụng các lớp trừu tượng, người dùng sẽ tạo nên mô hình của các đối tượng trong thế giới thực.
- Tính đóng gói (Encapsulation): Yếu tố này là để chỉ trường hợp các thực thể của lớp trừu tượng sở hữu những giá trị thuộc tính độc lập.
- Tính kế thừa (Inheritance): Yếu tố này cho phép các đối tượng được phép kế thừa và mở rộng lẫn nhau.
- Tính đa hình (Polymorphism): Tùy theo từng loại đối tượng khác nhau, ta có thể thực hiện một quy trình bằng nhiều cách riêng biệt.
Vậy là ta đã nắm được 4 yếu tố cần thiết để một lập trình OOP có thể phát huy hết tác dụng vốn có của nó. Vậy SOLID thì liên quan gì đến OOP? Nguyên tắc SOLID được hiểu như một cẩm nang hướng dẫn bạn sử dụng OOP thật hiệu quả. Tuân thủ theo các nguyên tắc SOLID giúp người dùng phối hợp được 4 tính năng của OOP với nhau thật nhuần nguyễn.
Khái niệm của nguyên lý SOLID
Nguyên lý SOLID nghĩa là gì? SOLID trong lập trình vốn là bộ 5 nguyên tắc được phát triển bởi 2 tác giả Bob Martin và Michael Feathers. Những hướng dẫn này sẽ giúp lập trình viên tạo ra được những đoạn code dễ đọc, dễ hiểu, dễ maintain. SOLID là viết tắt của 5 cụm từ sau:
- Single Responsibility Principle (SRP)
- Open/Closed Principle (OCP)
- Liskov Substitution Principle (LSP)
- Interface Segregation Principle (ISP)
- Dependency Inversion Principle (DIP)
Nguyên tắc trách nhiệm đơn lẻ (Single Responsibility Principle)
Một class chỉ nên thực hiện một công việc. Nói cho dễ hiểu thì một class chỉ nên thực hiện một công việc, thay vì thực hiện nhiều việc trong một class thì chúng ta có thể cho mỗi class thực hiện một công việc.
(Bad) Example
Better Example
Trong ví dụ thứ hai, class đã phân chia trách nhiệm soạn thảo văn bản và in văn bản giữa hai class. Bạn có thể nhận thấy rằng, nếu xảy ra lỗi, việc gỡ lỗi sẽ dễ dàng hơn, vì sẽ không quá khó để nhận ra lỗi ở đâu. Ngoài ra, có ít nguy cơ vô tình tạo ra lỗi phần mềm hơn vì bạn đang sửa đổi một phần mã nhỏ hơn. Mặc dù nó không đáng chú ý trong ví dụ này (vì nó nhỏ), loại phương pháp này cho phép bạn nhìn thấy “bức tranh lớn hơn” ; nó làm cho các chương trình dễ dàng nâng cấp và mở rộng hơn, mà không có các lớp quá rộng và mã trở nên khó hiểu.
Nguyên tắc đóng mở (The Open-Closed Principle)
Theo nguyên tắc này mỗi khi ta muốn thêm chức năng cho chương trình, chúng ta nên viết class mới mở rộng class cũ bằng cách kế thừa hoặc sở hữu class cũ chứ không nên sửa đổi class cũ. Việc này dẫn đến tình trạng phát sinh nhiều class, nhưng chúng ta sẽ không cần phải test lại các class cũ nữa, mà chỉ tập trung vào test các class mới, nơi chứa các chức năng mới.Nguyên tắc Đóng mở đại diện cho chữ “O” của năm nguyên tắc kỹ thuật phần mềm SOLID để viết mã được thiết kế tốt, dễ đọc hơn, dễ bảo trì hơn và dễ dàng nâng cấp và sửa đổi hơn.
(Bad) Example
Nguyên tắc thay thế Liskov
LSP có thể viết ngắn gọn như sau:Kiểu con phải có thể thay thế được cho kiểu cơ sở.Subtypes must be substituable for their base types.Nguyên tắc này trông có vẻ hơi khó hiểu một chút, thử diễn giải nó theo quan điểm cá nhân một cách đơn giản hơn xem sao. Nguyên lí này sẽ giúp chúng ta giữ được tính đúng đắn một việc: đảm bảo tính đa hình trong lập trình hướng đối tượng.
Như đã nói ở trên, nguyên tắc này đảm bảo các instance của lớp con có thể thay thế instance của lớp cha mà chương trình vẫn chạy ổn định, khi mở rộng phần mềm của mình bằng các lớp con kế thừa, chúng ta cần đảm bảo rằng các lớp con này có thể chạy được và chạy đúng những functions mà lớp cha đã cung cấp trước đó.