Interface Segregation Principle – Nguyên lí phân biệt interface

Interface Segregation Principle – Nguyên lí phân biệt interface là gì ?

Nguyên lí này khá là đơn giản thôi, có thể chỉ cần đọc qua thôi là nhiều bạn cũng đã hiểu kha khá rồi. Nội dung nguyên lí như sau: many client-specific interfaces are better than one general-purpose interface. Không nên sử dụng một interface lớn cho một mục đích chung, nên tách ra thành nhiều interface nhỏ với những mục đích cụ thể.

Bạn có thể nhìn vào hình trên, bạn chỉ cần ăn hoặc uống nhưng vì bạn đã kế thừa interface DrinkEat nên bạn phải thực hiện cả 2 hàm ăn và uống. Kết quả nhận được thật đáng buồn (cười).

 

Để đơn giản, mình sẽ lấy một ví dụ đơn giản như sau: Với chức năng quản lí thành viên trong website thì bạn cần có một interface để đóng gói các hàm cần thiết, nhưng với chức năng Login thì bạn chỉ cần một vài hàm thực hiện chứ không cần thiết phải implements hết tất cả các hàm, do đó sẽ làm dài dòng và gây khó hiểu.

public interface IMembership {
    login();
    register();
    confirmEmail();
    forgotPassword();
    changePassword();
    showName();
    showAvatar();
    ...
}

public class ManageMember implements IMembership {
    login();  // do not do anything
    register(); // do not do anything
    forgotPassword(); // do not do anything
    changePassword(); // do not do anything
    
    showName(){
        //do something
    }
    showAvatar() {
        //do something
    }
    
    ...
}

public class Login implements IMembership {
    login() {
        // do something    
    } 
    register(); // do not do anything
    confirmEmail(); //do not do anything
    forgotPassword(); // do not do anything
    changePassword(); // do not do anything
    showName(); // do not do anything
    showAvatar(); // do not do anything
}

Sau khi áp dụng nguyên lí để phân chia interface ra các interface nhỏ hơn thì kết quả có vẻ khả quan hơn, hàm interface ILogin chỉ chứa các hàm giúp thực hiện việc Login, không có hàm nào dư thừa. Nếu để như ban đầu, khi ta thêm chức năng vào thì lại đưa vào IMemberShip, ảnh hưởng đến class đã implements nó. Ví dụ muốn thêm chức năng gửi một email xác nhận việc đăng nhập sentEmailVerifyLogin() thì sẽ làm class Register cũng phải implements theo mà thực sự class này không cần tới hàm này, chỉ khai báo để không bị báo lỗi hay sao ?

public interface ILogin {
    login();
    sentEmailVerifyLogin();
    forgotPassword();
    ...
}
public Login implements ILogin {
    login() {
        ...
    }
    sentEmailVerifyLogin() {
        ...
    }
    ...
}
public interface IRegister {
    register();
    confirmEmail();
    ...
}
public Register implements IRegister {
    register() {
        ...
    }
    confirmEmail() {
        ...
    }
    ...
}
public interface IMembership extends IRegister, ILogin  {
    ....
}

Cuối cùng interface IMemberShip extends các interface khác để có được các hàm cần thiết. Bạn có thể thấy được lợi ích của việc chia nhỏ các interface này ra giúp implements đủ các chúc năng cần thiết và cũng giảm đi việc vi pham nguyên lí thay thế Liskov do việc chia thành các phần nhỏ.

Các interface nhỏ nên có sự liên kết với nhau, cụ thể bên trong nó là một nhóm các hàm có một ý nghĩa logic với nhau. Đừng để chỉ một interface trong đó có một phương thức, như thế chỉ làm tăng số lượng interface gây khó khăn trong việc quản lí và cũng làm mất đi ý nghĩa của chúng.

Đọc đến đây thì chắc đa phần các bạn đều hiểu nguyên lí này rồi nhưng thực hiện ra sao, làm sao để trở nên khoa học cũng là do cách bạn thiết kế nữa đó.

Series Navigation<< Liskov Substitution principle – Nguyên lí thay thế LiskowDependency inversion principle – Nguyên lí nghịch đảo phụ thuộc >>

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *