Trong bài viết này, tôi sẽ giới thiệu và phân tích chi tiết về nguyên tắc SOLID trong lập trình hướng đối tượng, một khái niệm quan trọng giúp cải thiện chất lượng và bảo trì mã nguồn dễ dàng hơn. SOLID là viết tắt của năm nguyên tắc thiết kế phần mềm cơ bản, được đưa ra bởi Robert C. Martin và Michael Feathers. Các nguyên tắc này bao gồm:
Single Responsibility Principle (SRP) - Nguyên tắc Trách nhiệm Đơn lẻ
Mỗi class chỉ nên có một trách nhiệm duy nhất. Điều này giúp giảm sự phức tạp của mã nguồn, làm cho nó dễ đọc, dễ bảo trì và dễ kiểm thử hơn. Ví dụ, một class chỉ nên có nhiệm vụ quản lý thông tin người dùng, không nên bao gồm các nhiệm vụ như gửi email hay in ấn báo cáo.
Ví dụ:
typescript
class TaskManager {
constructor() {}
createTask(): void {
console.log("Create Task");
}
updateTask(): void {
console.log("Update Task");
}
removeTask(): void {
console.log("Remove Task");
}
}
Open/Closed Principle (OCP) - Nguyên tắc Mở/Đóng
Các class nên mở cho việc mở rộng nhưng đóng cho việc sửa đổi. Điều này có nghĩa là bạn có thể thêm chức năng mới mà không cần sửa đổi mã nguồn hiện có. Điều này thường được thực hiện thông qua việc sử dụng kế thừa và/hoặc giao diện (interfaces).
Ví dụ:
typescript
interface ExamApprove {
approveRequestExam(exam: NewExamType): void;
verifyConditionExam(exam: NewExamType): boolean;
}
class BloodExamApprove implements ExamApprove {
approveRequestExam(exam: ExamApprove): void {
if (this.verifyConditionExam(exam)) {
console.log("Blood Exam Approved");
}
}
verifyConditionExam(exam: ExamApprove): boolean {
return true;
}
}
class RayXExamApprove implements ExamApprove {
approveRequestExam(exam: ExamApprove): void {
if (this.verifyConditionExam(exam)) {
console.log("RayX Exam Approved");
}
}
verifyConditionExam(exam: NewExamType): boolean {
return true;
}
}
Liskov Substitution Principle (LSP) - Nguyên tắc Thay thế Liskov
Các đối tượng của class con nên có thể thay thế cho đối tượng của class cha mà không làm thay đổi tính đúng đắn của chương trình. Điều này đảm bảo rằng một class con có thể đứng thay thế cho class cha của nó mà không gây ra lỗi.
Ví dụ:
typescript
class Student {
constructor(public name: string) {}
study(): void {
console.log(`${this.name} is studying`);
}
}
class StudentGraduation extends Student {
study(): void {
console.log(`${this.name} is studying`);
}
deliverTCC() {}
}
class StudentPosGraduation extends Student {
study(): void {
console.log(`${this.name} is studying and searching`);
}
}
Interface Segregation Principle (ISP) - Nguyên tắc Phân tách Interface
Không nên ép buộc một class phải triển khai các interface mà nó không sử dụng. Thay vào đó, tạo các interface nhỏ và cụ thể hơn để các class chỉ cần triển khai những phương thức mà chúng cần.
Ví dụ:
typescript
interface Employee {
salary(): number;
}
interface Commissionable {
generateCommission(): void;
}
class Seller implements Employee, Commissionable {
salary(): number {
return 1000;
}
generateCommission(): void {
console.log("Generating Commission");
}
}
class Receptionist implements Employee {
salary(): number {
return 1000;
}
}
Dependency Inversion Principle (DIP) - Nguyên tắc Đảo ngược Phụ thuộc
Các module cấp cao không nên phụ thuộc vào các module cấp thấp. Cả hai nên phụ thuộc vào trừu tượng. Điều này có nghĩa là các đối tượng không nên tạo trực tiếp các đối tượng mà chúng phụ thuộc vào, mà thay vào đó nên sử dụng các interface hoặc lớp trừu tượng.
Ví dụ:
typescript
interface Order {
id: number;
name: string;
}
class OrderRepository {
constructor() {}
saveOrder(order: Order) {}
}
class OrderService {
private orderRepository: OrderRepository;
constructor(repository: OrderRepository) {
this.orderRepository = repository;
}
processOrder(order: Order) {
this.orderRepository.saveOrder(order);
}
}
Áp dụng các nguyên tắc SOLID không chỉ giúp tạo ra mã nguồn dễ bảo trì, mở rộng và tái sử dụng mà còn giúp các nhà phát triển suy nghĩ kỹ lưỡng hơn về cấu trúc và thiết kế của phần mềm. Việc tuân thủ các nguyên tắc này trong quá trình phát triển phần mềm sẽ đem lại lợi ích lâu dài, giảm thiểu chi phí bảo trì và nâng cấp trong tương lai.