[Java] 인터페이스(Interface) 네이밍

어정윤·2022년 4월 3일
2

SSAFY-7th

목록 보기
1/3
post-thumbnail

[Java] 인터페이스(Interface) 네이밍

0. 들어가며

SSAFY 7기부터 현직자 멘토링이 새로 생겼다. 사실 별로 관심이 없었는데 같은 반 동기가 멘토링 게시판을 애용한다는 이야기를 듣고 어떤 질문들이 올라와 있는지 호기심에 멘토링 게시판을 둘러보던 중 흥미로운 게시글을 발견했다.

실습 때 사용하던 인터페이스의 네이밍에 대한 질문이었는데, 결론부터 말하면 실습 때 사용하던 네이밍은 지양해야하는 방법이라는 것을 새롭게 알았다.

사실 이 부분은 이전에 Java 스터디를 할 때 했던 다뤘던 내용일 수 도 있지만 잘 기억이 안난다...반성하고 복습하자.

1. 헝가리안 표기법(Hungarian Notation)

1-1. 헝가리안 표기법이란

헝가리안 표기법(Hungarian Notation)이란 프로그래밍 언어에서 변수 및 함수의 이름 인자 앞에 데이터 타입을 명시하는 코딩 규칙이다.

찰스 시모니(Charles Simonyi)가 마이크로소프트(Microsoft)의 개발 책임자로 있을 때 제안했으며, 제안자인 찰스 시모니가 헝가리아인이라서 헝가리안 표기법으로 불렸다. 80년대 당시에는 IDE라는게 부실했기 때문에 이 규칙이 엄청난 센세이션을 불러 일으켰다.

하지만 지금은 MS도 공식 가이드라인에서 사용하지 말 것을 권고하고 있다.

1-2. 헝가리안 표기법 적용

헝가리안 표기법은 명확한 룰이 없으므로 사용자에 따라 조금씩 다를 수 있지만, 아래 표가 공통적으로 많이 쓰이는 규칙이다.

  • 공통

  • OOP

1-3. 헝가리안 표기법 사용 예시

double dAverage = 50.0;
dAverage = 40.5;  // 이후 변수 네이밍만 보고 double 형임을 알 수 있다.
int nMemberCount = 5;
nMemberCount = increaseMember();  // 이후 변수 네이밍만 보고 int 형임을 알 수 있다.

1-4. 헝가리안 표기법 장점

  • 위 예시에서 본 것처럼 데이터 타입을 변수명에서 바로 추정할 수 있다.
  • 같은 의미를 가지는 서로 다른 타입의 변수가 있을 때 이름 충돌을 방지할 수 있다.

1-5. 헝가리안 표기법 단점

  • 코드를 단번에 파악하기 힘들어진다.
  • 변수나 함수 인자의 이름을 기억하기 힘들다.
  • 데이터 타입이 바뀌면 변수 또는 함수 인자의 이름을 바꿔야 한다. → 리팩토링을 지원하는 IDE가 없으면 많은 시간 투자가 필요하다. 특히 PHP, JavaScript, Python 같은 동적 타입 언어라면 함수 인자의 이름으로 타입을 명시해주는 만큼 수정이 필수적이므로, 헝가리안 표기법은 좋지 않은 선택이다.
  • 같은 의미를 가지는 서로 다른 타입의 변수가 있을 때 이것들을 왜 선언했는지 잊어버릴 경우 코드를 이해하기 어려워지고, 이는 유지보수성을 낮춘다.

2. 인터페이스(Interface) 네이밍

2-1. 헝가리안 표기법의 잔재

실습 중 배포된 파일에는 인터페이스를 구현한 구현체에는 Impl 접미사가 붙은 걸 볼 수 있다. 이는 헝가리안 표기법의 잔재로, 지양해야 하는 표기법이다.

2-2. 인터페이스 네이밍 방법

인터페이스를 네이밍할 때는 인터페이스의 이름을 그 의미 자체에 따라 지어야 한다.

예를 들어 전진go()), 후진(back()), 현재 위치 반환(getDistance())의 기능을 공통으로 갖는 자동차 클래스를 생성한다고 하자.

공통 기능인 전진, 후진, 현재 위치 반환을 각각의 클래스들이 갖고 있는 것은 객체지향적이지 못한 코드이다. 각 객체에서 중복되는 전진, 후진, 현재 위치 반환의 행위를 인터페이스로 추상화하는 것이 필요하다.

이때 인터페이스의 네이밍은 자동차의 움직임이라는 행위 자체로 네이밍을 해야한다는 것이다.

public class CarTest {

    public static void main(String[] args) {
        Move avante = new AvanteCar();
        Move porsche = new PorscheCar();
        avante.go();
        porsche.go();
        porsche.back();
        System.out.println("avanteCar = " + avante.getDistance());  // 10
        System.out.println("porscheCar = " + porsche.getDistance());  // 90
    }
}

interface Move {

    void go();

    void back();

    int getDistance();
}

class AvanteCar implements Move {

    private static final int GO_COUNT = 10;
    private static final int BACK_COUNT = 5;

    private int distance = 0;

    @Override
    public final int getDistance() {
        return this.distance;
    }

    @Override
    public final void go() {
        distance += GO_COUNT;
    }

    @Override
    public final void back() {
        distance -= BACK_COUNT;
    }
}

class PorscheCar implements Move {

    private static final int GO_COUNT = 100;
    private static final int BACK_COUNT = 10;

    private int distance = 0;

    @Override
    public final int getDistance() {
        return this.distance;
    }

    @Override
    public final void go() {
        distance += GO_COUNT;
    }

    @Override
    public final void back() {
        distance -= BACK_COUNT;
    }
}

추가로, Java Standard Library에서 List 인터페이스의 구현체인 ArrayList, LinkedList를 ArrayListImpl, LinkedListImpl이라고 명명하지 않는 것을 통해 헝가리안 표기법을 사용하지 않는다는 것을 다시 한 번 알 수 있다.

Impl과 같은 접미어는 DRY 규칙에도 어긋난다.

3. DRY 규칙

3-1. DRY 규칙이란

DRY 규칙은 Don’t Repeat Yourself의 약자로, ‘반복하지 마라’는 규칙이다.

3-2. DRY 규칙에 위배되는 네이밍 실수

앞에서 언급한 인터페이스의 구현체에 Impl 과 같은 접미사를 붙이는 행위처럼 DTO(Data Transfer Object)에 dto 접미사를 붙이는 실수를 많이 한다. 나 또한 지금까지 DTO에 해당 접미사를 붙였다. dto접미사를 붙이는 대신 패키지(package)에 넣음으로써 DRY 규칙을 따를 수 있다.

4. 정리

만약 클래스 뒤에 Impl이라는 접미어를 붙일 수 밖에 없는 상황이라면, 인터페이스를 쓰는 것 자체에 대해 다시 생각해볼 필요가 있다. 인터페이스와 그것을 구현한 단 하나의 구현체만 있는 경우라면, 이런 경우에는 인터페이스를 쓰지 않는 것이 더 바람직할 수 있다.

Reference

헝가리안 표기법

자바 인터페이스 이름관련: I로 시작하는 interface? impl로 끝나는 클래스?

DRY 원칙

profile
성장ing

0개의 댓글