My reflections on the interface



시스템을 자주 설계하면서 항상 느끼는 고찰이 하나 있다.
이럴 때는 인터페이스를 어떻게 디자인하는 것이 좋을 까?
이에 대해 필자의 생각에 대해 작성해보고자 한다.
언제 인터페이스를 사용하면 좋을 까?
인터페이스의 목적은 행위를 추상적으로 표현한 집합체
라고 생각한다.
어떤 행위를 수행해야하는 데, 그 행위가 구체적으로 표현하기 어려울 때, 인터페이스를 사용한다고 생각한다. 예를 들면 섭취
라는 행위를 할 때, 어떤 생명체는 입으로 먹을 것이고, 어떤 생명체는 입이라는 기관 대신 다른 기관이 섭취할 것이다. 이렇듯 섭취
라는 행위는 구체화하기 위해서는 많은 고민을 하게 된다.
인터페이스는 이러한 상황에서 섭취
라는 행위를 추상적으로 바꿀 수 있다.
위 예시처럼 인터페이스로 표현할 수 있을 것이다.
인터페이스는 추상적이다.
Lifable(생명가능) 인터페이스에는 #consume
이라는 메소드를 가지고 있다. 하지만, 만일 이러한 인터페이스를 사용해 사용자(개발자)가 입으로 먹는 생명체를 인터페이스로 정의하도록 해야한다고 가정해보자.
사실 이 글을 작성하고 있는 필자 역시 어떻게 인터페이스로 정의해야할지 감이 잡히지 않을 정도로 이상하다. 물론 다음과 같이 정의하는 것이 가능하다.
하지만 이러한 방식은 구체(클래스)를 생성할 때, #consume
메소드를 재정의를 하기 때문에, 입을 사용하도록 하는 것을 강제화시키지 못한다.
인터페이스는 소제목과 마찬가지로 "추상적"이다. 기존 기능을 구체화시키는 책임은 인터페이스에게는 없다. 구체화시키는 책임은 클래스에게 있다. 함부로 클래스의 책임을 가져가려고 하지 마라.
인터페이스를 올바르게 설계하는 방법
만일 위와 같이 입으로 먹는 생명체를 정의하고 싶다면, 다음을 고려해보라.
-
아예 다른 기능들을 추가하여 확장하면서 기능을 구체화시키도록 하기
동물이라는 인터페이스를 그냥 새롭게 정의하면서 기능을 추가하면서 명세를 통해 입을 통해 먹도록 하는 방식이다.
-
추상 클래스 사용하기
추상클래스를 통해 강제로 입으로 먹도록 할 수 있고, 추상 메소드를 통한 템플릿 메소드 기법으로도 가능하다. 물론 추상 메소드없이 구현하는 것도 가능하다.
-
클래스에 구체화하기
가장 일반적으로 구현체에게 구현의 책임을 부여하여 구현하는 방법이다.
각 상황에 맞게 설계하면 된다.
인터페이스와 관련된 정보들
- 구체가 다른 인자들을 모두 가지고 있도록 설계하고 싶다면, 인자가 없는 함수를 정의하는 것도 괜찮다.
- 단, 구체에 너무 의존적일 수 있기에 이 점을 유의해야한다.
- 인터페이스는 새로운 구현을 간단히 할 수 있다.
- 공통된 동작을 정의하고, 다양한 클래스에서 재사용할 수 있다는 점이 인터페이스의 매력이다.
- 클래스의 의존성은 되도록 인터페이스를 주입받도록 하는 것을 지향하는 것이 좋다.
- 클래스간 결합도를 낮출 수 있기 때문이다.
- SOLID 원칙 중 ISP(인터페이스 분리 원칙)을 이행할 때는 항상 고민해야한다.
- ISP로 인해 인터페이스가 우후죽순으로 늘어나면 관리가 힘들기 때문이다.
- 되도록 인터페이스는 각 메소드마다 주석을 다는 것을 추천한다.
- 인터페이스를 설계할 때는 신중히 고민하고, 자주 변경되지 않는 부분에 적용하는 것이 좋다.
마무리 및 요약
인터페이스는 추상적이지만, 추상적이기에 강력하다. 이 글은 많이 부족하지만, 인터페이스를 언제, 그리고 어떻게 사용해야할지 기초적으로 도움을 줬기를 바란다.
요약
- 인터페이스는 공통된 동작을 정의해 재사용성을 높이는 데 사용된다.
- 인터페이스는 결합도를 낮추고 응집력은 높여준다.