Joonas' Note

Joonas' Note

SOLID 원칙 - Interface Segregation Principle (ISP; 인터페이스 분리 원칙) 본문

개발

SOLID 원칙 - Interface Segregation Principle (ISP; 인터페이스 분리 원칙)

2023. 5. 16. 00:57 joonas

    정의

    Interface Segregation Principle (ISP; 인터페이스 분리 원칙)

    특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.

     

    위반 사례

    이 ATM기는 총 3개의 모듈을 가지고 있는데, 어떤 거래(transaction)에 대해서 입금(Deposit), 출금(Withdrawal), 송금(Transfer) 모듈을 각자 만들었다.

    각 모듈은 전문화된 기능을 가지기 위해 분리되었지만, 무언가 이상하다.

    입금 거래 모듈은 입금만 하면 되는데, 위 구조와 같다면 코드가 이럴것이다.

    public class DepositTransaction extends Transaction implements UI {
      @Override public void requestDepositAmount() {
        System.out.println("Request deposit");
      }
    
      @Override public void requestWithdrawalAmount() {
        throw new UnsupportedMethodException("Can not withdrawal at Deposit Transaction");
      }
    
      @Override public void requestTransferAmount() {
        throw new UnsupportedMethodException("Can not transfer at Deposit Transaction");
      }
    
      @Override public void execute() {
        requestDepositAmount();
      }
    }
    
    public class WithdrawalTransaction extends Transaction implements UI {
      @Override public void requestDepositAmount() {
        throw new UnsupportedMethodException("Can not deposit at Withdrawal Transaction");
      }
    
      @Override public void requestWithdrawalAmount() {
        System.out.println("Request withdrawal");
      }
    
      @Override public void requestTransferAmount() {
        throw new UnsupportedMethodException("Can not transfer at Withdrawal Transaction");
      }
    
      @Override public void execute() {
        requestWithdrawalAmount();
      }
    }
    
    public class TransferTransaction extends Transaction implements UI {
      @Override public void requestDepositAmount() {
        throw new UnsupportedMethodException("Can not deposit at Transfer Transaction");
      }
    
      @Override public void requestWithdrawalAmount() {
        throw new UnsupportedMethodException("Can not withdrawal at Transfer Transaction");
      }
    
      @Override public void requestTransferAmount() {
        System.out.println("Request transfer");
      }
    
      @Override public void execute() {
        requestTransferAmount();
      }
    }

    입금 거래 모듈을 개발하는 입장에서, 송금이 되지 않는다는 걸 작성하는 일은 필요하지 않고 옳지 못하다.

    해결

    각 모듈에 맞게 인터페이스를 분리하여 해결할 수 있다.

    UI 인터페이스를 모듈별로 분리하였다. 이제 각 모듈은 사용하는 기능들만 구현하면 된다.

    먼저, UI 인터페이스를 각 모듈을 위해 쪼개자.

    // integrated interface for general
    public interface UI extends DepositUI, WithdrawalUI, TransferUI {}
    
    // segregated interface
    public interface DepositUI {
        void requestDepositAmount();
    }
    
    public interface TransferUI {
        void requestTransferAmount();
    }
    
    public interface WithdrawalUI {
        void requestWithdrawalAmount();
    }

     

    그리고 각 모듈에서 필요한 인터페이스만 가져다가 구현한다.

    public class DepositTransaction extends Transaction {
      private DepositUI depositUI;
    
      public DepositTransaction(DepositUI ui) {
        depositUI = ui;
      }
    
      @Override
      public void execute() {
        depositUI.requestDepositAmount();
      }
    }
    
    public class WithdrawalTransaction extends Transaction {
      private WithdrawalUI withdrawalUI;
    
      public WithdrawalTransaction(WithdrawalUI ui) {
        withdrawalUI = ui;
      }
    
      @Override
      public void execute() {
        withdrawalUI.requestWithdrawalAmount();
      }
    }
    
    public class TransferTransaction extends Transaction {
      private TransferUI transferUI;
    
      public TransferTransaction(TransferUI ui) {
        transferUI = ui;
      }
    
      @Override
      public void execute() {
        transferUI.requestTransferAmount();
      }
    }

    이제 필요한 기능만 구현하면 되는 인터페이스가 준비되었다. 그럼 아래와 같은 코딩이 가능하다.

    public void testFunction() {
      Transaction custom = new TransferTransaction(new TransferUI() {
        @Override
        public void requestTransferAmount() {
          System.out.println("Request transfer for me");
        }
      });
      custom.execute();
    }

    주의 사항

    개발을 하다보면 클라이언트가 사용하지 않는 메소드를 추가하여, 하나의 인터페이스가 거대해지는 일이 잦다.

    쪼개려다보면 애매한 상황도 많고 파일이 많아지는게 또 피곤한 일이라, 굉장히 위배하기 쉬운 원칙이다.

    전체 구조 및 코드

    ​위 링크에서 실행 결과와 함께 더 자세히 확인해 볼 수 있다

    참고

     

    SOLID (객체 지향 설계) - 위키백과, 우리 모두의 백과사전

    위키백과, 우리 모두의 백과사전. -->

    ko.wikipedia.org

    http://stg-tud.github.io/sedc/Lecture/ws16-17/3.2-ISP.pdf

     

    Interface Segregation Principle: Everything You Need to Know

    A practical guide to understand and apply the Interface Segregation Principle, one of the SOLID principles.

    reflectoring.io

    The Interface Segregation Principle, Robert C. Martin, C++ Report, June 1996

     

    896isp.pdf

     

    drive.google.com

     

     

    The ATM User Interface Example | Agile Principles, Patterns, and Practices in C#

    Now let's consider a slightly more significant example: the traditional automated teller machine (ATM) problem. The user interface of an ATM needs to be very flexible. The output may need to be translated into many different languages and it may need to be

    flylib.com

     

    Comments