Nguyên lý SOLID trong lập trình: Hiểu đúng để viết code chất lượng

1. Single Responsibility Principle (SRP) – Nguyên tắc trách nhiệm duy nhất

Mô tả: Một lớp chỉ nên có một lý do để thay đổi, nghĩa là nó chỉ nên có một nhiệm vụ duy nhất.

Lợi ích: Giúp hệ thống dễ bảo trì, giảm nguy cơ ảnh hưởng ngoài ý muốn khi thay đổi code.

 

Ví dụ sai lầm:

public class Report {

public void GenerateReport() { /* Code tạo báo cáo */ }

public void PrintReport() { /* Code in báo cáo */ }

}

Sửa đúng:

public class ReportGenerator {

public void GenerateReport() { /* Code tạo báo cáo */ }

}

public class ReportPrinter {

public void PrintReport() { /* Code in báo cáo */ }

}

2. Open/Closed Principle (OCP) – Nguyên tắc đóng/mở

Mô tả: Các module trong phần mềm nên được mở rộng mà không cần sửa đổi code hiện có.

Lợi ích: Giảm rủi ro bug khi thêm tính năng mới, dễ mở rộng hệ thống.

Ví dụ sai lầm:

public class AreaCalculator {

public double CalculateArea(Rectangle r) {

return r.Width * r.Height;

}

}

Sửa đúng:

public interface IShape {

double CalculateArea();

}

public class Rectangle : IShape {

public double Width, Height;

public double CalculateArea() => Width * Height;

}

public class Circle : IShape {

public double Radius;

public double CalculateArea() => Math.PI * Radius * Radius;

}public class AreaCalculator {

public double CalculateArea(IShape shape) {

return shape.CalculateArea();

}

}

3. Liskov Substitution Principle (LSP) – Nguyên tắc thay thế Liskov

Mô tả: Một lớp con phải có thể thay thế lớp cha của nó mà không làm thay đổi tính đúng đắn của chương trình.

Lợi ích: Đảm bảo tính kế thừa đúng đắn, tránh lỗi khi sử dụng đa hình.

Ví dụ sai lầm:

public class Bird {

public virtual void Fly() { Console.WriteLine(“Flying”); }

}

public class Penguin : Bird {

public override void Fly() { throw new Exception(“Penguins can’t fly!”); }

}

Sửa đúng:

public abstract class Bird {}

public interface IFlyable { void Fly(); }

public class Sparrow : Bird, IFlyable {

public void Fly() { Console.WriteLine(“Flying”); }

}

public class Penguin : Bird {}

4. Interface Segregation Principle (ISP) – Nguyên tắc phân tách Interface

Mô tả: Một interface lớn không nên ép các lớp con triển khai những phương thức mà chúng không sử dụng.

Lợi ích: Tránh việc các lớp không cần thiết phải implement những phương thức không dùng đến.

Ví dụ sai lầm:

public interface IWorker {

void Work();

void Eat();

}

Sửa đúng:

public interface IWorkable { void Work(); }

public interface IEatable { void Eat(); }

5. Dependency Inversion Principle (DIP) – Nguyên tắc đảo ngược sự phụ thuộc

Mô tả: 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 abstraction.

Lợi ích: Dễ thay đổi và mở rộng hệ thống mà không ảnh hưởng đến các phần khác.

Ví dụ sai lầm:

public class SQLDatabase {

public void SaveData(string data) { /* Lưu vào SQL */ }

}

public class DataService {

private SQLDatabase db = new SQLDatabase();

public void Save(string data) { db.SaveData(data); }

}

Sửa đúng:

public interface IDatabase {

void SaveData(string data);

}

public class SQLDatabase : IDatabase {

public void SaveData(string data) { /* Lưu vào SQL */ }

}

public class DataService {

private IDatabase _db;

public DataService(IDatabase db) { _db = db; }

public void Save(string data) { _db.SaveData(data); }

}

Zalo

AI Trợ Giảng

Luôn sẵn sàng hỗ trợ

Xin chào!

Tôi là AI trợ giảng của Study+. Tôi có thể giúp bạn tìm khóa học phù hợp, giải đáp thắc mắc về nội dung học tập và hỗ trợ các vấn đề kỹ thuật.