"인터페이스를 모두(always) 만드는 것에 대해서 어떻게 생각하세요?"라는 얘기를 pistos님에게 질문을 받은적이 있다. 술자리여서 깊게 얘기는 할수 없었지만, 한번 정리를 해보고 싶은 이야기였다.
클래스를 작성을 할때 무조건!!! 인터페이스를 두는 방법은 그다지 좋은 방법이라는 생각이 들지는 않는다. 항상 느끼는 거지만, 무조건이라는 말을 하기는 쉽지 않다. (그렇지만, 난 극단적인 표현을 사용하는 사람들의(Holub on pattern, prefactoring) 이야기를 즐기는 편이다. 장단점을 확연히 알수 있는 계기가 되기때문이다.)
특정한 layer에서 I/F하는 부분에서는 강제화하는 것은 layered architecture차원에서 있을수 있는 일(?)이지만, 그렇다고 모든 클래스를 인터페이스를 만들고, 구현체를 구현하는 것은 바보 같은 일이다. 모든 코드를 유연하게 만드는 만큼 시스템을 복잡하게 만드는 일은 없는 것이다. 어느 시점에는 강제화(상속,concrete)을 해야 한다.
C/C++에서 구현을 하는 헤더처럼 모든 클래스의 인터페이스를 구현하는 것은 너무 많은 클래스를 만들게 하고, 불필요한 작업을 하게 만든다. (단, 클래스 관계가 아닌 구현에 너무 집착하는 개발자에게는 가능한 인터페이스를 좀더 깊게 생각해보라고 얘기를 하고 싶다.)
InterfaceImplementationPair를 읽다가 보면 inteface를 많이 만드는 버릇은 C/C++에서 온 버릇때문인듯하다. 사실 나도 다시 한번 생각을 해보니, 그렇거 같기도 하다..^^
얼마전에 팀내에서 만성피로님이 interface를 사용하지 않겠다고 해서 논란이 있었지만, 적정한 합의점(?)은 layer간만이라도 최소한 interface로 만들자는 의견이었다. 사실 여러 개발자들이 따지고 들어가다가 보면 정답은 없기때문에 합의점을 찾는 것은 중요하다.
MF아저씨는 InterfaceImplementationPair에서 얻는 이득은 아래와 같이 얘기를 했다. 분명히 이득히 있다는 것이다.
하지만, MF는 그런 기술을 그다지 좋아하지 않는다고 얘기를 한다.
2가지 이유를 이야기를 한다. 우리가 불편하게 느끼는 2가지를 얘기를 하는 것이다. 사실 이 부분은 IDE가 MF가 얘기를 할때보다 더 좋아진게 분명하다.
이클립스에서 구현체로 바로 갈수 있는 플러그인이다.
http://eclipse-tools.sourceforge.net/implementors/download.html
2가지 이유중의 한 가지는 없어졌다
although good IDEs help, 싱크를 맞추는 문제는 상대적으로 노력이 적은 편이다.
또, 반대의 관점에서 보자. Concrete클래스 위주로 작성시이다.
과거에는 수작업으로 Extract Interface를 해야하기때문에 미리 만드는 수고를 해도 추후에 큰 빛을 볼수도 있었지만, IDE가 발달을 해서 eclipse IDE를 이용하면 extract interface를 할때 안전하게 할수가 있다. 구현체에 있던 주석까지도 안전하게 inteface로 옮겨준다. 수작업으로 하는 것은 좋지 않은 방법이며, IDE를 믿자.
구현중심의 클래스를 활용하다가 인터페이스가 필요한 시점이 생기면, 바로 refactoring을 하자. 다른 구현체로 교체하거나 인터페이스 기반으로 코드를 바꾸어야 할때 유용한 refactoring중의 하나이다.
Trade-Off가 발생을 한다. 인터페이스를 미리 만들고, 행위가 추가될때 CTRL 1으로 행위를 추가를 할 것인가? Concrete클래스에서 Multiple구현이 필요할때 Extract Interface를 할 것인가?
interface를 쓰던 concrete클래스를 쓰던간에 정확한 목표는 있어야 할 것이다. 개발을 할때 test코드와 production코드를 나누어서 작성을 할 것이냐? 둘다 가능한 코드로 작성을 할것이냐는 내 선택은 하나의 코드로 둘다(test code, production code) 가능하게 하는 것 이 베스트라고 생각을 한다. 중복코드가 없고, 변화가 생겼을때 유연하게 대처할수만 있다면, 어떤 한 것을 선택을 해도 그 방법이 절대 아니다라는 말을 할수가 없다.
테스트의 중요성과 TDD의 인기로 인터페이스로 코드를 작성하는 것이 일반시 되고 있다.
이 말은 Mock을 활용하기 위해서 multi구현이 가능한 형태로 되어야 한다는 이야기다. 인터페이스당 최소 구현체 2개라는 이야기다.
Concrete클래스는 Mock을 이용해서 테스트하기가 어렵다. 최근에는 이 마져도 여러가지 확장 라이브러리들(easymock-extenion, jmock-extention)이 손쉽게 할수 있는 방법을 제시를 해주고 있다. 여러가지 따지고 들어가다 보니, IDE의 발달로 정답이 없는 문제가 되어 버렸다. Trade-Off가 비슷하다는 생각이 든다.
비슷하다면, 보통 자신의 스타일에 맞는 것을 선호를 하게 된다. 여기서 미묘한 개인적인 취향으로 번지는 것이다. 코딩하는 스타일과도 밀접한 관계를 가질수도 있다.
많은 개발자들이 있고, 여러 lab,team이 존재를 할때는 가끔 강제적인 Rule이 필요하기도 하지만, 그게 가끔은 답답한 경우도 있다.
그렇지만, 항상 화두가 존재한다는 것이 재미있기도 하다. 모든 사람이 OOP를 잘하고, 정답이 하나였다면, 지루했을 것이다.
난 그래서 개발자가 Domain Expert에 가까워질수록 좋은 디자인의 코드가 나온다는 Eric Evans말에 올인한다. 시스템의 domain영역도 중요하지만, 회사스타일과 정책의 변화도 무시 못할 스키마중의 하나이다.
- 인터페이스라는 말이 너무 다양하게 쓰여서 위에 글은 아래와 같은 용어로 정의를 하였다.
interface : 자바에서 사용하는 interface
I/F : 외부와 통신하는 interface
PS. 이런 너무 글을 길게 써버렸다. 정답을 찾기 힘든 문제라 말이 길어진 듯하다. 예지력을 키워나가야 겠다.
