프로그래밍을 하다보면 숫자나 문자열을 하드코딩하게 되는 경우가 있다.
다음은 그 예시들이다.
매직넘버: 의미가 명확하지 않은 구체적인 숫자 값
for(int i=0; i<10; i++)
문자열 리터럴: 로그 또는 에러메세지, 텍스트 등 자주 사용되는 문자열
"[ERROR] 잘못 된 주소 입력입니다."
환경설정 값: DB연결 문자열, API, 포트번호 등
"jdbc:mysql://localhost:3306/mydatabase?user=root&password=1234"
파일 경로
"/resources/testImages/lena.png"
정규 표현식
"[가-힣a-zA-Z]+\d+"
프로그램의 가독성과 유지보수를 향상시키기 위해 이 값들은 상수화 할 필요가 있다.
상수란, 프로그램이 실행되는 동안 '값이 고정되어 변경할 수 없는 메모리 공간' 을 의미한다.
자바 프로그래밍을 할 때, 문자열이나 매직넘버 등을 상수화 할때 사용할만한 방법은 두 가지가 있다.
상수 값이 애플리케이션에서 중요한 역할을 하고, 그 값들이 명확히 구분되어야 하며, 추가 기능이 필요한 경우 enum을 사용하는 것이 좋다. 그러나 만약 단순한 상수 값만 필요하고 추가 로직이 필요하지 않은 경우에는 static final 을 사용하는 것이 코드를 간결하게 유지할 수 있다.
public final class GameConstants {
public static final String ERROR_INVALID_INPUT = "[ERROR] 잘못된 숫자 입력입니다.";
public static final String ERROR_INVALID_CONTINUE_INPUT = "[ERROR] 1 또는 2 를 입력하세요.";
public static final int MIN_NUMBER = 1;
public static final int MAX_NUMBER = 9;
public static final int MAX_NUMBER_LENGTH = 6;
public static final String INPUT_REGEX = "\\d+";
private GameConstants() {} // 인스턴스화 방지
}
// 다른 파일에서..
void numberInput(String inputString) {
if (!Pattern.matches(INPUT_REGEX, inputString)) {
throw new IllegalArgumentException(ERROR_INVALID_INPUT);
}
}
단순한 값 표현은 이렇게 사용하면 된다.
public enum GameStatus {
CONTINUE("1"),
STOP("2");
private final String status;
GameStatus(String status) {
this.status = status;
}
public String getStatus() {
return status;
}
public static boolean isValidStatus(String inputStatus) {
for (GameStatus status : GameStatus.values()) {
if (status.getStatus().equals(inputStatus)) {
return true;
}
}
return false;
}
}
// 다른 파일에서..
void continueInput(String inputContinue) {
if (!GameStatus.isValidStatus(inputContinue)) {
throw new IllegalArgumentException(ERROR_INVALID_CONTINUE_INPUT);
}
}
상수 값이 명확히 구분되고, 비슷한 카테고리로 묶이는 경우나, 추가 로직이 필요한 경우에는 열겨형이 확실히 깔끔하다.
상수 클래스를 만들면, 전역에서 접근 가능한 값이 생긴것이다.
이 상수를 로직에서 사용할 때는 정확히 나타내는 의미를 이해하는것이 중요하다.
예를 들어, MAX_SIZE = 3
이라는 상수를 정의하고 프로그램의 여러 부분에서 이 값을 사용하여 구현했다. 처음에는 이 상수가 프로그램의 다양한 부분에 적합한 것처럼 보일 수 있다. 하지만, 추후에 유지보수 과정에서 MAX_SIZE
의 값을 변경하게 되면 문제가 발생할 수 있다.
변경된 MAX_SIZE
값이 여러 부분에서 사용되었던 것이 각각 서로 다른 의미를 가지고 있었을 가능성이 있기 때문이다. 예를 들어, 한 곳에서는 MAX_SIZE
가 최대 허용 파일 개수를 의미했을 수 있고, 다른 곳에서는 사용자의 최대 인원 수를 의미했을 수 있다. 이러한 경우, 단일 상수 값의 변경이 서로 다른 부분에서 예상치 못한 결과를 초래할 수 있다.
명확한 네이밍
이를 해결하기 위해, 상수 네이밍을 명확하게 해야한다.
MAX_FILE_SIZE
와 MAX_PEOPLE_COUNT
와 같이 명확한 네이밍을 하면 실수 가능성이 줄어든다.
전역 상수 줄이기
상수 클래스에는 정말 전역에서 명확한 의미를 가지고 사용되는 값만 저장하고,
그렇지 않은 상수들은 사용되는 클래스에서만 private
로 정의하여 그곳에서만 사용하는것이 좋다. 이럴 경우 추후 유지보수를 진행해도 다른 파일에서 오류가 발생할 가능성이 적어진다.