본문 바로가기
개발/Java

[Java] 상수 값에 행위를 정의하고 싶다면 - Constant Specific Method Implementation

by Mingvel 2023. 7. 22.

코드를 뚝딱뚝딱 만지다 보면 우리는 종종 특정 분류에 있는 값을 정의하여 사용해야 할 경우가 생기고

 

우리는 이것을 상수로 정의하여 사용하곤 합니다

 

가위바위보 게임을 예로 들자면 

 

가위, 바위, 보 이 세 가지는 가위바위보라는 범위 내의 각각의 상수값으로 정의할 수 있습니다

 

public enum RPS {
	ROCK,
	PAPER,
	SCISSORS;
}

 

모두가 아시다시피 가위바위보 게임은 가위,바위.보를 정의하는 것으로 끝나지 않습니다

 

가장 중요한 가위, 바위, 보 각각의 상관관계 


가위는 보를 이긴다
보는 주먹을 이긴다
주먹은 가위를 이긴다

위 규칙에 대한 정의 혹은 행위가 필요합니다

 

위 규칙을 구현하기 위해 우리는 가위바위보의 규칙을 정의하는 Util Class를 정의할 수 있습니다.

public class RPSRule {

    private RPSRule() {

        throw new IllegalStateException();
    }

    public static RPS determineWinner(RPS first, RPS second) {

        return switch (first) {
            case ROCK -> PAPER == second ? second : first;
            case SCISSORS -> ROCK == second ? second : first;
            case PAPER -> SCISSORS == second ? second : first;
        };
    }
}

위에서 예시로 정의한 RPSRule 유틸 클래스의 determineWinner 메서드를 사용하면 

 

두 가지 가위바위보 입력이 있을 때, 게임에서 승리한 값을 응답받을 수 있습니다

 

위 코드는 언뜻보면 그럴싸한 코드로 보일 수도 있습니다

 

하지만 위 코드를 OOP(Object Oriented Programing)의 관점에서 바라보면 

 

RPS라는 객체(상수)는 내부에 값을 정의하고 있지만

 

값들의 연관관계 혹은 행위에 대한 정의RPSRule에 의존하고 있기에 

 

이는 객체 내부 응집도가 떨어지는 코드라고 할 수 있습니다

 

 

이와 같은 상황에서 상수 내부에 행위를 정의함으로써 객체 내부 응집도를 높일 수 있는 방법 중 한 가지가 바로

Constant Specific Method Implementation 을 사용하는 것입니다

 

이는 상수에 추상메서드를 정의하고, 각각의 값에서 해당 추상 메서드를 구현하게 하면서, 행위를 정의할 수 있는 방법입니다

 

Constant Specific Method Implementation 을 사용하여 위 코드의 가위바위보 규칙을 RPS 내부에 정의한 내용은 다음과 같습니다

public enum RPS {
    ROCK {
        @Override
        public RPS determineWinner(RPS other) {

            // 상대가 PAPER 라면 상대 승
            return other == PAPER ? PAPER : this;
        }
    },
    PAPER {
        @Override
        public RPS determineWinner(RPS other) {

            //상대가 SCISSORS 라면 상대 승
            return other == SCISSORS ? SCISSORS : this;
        }
    },
    SCISSORS {
        @Override
        public RPS determineWinner(RPS other) {

            //상대가 ROCK 이라면 상대 승
            return other == ROCK ? ROCK : this;
        }
    };

    public abstract RPS determineWinner(RPSAct other);
}

 

위 코드에서처럼, 승리 값을 정하는 determineWinner 라는 메서드를 추상 메서드로 선언 후

 

각각의 값에서 행위를 구현할 수 있게 되었고, 응집도 높은 코드로 개선되었습니다

 

물론, 객체 지향과는 성격이 다른 패러다임인 DOP(Data Oriented Programing)의 관점에서 앞선 코드를 바라본다면 

객체의 데이터와 행위를 분리한 것에서 잘 짜여진 코드라고 볼 수도 있습니다

 

따라서 앞선 코드가 잘못 구현 된 코드고, 뒤에 설명한 코드가 잘 짜여진 코드라고 섣부르게 판단하기 보단

 

주어진 상황과 코드 스타일에 따라 적절히 판단하여 사용하는 것이 중요합니다

 

 

반응형

댓글