앞서 SOLID 설계 5원칙 중 세번째 원칙인 LSP에 대해 공부하였다. LSP는 하위 클래스 타입의 인스턴스는 상위형 객체 참조형 변수에 대입해 상위 클래스의 인스턴스 역할을 하는데 문제가 없어야 한다.
주로 상위클래스에 명시하지 않은 리턴 값을 반환하거나, 명시하지 않은 예외를 발생시키거나, 혹은 상위클래스의 의도와 다른 기능을 구현할 경우 LSP를 위반하게 되며, 이는 곧 OCP도 위반하게 되는 것을 말한다. 확장에는 더 닫혀있기 때문에, 설계를 함에도 있어 LSP를 염두해두고 개발을 하는 습관을 길러야 한다.

그럼 이제 4번째 설계 원칙인 ISP에 대해 알아보도록 한다.

ISP - Interface Segregation Principle

The interface-segregation principle(ISP) states that no client should be forced to depend on methods it does not use. 클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안된다.
앞서 이야기 했던 단일 책임 원칙(SRP)와 인터페이스 분리 원칙(ISP)는 같은 문제(용도에 맞게 기능을 분리하는 것)에 대한 두 가지 다른 해결 책이라고 볼 수 있다. 프로젝트 요구사항이나 설계자의 취향에 따라 두가지중 하나를 선택해서 하나를 설계 할 수 있다. 하지만 특별한 경우가 아니라면 단일 책임 원칙을 사용하는 것이 더 좋은 해결책이라고 할 수 있다.
추가로, 인터페이스 분할 원칙을 이야기 할 때 함께 등장하는 원칙 중 하나로 인터페이스 최소주의 원칙이라는 것이 있다. 인터페이스를 통해 메소드를 외부에 제공할 때는 최소한의 메소드만 제공하라는 것이다. 인터페이스 분리 원칙에서 주장하는 의도와 동일하다.

잘못된 예시와 개선 사례 (1)


// 하나의 인터페이스를 모든 클라이언트가 구현하고 있음

public interface ArticleService {
    void list();
    void write();
    void delete();
}

public class UiList implements ArticleService {
    @Override
    public void list() {}
    
    @Override
    public void write() {}
    
    @Override
    public void delete() {}
}

public class UiWist implements ArticleService {
    @Override
    public void list() {}
    
    @Override
    public void write() {}
    
    @Override
    public void delete() {}
    
}

public class UiDist implements ArticleService {
    @Override
    public void list() {}
    
    @Override
    public void write() {}
    
    @Override
    public void delete() {}
    
}

위 사례에서 ArticleService 인터페이스는 list(), write(), delete()메소드를 선언하였다. UiList는 조회만 필요하고, UiWist는 쓰기만 필요하고, UiDist는 삭제하는 기능만 필요함에도 불구하고 모두 본인이 사용하지 않는 메소드에 의존 관계를 맺고 있다. 위의 코드를 아래와 같이 개선해보자.

// 각각의 클라이언트별로 Interface를 구분

public interface ArticleListService {
    void list();
}

public interface ArticleWriteService {
    void Write();
}

public interface ArticleDeleteService {
    void Delete();
}

public class UiList implements ArticleListService {
    @Override
    public void list() {}
}

public class UiWist implements ArticleWriteService {
    @Override
    public void write() {}
}

public class UiDist implements ArticleDeleteService {
    @Override
    public void delete() {}
}

결론

인터페이스 분리 원칙은 클라이언트 입장에서 인터페이스를 분리하는 원칙이다. 각 클라이언트가 사용하는 기능을 중심으로 인터페이스를 분리함으로써, 클라이언트로부터 발생하는 인터페이스 변경의 여파가 다른 클라이언트에 미치는 영향으 최소화 할 수 있게 한다.


참고자료

  1. 스프링 입문을 위한 객체 지향의 원리와 이해
  2. 개발자가 정복해야 할 객체지향-4
  3. 객체지향의 5대 설계 원칙 - SOLID

oksusutea's blog

꾸준히 기록하려고 만든 블로그