[리팩토링] 매직 넘버 치환

이제일·2021년 9월 4일
0

매직 넘버를 기호 상수로 치환

코드에 특정한 숫자(이를 매직 넘버라고 표현)를 직접 적는 경우
이를 int MAX_LENGTH = ... 처럼 기호 상수로 치환합니다.

문제점

매직 넘버를 사용할 경우

  • 수의 의미를 알기 어렵다
    특정한 값이 적혀있으면 무엇을 뜻하는지 바로 알기 어렵습니다.
if( inputValue > 100)
	return;

if( inputValue > MAX_INPUT_LENGTH )
	return;
  • 수정하기 어렵다
    요구사항의 변경등으로 수정을 해야 할 경우 값을 일일이 직접 변환 해주어야 하고, 동일한 값이라 하더라도 같은 의미인지를 확인해야하는 절차가 있어야합니다.
    이로인해 손도 많이가고 틀리기도 쉽습니다.

주의할 점

이해하기 어려운 이름을 사용하면 오해가 생길 수 있음

방법

다음의 코드를 변환하는 방법

public class Main {
	public static void main(String[] args) {
		Robot robot = new Robot();
		robot.order(0); // walk
		robot.order(1); // stop
		robot.order(2); // jump
	}
}

class Robot {
	public void order(int command) {
		if(command == 0) {
			System.out.println("walk");
		} else if(command == 1) {
			System.out.println("stop");
		} else if(command == 2) {
			System.out.println("jump");
		}
	}
}

public static final

가장 익숙하며 쉬운 방법

public class Main {
	public static void main(String[] args) {
		Robot robot = new Robot();
		robot.order(Robot.COMMAND_WALK); // 적절한 기호 상수의
		robot.order(Robot.COMMAND_STOP); // 이름 덕분에
		robot.order(Robot.COMMAND_JUMP); // 주석이 필요하지 않음
	}
}

class Robot {
	public static final int COMMAND_WALK = 0;
	public static final int COMMAND_STOP = 1;
	public static final int COMMAND_JUMP = 2;
    
	public void order(int command) {
		if(command == COMMAND_WALK) {
			System.out.println("walk");
		} else if(command == COMMAND_STOP) {
			System.out.println("stop");
		} else if(command == COMMAND_JUMP) {
			System.out.println("jump");
		}
	}
}

클래스로 치환

위에서 소개한 방법의 경우 외부에서 robot.order(0);을 사용하더라도 문제가 없습니다.
또한 분류 코드를 한 곳에 정리하여 보기 쉽게 하는 효과도 있습니다.

public class Main {
	public static void main(String[] args) {
		Robot robot = new Robot();
		robot.order(Robot.Command.COMMAND_WALK);
		robot.order(Robot.Command.COMMAND_STOP);
		robot.order(Robot.Command.COMMAND_JUMP);
	}
}

class RobotCommand {
	private final String name;
    
	public RobotCommand(String name) {
		this.name = name;
	}
}

class Robot {
	public static final int COMMAND_WALK = new RobotCommand("WALK");
	public static final int COMMAND_STOP = new RobotCommand("STOP");
	public static final int COMMAND_JUMP = new RobotCommand("JUMP");
    
	public void order(RobotCommand command) {
		if(command == COMMAND_WALK) {
			System.out.println("walk");
		} else if(command == COMMAND_STOP) {
			System.out.println("stop");
		} else if(command == COMMAND_JUMP) {
			System.out.println("jump");
		}
	}
}

인자값으로 클래스형을 받기 때문에 robot.order(0);을 쓸 경우 컴파일 에러가 나기에 실수를 컴파일러가 검출할 수 있게 됩니다.


enum으로 표현

자바 5부터는 enum 클래스를 이용해 기호 상수를 표현할 수 있게되었습니다.
위 처럼 분류하는 클래스를 자바에서 제공해주는 enum으로 대체한 방법입니다.

public class Main {
	public static void main(String[] args) {
		Robot robot = new Robot();
		robot.order(Robot.Command.WALK);
		robot.order(Robot.Command.STOP);
		robot.order(Robot.Command.JUMP);
	}
}

class Robot {
	public enum Command {
		WALK, STOP, JUMP,
	}
	public void order(int command) {
		if(command == Command.WALK) {
			System.out.println("walk");
		} else if(command == Command.STOP) {
			System.out.println("stop");
		} else if(command == Command.JUMP) {
			System.out.println("jump");
		}
	}
}
profile
세상 제일 이제일

0개의 댓글