# 76: The Single Responsibility Principle — SRP

Một trong những nguyên tắc nền tảng của một thiết kế tốt là:

Tập hợp tất cả những điều mà thay đổi bởi một lý do, và tách chúng thành những điều mà bị thay đổi bởi những lý do khác nhau. - Single Responsibility Principle

Một cách dễ hiểu chính là một hệ thống con, module, class, hay kể cả function không nên có nhiều hơn một lý do để thay đổi. Một ví dụ điển chính là một class gồm có những phương thức làm việc với những nguyên tắc kinh doanh, báo cáo, và database:

public class Employee { 
    public Money calculatePay()public String reportHours()public void save()}

Một vài lập trình viên nghĩa rằng việc kết hợp ba hàm này lại với nhau vào chung một class là một điều vô cùng đúng đắn. Suy cho cùng, Class là nơi tập hợp các hàm tính toán trên những biến chung. Tuy nhiên, vấn đề chính là ba hàm này thay đổi hoàn toàn dựa trên những lý do khác nhau.

  • Hàm calculatePay sẽ thay đổi bất cứ khi nào nguyên tắc kinh doanh của việc tính toán chi phí tăng.
  • Hàm reportHours sẽ thay đổi bất cứ khi nào có người nào đó muốn dùng một định dạng báo cáo khác.

Tuy nhiên, nếu lớp Employee bị lạm dụng bởi các bộ phận khác dẫn đến mọi sự thay đổi của Employee sẽ khiến cho những bộ phận khác phải triển khai lại và phủ định toàn bộ những lợi ích của mô hình thiết kế các thành phần(hoặc là SOA nếu bạn thích một cái tên hoa mỹ hơn).

public class Employee{
    public Money calculatePay()}

public class EmployeeReporter{ 
    public string reportHours(Employee e)}

public class EmployeeRepository{ 
    public void save(Employee e)}

Bằng một sự tách rời đơn giản của class ban đầu ở bảng trên đã giải quyết tất cả các vấn đề mà ta gặp phải. Mỗi class này có thể được đặt trong từng phần riêng của nó.

Hoặc là, mọi class phụ trách công việc báo cáo có thể được xếp vào bộ phận báo cáo. Tất cả mọi class liên quan đến việc trao đổi thông tin từ database có thể được xếp vào bộ phận lưu trữ. Và tất cả những class liên quan đến các quy luật kinh doanh thì có thể xếp vào bộ phận kinh doanh.

Nếu bạn nhanh trí bạn có thể nhận ra code ở trên vẫn còn sự phụ thuộc vào nhau.

Chính là kiểu Employee vẫn còn bị phụ thuộc vào những lớp khác. Vì vậy nếu Employee bị chỉnh sửa, hầu hết các những class khác đều phải compile lại hoặc tái sản xuất. Chính vì thế, kiểu Employee không thể bị thay đổi và phải được cài đặt một cách độc lập. Tuy nhiên những lớp khác đều có thể làm việc với nó được đồng thời phải được cài đặt độc lập. Không một sự thay đổi nào của một trong những lớp đó có thể khiến cho các lớp khác phải compile lại hoặc tái sản xuất. Kể cả kiểu Employee cũng có thể được cài đặt độc lập bằng cách sử dụng Đảo ngược phần tử độc lập (Dependency Inversion Principle - DIP), nhưng đó là một chủ đề khác cho một cuốn sách khác.

Hãy cẩn thận áp dụng SRP, phân biệt những điều mà bị thay đổi bởi các lý do khác nhau, là một trong những chiếc chìa khoá để tạo ra các thiết kế có cấu trúc các thành phần được triển khai một cách độc lập.