[JAVA] 01. 매직넘버를 심볼릭 정수로 치환하기

|
소스코드에 '100'과 같은 구체적인 숫자값(매직넘버)을 사용한 경우에 적용할 수 있는 리팩토링이다.

해당 코드를 리팩토링 하려는 이유는 숫자값 '100'이라는 값이 어떤 의미인지 파악하기 힘들고,

숫자값이 변경될 경우 어떠한 숫자값들이 여기서 의미하는 '100'과 같은 숫자인지 확인하고 수정하기 힘들기 때문이다.


그럼 지금부터 리팩토링의 대상이 될 예시 코드를 살펴보도록 하자.

먼저 매직넘버가 작성되어 있는 Robot 클래스부터 살펴보자.

리팩토링 적용 전

public class Robot {

    private final String _name;

    public Robot(String name){

        _name = name;

    }
 

    public void order(int command){

        if(command == 0){

            System.out.println(_name + " walks.");

        }else if(command == 1){

            System.out.println(_name + " stops.");

        }else if(command == 2){

            System.out.println(_name + " jumps.");

        }else{

            System.out.println("Command error. command = "+command);

        }

    }

}



다음은 Robot 클래스의 인스턴스를 생성하여 메소드를 호출하는 Main 클래스이다.

public class Main {

    public static void main(String[] args){

        Robot robot = new Robot("kjk3071");

              robot.order(0); //walk

              robot.order(1); //stop

              robot.order(2); //jump

    }

}


order에 보내는 파라미터가 어떤 기능을 수행하는지 전혀 알 수 없기 때문에 주석을 이용해 표현하고 있다.

하지만 이는 근본적인 문제해결로 볼 수 없으므로 리팩토링을 적용해 보도록 하겠다.



리팩토링 적용 후

public class Robot {

    private final String _name;
 

    public static final int COMMAND_WALK = 0;

    public static final int COMMAND_STOP = 1;

    public static final int COMMAND_JUMP = 2;
 

    public Robot(String name){

        _name = name;

    }
 

    public void order(int command){

        if(command == COMMAND_WALK){

            System.out.println(_name + " walks.");

        }else if(command == COMMAND_STOP){

            System.out.println(_name + " stops.");

        }else if(command == COMMAND_JUMP){

            System.out.println(_name + " jumps.");

        }else{

            System.out.println("Command error. command = "+command);

        }

    }

}


Robot 클래스의 매직넘버를 심볼릭 정수로 변환한 모습을 확인할 수 있다. 



Main 클래스에서도 Robot 클래스의 심볼릭 정수를 직접적으로 사용하였다.

접근제어자가 public 이고 static을 사용하였으므로 객체 생성여부 상관없이 해당 변수를 사용할 수 있다.

public class Main {

    public static void main(String[] args){

        Robot robot = new Robot("kjk3071");

        robot.order(Robot.COMMAND_WALK);

        robot.order(Robot.COMMAND_STOP);

        robot.order(Robot.COMMAND_JUMP);

    }

}




다른 방법을 사용한 심볼릭 정수 표현 

enum을 사용한 예시를 살펴보도록 하자.

public class Robot {

    private final String _name;

    public enum Command{

        WALK,

        STOP,

        JUMP

    }
 

    public Robot(String name){

        _name = name;

    }
 

    public void order(Robot.Command command){

        if(command == Command.WALK){

            System.out.println(_name + " walks.");

        }else if(command == Command.STOP){

            System.out.println(_name + " stops.");

        }else if(command == Command.JUMP){

            System.out.println(_name + " jumps.");

        }else{

            System.out.println("Command error. command = "+command);

        }

    }

}



public class Main {

    public static void main(String[] args){

        Robot robot = new Robot("kjk3071");
 

        robot.order(Robot.Command.WALK);

        robot.order(Robot.Command.STOP);

        robot.order(Robot.Command.JUMP);

    }

}



다음은 타입코드를 클래스로 치환하여 사용한 예시이다.

public class RobotCommand {

    private final String _name;
 

    public RobotCommand(String name){

        _name = name;

    }
 

    public String toString(){

        return "[ RobotCommand: " + _name + " ] "

    }

}


public class Robot {

    private final String _name;
 

    public static final RobotCommand COMMAND_WALK = new RobotCommand("walk");

    public static final RobotCommand COMMAND_STOP = new RobotCommand("stop");

    public static final RobotCommand COMMAND_JUMP = new RobotCommand("jump");
 

    public Robot(String name){

        _name = name;

    }
 

    public void order(RobotCommand command){

        if(command == COMMAND_WALK){

            System.out.println(_name + " walks.");

        }else if(command == COMMAND_STOP){

            System.out.println(_name + " stops.");

        }else if(command == COMMAND_JUMP){

            System.out.println(_name + " jumps.");

        }else{

            System.out.println("Command error. command = "+command);

        }

    }

}


public class Main {

    public static void main(String[] args){

        Robot robot = new Robot("kjk3071");
 

        robot.order(Robot.COMMAND_WALK);

        robot.order(Robot.COMMAND_STOP);

        robot.order(Robot.COMMAND_JUMP);

    }

}



다른 방법을 사용한 예시들은 다양한 방법을 통해 심볼릭 정수를 사용할 수 있다는 것을 보여준다.


하지만 심볼릭 정수를 적용하지 말아야 할 부분이 존재한다.

가변성을 띄는 변수나 명확히 정의된 변수가 바로 그러한 대상이다.

이외에도 바이트코드에 쓰여있는 정수를 조심해야 한다. 컴파일 시점에 따라 전혀 다른 값이 될 수 있기 때문이다.



지금까지 매직넘버를 심볼릭 정수로 변환하는 리팩토링에 대해서 살펴보았다.

리팩토링을 통해 개선하는것도 중요하지만, 이번 장의 내용은 최초 코딩시에 고려하여 작성하는 것이 가장 좋을 듯 싶다.

'JAVA > REFACTORING' 카테고리의 다른 글

[JAVA] 리팩토링의 정의  (0) 2012.02.15
And
prev | 1 | 2 | 3 | 4 | 5 | ··· | 28 | next