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

Nguyên Lý SOLID trong C#

0 0 31

Người đăng: LongNguyen

Theo Viblo Asia

1. Định nghĩa

  • SOLID là nguyên tắc thiết kế, phát triển phần mềm. Mục đích giúp cho lập trình viên viết code tốt hơn, dễ đọc, dễ bảo trì.

  • SOLID được ghép lại từ 5 chữ viết tắt đầu tiên của 5 nguyên tắc này:

    • S is single responsibility principle (SRP)
    • O stands for open closed principle (OCP)
    • L Liskov substitution principle (LSP)
    • I interface segregation principle (ISP)
    • D Dependency injection principle (DIP)

2.1 . Single responsibility principle (SRP)

  • Một class chỉ nên giữ 1 trách nhiệm duy nhất (Chỉ có thể sửa đổi class với 1 lý do duy nhất)

  • Mục đích là để dễ đọc, dễ quản lý. Thử tưởng tượng bạn có một class làm quá nhiều việc, khi đó bạn nhìn vào sẽ rất rối và việc sửa đổi cũng tốn nhiều công sức => thiết kế tồi nhét tất cả mọi thứ vào một class.

  • Ví dụ thực tế nếu bạn thiết kế một dụng cụ vừa là búa vừa là cờ lê thì rất khó sử dụng => thiết kế tồi. Tốt hơn là nên chia ra riêng. Một dụng cụ búa, một dụng cụ là cờ lê.

 public class Employee { public int Employee_Id { get; set; } public string Employee_Name { get; set; } /// <summary> /// This method used to insert into employee table /// </summary> /// <param name="em">Employee object</param> /// <returns>Successfully inserted or not</returns> public bool InsertIntoEmployeeTable(Employee em) { // Insert into employee table. return true; } /// <summary> /// Method to generate report /// </summary> /// <param name="em"></param> public void GenerateReport(Employee em) { // Report generation with employee data using crystal report. } }
  • Phân tích: Class ‘Employee’ có 2 trách nhiệm, một là trách nhiệm thao tác với cơ sở dữ liệu và cái kia là tạo ra báo cáo. Lớp Employee không nên đảm nhận việc tạo ra báo cáo vì giả sử đến một ngày khách hàng yêu cầu phải tạo ra báo cáo trong Excel hoặc bất cứ định dạng nào khác, class này lại phải thay đổi cho phù hợp => Điều này là không tốt.

  • Giải pháp: Chúng ta nên viết sang một class khác cho việc tạo báo cáo, vậy khi có bất cứ sự thay đổi nào với việc tạo báo cáo, sẽ không ảnh hưởng đến class Employee.

public class ReportGeneration
{ /// <summary> /// Method to generate report /// </summary> /// <param name="em"></param> public void GenerateReport(Employee em) { // Report reneration with employee data. }
}

2.2 Open closed principle (OCP)

  • Nguyên lý thứ hai, tương ứng với chữ O trong SOLID. Nội dung nguyên lý:

Có thể mở rộng 1 class, nhưng không được sửa đổi bên trong class đó

public class ReportGeneration
{ /// <summary> /// Report type /// </summary> public string ReportType { get; set; } /// <summary> /// Method to generate report /// </summary> /// <param name="em"></param> public void GenerateReport(Employee em) { if (ReportType == "CRS") { // Report generation with employee data in Crystal Report. } if (ReportType == "PDF") { // Report generation with employee data in PDF. } } }
  • Phân tích: Vấn đề xảy ra khi bạn muốn thêm nhiều loại export như xls, word, xlsx,... lúc này bạn phải sửa class cũ ReportGeneration và thêm vào nhiều if bên trong phương thức GenerateReport. => Việc chỉnh sửa class này không được khuyến khích, ta sẽ tìm giải pháp khác để mở rộng class ban đầu.

  • Giải pháp: Ta sẽ sử dụng một interface để trừu tượng hóa chức năng tạo report. Khi có thêm loại report ta chỉ cần tạo class cụ thể và sử dụng interface này.

public interface IReportGeneration { public void GenerateReport(Employee em); } /// <summary> /// Class to generate Crystal report /// </summary> public class CrystalReportGeneraion : IReportGeneration { public void GenerateReport(Employee em) { // Generate crystal report. } } /// <summary> /// Class to generate PDF report /// </summary> public class PDFReportGeneraion : IReportGeneration { public void GenerateReport(Employee em) { // Generate PDF report. } }

2.3 Liskov substitution principle (LSP)

  • Class con không nên phá vỡ các định nghĩa và hành vi của class cha.

  • Ví dụ: Employee là lớp cha của Developer và BotDeveloper. Hai class này kết thừa từ Employee.

public abstract class Employee
{ public string Empcode {get;set;} public string FristName {get;set;} public string LastName {get;set;} public virtual string GetFullname() { return $"{FirstName} {LastName}"; }
} public class Developer : Employee
{ public override string GetFullname() { return $"Developer - {FirstName} {LastName}"; }
} public class BotDeveloper: Employee{ public override string GetFullname() { throw new NotImplementedException(); }
} List<Employee> employeeList = new List<Employee>();
employeeList.Add(new Developer());
employeeList.Add(new BotDeveloper());
foreach (Employee e in employeeList)
{ e.GetFullname();
}
  • Vấn đề: class nhân viên máy móc đã phá vỡ các định nghĩa và hành vi của class cha là class nhân viên - một nhân viên là con người.

  • Giải pháp: BotDeveloper không được kế thừa Employee và nên được tách riêng ra 1 class mới.

2.4 Interface segregation principle (ISP)

  • Thay vì dùng 1 interface lớn, ta nên tách thành nhiều interface nhỏ, với các mục đích khác nhau.
 public interface IExportReport { void ExportExcelReport(); void ExportPdfReport(); }
  • Vấn đề: có những nhân viên chỉ cần chức năng export excel, có nhân viên cần cả 2 chức năng. Lúc này nếu gom chung lại thì ta phải implement lại tất cả phương thức.
  • Giải pháp: Tách nhỏ mỗi loại export ra thành các interface nhỏ.
 public interface IExportPdfFile { void ExportPdfReport(); } public interface IExportExcelReport { void ExportExcelReport(); }

2. 5 Dependency inversion principle (DIP)

  • Không nên viết code gắn chặt với nhau bởi vì sẽ là cơn ác mộng cho việc bảo trì khi ứn dụng trở lên lớn dần. Nếu một class phụ thuộc một class khác, bạn sẽ cần phải thay đổi class đó nếu một trong những class phụ thuộc phải thay đổi. Chúng ta nên cố gắng viết các class ít phụ thuộc nhất có thể.

  • Giảm sự phụ thuộc bằng cách inject (tiêm) các class phụ thuộc vào class dùng class đó.

Tham khảo:

Bình luận

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

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

4 đặc tính của lập trình hướng đối tượng (Object oriented program)

Lập trình hướng đối tượng quá quen thuộc rồi bạn nào học lập trình đều phải học, đi phỏng vấn cũng vậy hỏi suốt(chắc cái này tùy vào vị trí tuyển dụng chủ yếu junior chắc chắn sẽ hỏi).nó là nền tảng cho hầu hết các design pattern hiện nay.

0 0 34

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

Khác nhau giữa abstract class và interface khi nào dùng chúng

Nhắc đến Interface và abstract class hãy nhớ 2 từ này khá clear rồi, Khi sử dụng Interface là bạn Implement còn sử dụng abstract class là bạn extend. . Interface:. .

0 0 29

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

So sánh Interface và Abstract trong lập trình hướng đối tượng.

Tổng quan. Interface và Abstract class là 2 khái niệm cơ bản trong lập trình OOP.

0 0 48

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

Áp Dụng Nguyên Tắc SOLID Trong Lập Trình

Giới Thiệu. 1. SOLID là gì. SOLID là viết tắt của 5 chữ cái đầu trong 5 nguyên tắc:.

0 0 21

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

Kỹ thuật giải quyết bài toàn về policy và công thức tính toán động cho sản phẩm phần mềm

Dạo này tôi có một mối duyên rất tình cờ với việc làm các phần mềm thuộc lĩnh vực tài chính và ngân hàng. Một số bài toán trong lĩnh vực này làm tôi nhớ đến những ngày đầu làm việc với phần mềm Trinet

0 0 21

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

Object Relational Mapping

Trong cách phát triển ứng dụng web hiện nay chắc hẳn các bạn đã quen với với từ khóa ORM(Object Relational Mapping). Khi mà thời đại của các framework ứng với các ngôn ngữ đang lên ngôi một cách mạnh

0 0 28