티스토리 뷰
매직넘버 / 리터럴 사용
매직넘버/리터럴 이란 프로그래밍에서 비즈니스적 의미를 가진 숫자나 문자를 그대로 표현한 것을 칭한다.
public class BankingAccount {
private BigDecimal depositAmount;
public String productName(String productCode) {
if ("1".equals(productCode)) {
return "입출금통장";
}
if ("2".equals(productCode)) {
return "모임통장";
}
throw new IllegalArgumentException("상품이 존재하지 않습니다.");
}
public void makeDeposit(BigDecimal depositAmount) {
if (depositAmount.compareTo(BigDecimal.valueOf(0L)) < 0) {
throw new IllegalArgumentException("입금 금액을 입력해 주세요");
}
this.depositAmount = this.depositAmount.add(depositAmount);
}
}
상위 코드는 은행 통장을 표현한 클래스이다. 통장의 금융상품명을 처리할 때 "1", "2" 와 같은 매직 리터럴을,
입금 처리를 할 때 입금금액에 대한 검증에서 0L 이라는 매직 넘버를 사용했다.
코드에서 비즈니스적 의미를 제대로 선언하지 않은 숫자나 문자열은 그것이 무엇을 의미하는 지 알 수 없다. 의미를 파악하기 위해 별도의 주석이나 문서를 관리해야 하거나, 프로그램의 흐름을 분석해야 한다.
무분별하게 사용된 매직넘버는 관리에 어려움을 준다. 매직넘버가 가진 비즈니스 로직이 변경된다면 모든 코드의 매직넘버를 찾아서 수정해주어야 하는데, 같은 숫자값을 가진 서로 다른 의미의 매직넘버들이 산재되어 있다면 변경 과정에서 장애를 일으킬 확률이 매우 높다.
(매직넘버와 매직 리터럴은 이 포스팅에서는 '매직넘버' 라는 표현으로 모두 대체하겠습니다)
매직넘버 치환 방법
매직넘버를 치환하는 방법으로는 아래와 같이 상수와 Enum을 활용하는 방안을 생각해 볼 수 있다.
상수 활용
public class BankingAccount {
private static final long MIN_DEPOSIT_AMOUNT = 0L;
private BigDecimal depositAmount;
public void makeDeposit(BigDecimal depositAmount) {
if (depositAmount.compareTo(BigDecimal.valueOf(MIN_DEPOSIT_AMOUNT)) < 0) {
throw new IllegalArgumentException("입금 금액을 입력해 주세요");
}
this.depositAmount = this.depositAmount.add(depositAmount);
}
}
상기 코드에서는 최소 입금금액을 MIN_DEPOSIT_AMOUNT 라는 상수로 치환했다. 0원 이라는 금액을 상수로 치환하여 최소 입금금액을 검증한다는 코드의 의미도 파악하기에 좋고, 최소 입금금액이 변경되면 상수선언의 값만 바꿔주면 된다. 추후 필요 시 상수의 접근지정자를 변경해 다른 코드에서도 활용할 수 있다.
Enum 활용
public class BankingAccount {
public String productName(String productCode) {
return BankingProduct.productName(productCode);
}
}
public enum BankingProduct {
DEPOSIT_ACCOUNT("1", "입출금통장"),
PARTY_ACCOUNT("2", "모임통장");
private String productCode;
private String productName;
BankingProduct(String productCode, String productName) {
this.productCode = productCode;
this.productName = productName;
}
public static String productName(String productCode) {
return Arrays.stream(values())
.filter(bankingProduct -> bankingProduct.productCode.equals(productCode))
.findFirst()
.orElseThrow( () -> new IllegalArgumentException("상품이 존재하지 않습니다."))
.name();
}
}
상기 코드는 enum을 활용하여 매직넘버를 치환했다. enum은 그 자체로 비즈니스적 의미를 갖는 공통적 요소들을 관리할 수 있고, 비즈니스 로직을 함께 관리할 수 있는 장점도 가진다. enum에 대한 자세한 활용은 별도의 포스팅으로 작성해 보겠다.
의미없는 상수 변환
숫자 1을 ONE 이라는 상수로 치환한다든가, for 루프와 같은 반복문에서 0을 FIRST_INDEX 로 치환하는 행위가 굳이 필요할지는 고려해봐야겠다. 매직넘버의 치환은 특수한 의미를 갖는 데이터의 업무적 가독성을 높이고, 변경에 안전한 코드를 작성하는데 의미가 있다고 생각한다.
'프로그래밍 > 클린코드 & 리팩토링' 카테고리의 다른 글
[객체지향 생활체조 원칙] 규칙 5. 줄여쓰지 않는다 (0) | 2021.09.05 |
---|---|
[객체지향 생활체조 원칙] 규칙 4. 한 줄에 점을 하나만 찍는다 (0) | 2021.08.29 |
[객체지향 생활체조 원칙] 규칙 3. 모든 원시값과 문자열을 포장한다 (3) | 2021.08.28 |
[객체지향 생활체조 원칙] 규칙 2. else 예약어를 쓰지 않는다 (0) | 2021.08.21 |
[객체지향 생활체조 원칙] 규칙 1. 한 메서드에 오직 한 단계의 들여쓰기만 한다 (0) | 2021.08.14 |
- Total
- Today
- Yesterday