Programming/Clean Code

Clean Code - 외부 코드 사용하기 (+ 경계 클래스, 어댑터 패턴)

JaeHoney 2022. 5. 10. 08:30

개요.

시스템에 들어가는 모든 소프트웨어를 직접 개발하는 경우는 드물다.

 

패키지를 사거나 라이브러리 등 오픈 소스를 사용하기도 한다. 이 때 우리는 외부 코드를 우리코드에 어떻게 해야 더 깔끔하고 안전하게 통합할 수 있는 지 고민해야 한다.

 

고민은 외부 코드와 우리 코드의 경계를 파악하는 것부터 시작한다.

 

경계(Boundaries)

 

전체 소프트웨어 개발에 사용하게 되는 외부 코드를 내 코드에서 호출하는 부분을 경계(boundaries)라고 한다.

 

경계 없이 단순하게 외부 코드를 사용하려는 곳에서 직접 호출할 수 있지만 그렇게 했을 때 아래와 같은 문제가 생긴다.

 

  • 인터페이스 제공자가 지원한 인터페이스를 그대로 사용해야 한다.
    • 인터페이스 제공자는 최대한 범용적이게 개발하는 것을 선호한다.
  • 인터페이스 사용자는 자신의 요구에 집중하는 인터페이스를 바란다.
  • 소프트웨어 변경에 많은 투자와 재작업이 필요하다.

외부 코드 사용하기

예로 java.util.Map을 살펴보자. 아래 그림에서 보듯이 Map은 굉장히 다양한 인터페이스로 수많은 기능을 제공한다. 인터페이스 제공자는 최대한 자신의 코드가 범용적이게 사용되는 것을 원하기 때문이다.

 

Map이 제공하는 기능성과 유연성은 확실히 유용하지만 그만큼 위험도 크다. 가령, Map을 여기저기서 사용한다고 가정해보자. 운영중인 소프트웨어에서는 Map을 clear()할 필요도 없고 해서도 안된다. 하지만 clear() 인터페이스는 제공된다. 즉 Map을 사용하는 사용자라면 누구나 Map을 지울 수 있다.

 

추가적으로 Map 인터페이스에 변경사항이 생긴다면 우리는 외부 코드인 Map 인터페이스를 수정할 수는 없기 때문에, 모든 소스를 돌아다니면서 Map을 사용하는 곳의 코드를 전부 수정해야 한다.

 

다음은 Map을 좀 더 깔끔하게 사용한 코드이다.

public Sensors {
    private Map<String, Sensor> sensors = new HashMap<>();
    
    public Sensor getById(String id) {
        return sensors.get(id);
    }
    
    // 이하 생략
}

외부 코드인 Map을 Sensors안으로 숨긴다. 이렇게 경계 인터페이스를 하나 두고 사용하면 아래와 같은 장점들이 있다.

  • Sensors 클래스는 비즈니스 로직에 필요한 인터페이스만 제공한다.
    • 프로그램이 설계 규칙과 비즈니스 규칙을 따르도록 강제할 수도 있다.
  • 변경 사항이 생기면 Sensors 클래스 내부만 고쳐주면 된다.

+ Map 클래스를 사용할 떄마다 위와 같이 캡슐화를 해야 한다는 말이 아니라, 이러한 상황이나 외부 코드를 사용할 때 경계 인터페이스를 고려해야 한다는 말이다.

 

외부 인터페이스를 사용할 때는 해당 인터페이스를 사용하는 클래스나 인터페이스 밖으로 노출되지 않도록 주의한다. 외부 인터페이스의 인스턴스를 그대로 인수로 넘기거나 반환 값으로 사용되지 말아야함을 의미한다.

 

아래와 같이 Adapter 패턴을 사용하는 방법도 존재한다.

참고(대상)

  • Client - 사용자
  • Adaptee - 외부 시스템
  • Adapter - 변환기 (경계 시스템)
  • Target Interface - 변환 대상 인터페이스 (Adapter가 구현하는 인터페이스)

설계 방법

  • Adaptee와 Target  Interface를 비교한다.
  • Adaptee와 Target Interface를 연결하는 Adapter 클래스를 작성한다.
  • Adapter 클래스를 의존성 주입하여 사용한다.

정리

정리하면 관리가 불가능한 외부 인터페이스에 모든 코드를 의존하지 말고 새로운 클래스로 경계를 감싸거나, 아니면 ADAPTER 패턴을 사용해서 우리가 원하는 인터페이스를 제공하게 변환하자.

 

어느 방법이든 코드 가독성이 높아지며, 실수를 방지할 수 있고 변경할 코드도 줄어든다.

 


Reference