[S.O.L.I.D] – Interface Segregation Principle

Giới thiệu

Trước khi bắt đầu nguyên lý thứ 4 tương ứng với chữ I trong nguyên tắc SOLID, mình xin nhắc lại về interface. 

Interface là một khuôn mẫu mà bên trong nó chỉ có các method chứ không có thân hàm. Các class implement từ interface mặc định phải triển khai các method này. Thế nhưng từ java 8 trở đi thì chúng ta còn thêm nhiều tuỳ chọn khác như static method, default method etc. 

Phát biểu: Thay vì sử dụng một interface lớn chúng ta nên tách thành nhiều interface nhỏ, với nhiều mục đích cụ thể.

interface_segregation_principle_thumb

Để thiết kế một hệ thống linh hoạt, dễ bảo trì và nâng cấp các module trong hệ thống giao tiếp với nhau thông qua interface. Giữa các module chúng sẽ gọi nhau thông qua interface mà không cần quan tâm đến implement bên dưới của nó. 

Đối với một interface, khi một class implement nó bắt buộc phải implement các method được khai báo bên trong interface. Nếu bạn khai báo một interface quá rất với rất nhiều method thì các class implement nó phải triển khai toàn bộ. Và đôi khi chúng lại không cần thiết.

Áp dụng Interface Segregation principle

Áp dụng interface segregation principle, chúng ta sẽ chia một interface lớn ra thành nhiều interface nhỏ, mỗi interface chứa một nhóm các method liên quan đến nhau.

Ví dụ

public interface Animal {
  void Eat();
  void Drink();
  void Sleep();
}
class Dog implement Animal {
  public void Eat () {} 
  public void Drink () {} 
  public void Sleep () {} 
}

class Cat implement Animal {
  public void Eat () {} 
  public void Drink () {} 
  public void Sleep () {} 
}

Khi muốn thêm một loài động vật mới và chúng có các chức năng mới như bay, bơi etc thì chúng ta phải thêm các method này vào interface. Điều này làm interface càng ngày càng phình to và các loài vật implement interface Animal đều phải triển khai tất cả các method kể cả những method chúng không sử dụng. Ví dụ như Chó làm sao bay? =)).

public interface Animal {
  void Eat();
  ...
  void Swim();
  void Fly();
}
class Fish implement Animal {
  public void Eat () {} 
  ...
  public void Swim() {}
  public void Fly() { throw new UnsupportedOperationException("Ca khong biet bay"); }
}
public class Bird implement Animal {
  public void Eat () {} 
  ...
  public void Swim() { throw new UnsupportedOperationException("Chim khong biet boi"); }
  public void Fly()
}

Trong thực tế khi chúng ta làm chức năng mới, thì thường mình sẽ thêm một method vào interface cứ như vậy interface sẽ ngày càng to ra. Và khi bạn thêm các method như vậy thì bỗng nhiên các class cũ implement từ nó trước đó như Dog, Cat đều phải triển khai trong khi chúng không cần dùng đến như fly() chó làm sao biết bay.

Để giải quyết vấn đề này chúng ta cần tách interface Animal thành nhiều interface nhỏ và phân chúng theo nhóm chức năng. Ví dụ như mình sẽ chia nó ra thành các interface Bird, Fish.

public interface Animal {
  void Eat();
  void Drink();
  void Sleep();
}
public interface Bird {
  void Fly();
}
public interface Fish {
  void Swim();
}

// Các class chỉ cần kế thừa những interface có chúc năng chúng cần
public class Dog implement Animal {
  public void Eat() {}
  public void Drink() {}
  public void Sleep() {}
}

public class FlappyBird implement Animal, Bird {
  public void Eat() {}
  public void Drink() {}
  public void Sleep() {}
  public void Fly() {}
}

public class FormosaFish: Animal, Bird {
  public void Eat() {}
  public void Drink() {}
  public void Sleep() {}
  public void Swim() {}
}

Kết luận

Chúng ta cần kết hợp với nguyên tắc Single responsibility principle để chia nhóm chức năng cho hợp lý và từ đó mới khởi tạo các interface theo từng nhóm chức năng riêng. 

Nếu sử dụng nguyên tắc này đúng đắn sẽ giảm thiểu code dư thừa đáng kể vì các class sẽ không phải triển khai các method mà nó không sử dụng. Đó cũng là một dấu hiệu cho biết rằng bạn có đang vi phạm nguyên tắc này hay không!.

Tham khảo: http://blogs.msdn.com/b/cdndevs/archive/2009/07/15/the-solid-principles-explained-with-motivational-posters.aspx

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x