- vừa được xem lúc

Hiểu Open - Closed Principle qua ví dụ !

0 0 14

Người đăng: Henryk Sienkiewicz

Theo Viblo Asia

Open - Closed Principle là gì

  • The Open Closed Principle (OCP) is the SOLID principle which states that the software entities (classes or methods) should be open for extension but closed for modification.
  • Nguyên tắc đóng mở (OCP) là một nguyên tắc trong SOLID mà ở đó các thực thể (class hoặc method) cần dễ mở rộng và khó sửa đổi.

Ví dụ thực tế

  • Hiện tại scope của team tất cả member đều là developer.
  • Bây giờ sếp cần chúng ta tính toán tổng lương của nhân viên trong team.
  • Ở đây salary của một dev = HourlyRate * WorkingHours
Bắt đầu nào !
  • Tạo class DeveloperReport
public class DeveloperReport
{ public int Id { get; set; } public string Name { get; set; } public string Level { get; set; } // Level của member public int WorkingHours { get; set; } // Số giờ làm việc public double HourlyRate { get; set; } // Hệ số lương
}
  • Tiếp theo là viết hàm tính toán tổng lương của team
public class SalaryCalculator
{ private readonly IEnumerable<DeveloperReport> _developerReports; public SalaryCalculator(List <DeveloperReport> developerReports) { _developerReports = developerReports; } public double CalculateTotalSalaries() { double totalSalaries = 0D ; foreach (var devReport in _developerReports) { totalSalaries += devReport.HourlyRate * devReport.WorkingHours; } return totalSalaries; }
}
  • Hàm Main
static void Main(string[] args)
{ var devReports = new List<DeveloperReport> { new DeveloperReport {Id = 1, Name = "Dev1", Level = "Senior developer", HourlyRate = 10.5, WorkingHours = 55 }), new DeveloperReport {Id = 2, Name = "Dev2", Level = "Junior developer", HourlyRate = 20, WorkingHours = 30 }), new DeveloperReport {Id = 3, Name = "Dev3", Level = "Senior developer", HourlyRate = 12, WorkingHours = 50 }) }; var calculator = new SalaryCalculator(devReports); Console.WriteLine($"Tong luong cua anh em {calculator.CalculateTotalSalaries()} dollars");
}
  • Mọi thứ hoạt động đều tốt ?. Nhưng một ngày đẹp trời chính sách công ty thay đổi. Sếp bảo "Không được tháng này là tháng 12 rồi các huynh đài senior member lúc này được tăng thêm 20%" vì một lý do nào đó mà ai cũng biết nhưng không ai nói ?
  • Lúc này thì chúng ta cần phải sửa lại code một chút
  • Lúc này hàm tính toán lương của thành viên trong team sẽ trở thành
public double CalculateTotalSalaries()
{ double totalSalaries = 0D; foreach (var devReport in _developerReports) { if(devReport.Level == "Senior developer") { totalSalaries += devReport.HourRate * devReport.WorkingHours * 1.2; } else { totalSalaries += devReport.HourRate * devReport.WorkingHours; } } return totalSalaries;
}
  • Mọi thứ lại hoạt động tốt trở lại nhưng có vẻ không ổn.
  • Mỗi lần có sự thay đổi yêu cầu của sếp về bonus salary của dev thì chúng ta phải sửa lại code ở hàm CalculateTotalSalaries cho đúng ý sếp ?
  • Rõ ràng là cần có giải pháp nào đó để xử lý vấn đề này hmmm
  • Lúc này thì Open - Closed Principlesẽ phát huy tác dụng ?

Áp dụng Open - Closed Principle

  • Tạo abstract class BaseSalaryCalculator
public abstract class BaseSalaryCalculator
{ protected DeveloperReport DeveloperReport { get; private set; } public BaseSalaryCalculator(DeveloperReport developerReport) { DeveloperReport = developerReport; } public abstract double CalculateSalary();
}
  • Tiếp theo là tạo 2 class SeniorDevSalaryCalculator, JuniorDevSalaryCalculator tương ứng với 2 level dev trong team Senior & Junior (mỗi level dev thì có một cách tính hệ số lương khác nhau ở đây thì các huynh đài senior sẽ được x 1.2)
public class SeniorDevSalaryCalculator : BaseSalaryCalculator
{ public SeniorDevSalaryCalculator(DeveloperReport report) :base(report) { } public override double CalculateSalary() => DeveloperReport.HourlyRate * DeveloperReport.WorkingHours * 1.2;
}
public class JuniorDevSalaryCalculator : BaseSalaryCalculator
{ public JuniorDevSalaryCalculator(DeveloperReport developerReport) :base(developerReport) { } public override double CalculateSalary() => DeveloperReport.HourlyRate * DeveloperReport.WorkingHours;
} 
  • Bây giờ là lúc viết hàm tính toán lương SalaryCalculator

public class SalaryCalculator
{ private readonly IEnumerable<BaseSalaryCalculator> _developerCalculation; public SalaryCalculator(IEnumerable<BaseSalaryCalculator> developerCalculation) { _developerCalculation = developerCalculation; } public double CalculateTotalSalaries() { double totalSalaries = 0D; foreach (var devCalc in _developerCalculation) { totalSalaries += devCalc.CalculateSalary(); } return totalSalaries; }
}
  • Hàm main
 class Program
{ static void Main(string[] args) { var devCalculations = new List<BaseSalaryCalculator> { new SeniorDevSalaryCalculator(new DeveloperReport {Id = 1, Name = "Dev1", Level = "Senior developer", HourlyRate = 10.5, WorkingHours = 55 }), new JuniorDevSalaryCalculator(new DeveloperReport {Id = 2, Name = "Dev2", Level = "Junior developer", HourlyRate = 20, WorkingHours = 30 }), new SeniorDevSalaryCalculator(new DeveloperReport {Id = 3, Name = "Dev3", Level = "Senior developer", HourlyRate = 12, WorkingHours = 50 }) }; var calculator = new SalaryCalculator(devCalculations); Console.WriteLine($"Tong luong cua anh em {calculator.CalculateTotalSalaries()} dollars"); }
} 
  • Mọi thứ bây giờ có vẻ khá ổn. Nếu một ngày đẹp trời sếp lại yêu cầu thay đổi cách tính lương của một level dev mới trong team thì đơn giản. Chúng ta chỉ cần tạo thêm một class giống như class SeniorDevSalaryCalculator là xong !!
Tóm cái váy lại.
  • Nhìn vào ví dụ bên trên thì chúng ta thấy class SalaryCalculator đã bị đóng sổ (Closed) nhưng có thể được mở rộng (Open). Đúng với những gì mà Open - Closed Principle yêu cầu.
  • Cách code và tổ chức code nhìn rất khoa học dễ hiểu và quan trọng hơn là chiều được lòng sếp ?

Bình luận

Bài viết tương tự

- vừa được xem lúc

Các loại tham chiếu Nullable trong C# (Phần 1)

1. Giới thiệu. C# 8.0 giới thiệu kiểu tham chiếu nullable và kiểu tham chiếu non-nullable cho phép bạn đưa ra các lựa chọn quan trọng về thuộc tính cho các biến kiểu tham chiếu:.

0 0 52

- vừa được xem lúc

Command pattern qua ví dụ !

Command pattern là gì . Command pattern khá phổ biến trong C #, đặc biệt khi chúng ta muốn trì hoãn hoặc xếp hàng đợi việc thực hiện một yêu cầu hoặc khi chúng ta muốn theo dõi các hoạt động. Hơn nữa, chúng ta có thể hoàn tác tác chúng. .

0 0 192

- vừa được xem lúc

Hiểu Liskov Substitution Principle qua ví dụ !

Liskov Substitution Principle là gì . Nguyên tắc đóng mở xác đinh rằng các instance của lớp con có thể thay thế được instance lớp cha mà vẫn đảm bảo tính đúng đắn của chương trình.

0 0 36

- vừa được xem lúc

Creating custom Controls Wpf

Introduction. Wpf/winforms provides various controls like Buttons, Textbox, TextBlock, Labels etc.

0 0 55

- vừa được xem lúc

[P1] Chọn công nghệ nào để xây dựng website?

Hiện nay nhu cầu phát triển website, app tăng rất cao do xu hướng "số hóa 4.0" trong và ngoài nước.

0 0 86

- vừa được xem lúc

Kiểu dữ liệu trong C#

Dẫn nhập. Ở bài BIẾN TRONG C# chúng ta đã tìm hiểu về biến và có một thành phần không thể thiếu khi khai báo biến – Đó là kiểu dữ liệu.

0 0 36