Java 클린코드 매직넘버 이슈 및 final 키워드

1. 매직넘버를 직접 작성하는것을 지양하라

소스코드를 보다보면 특정한 숫자 매직넘버(Magic Number)를 직접 작성하는 나쁜 스타일의 코드를 볼 수 있습니다.

만약에 캐싱으로 캐싱값들을 강제로 업데이트하는 로직이 있다고 가정해보겠습니다. 여기에서 캐시에 대한 시간값을 지정했다고 가정하면 다음과 같이 코드를 작성하는것이 올바른 코드 일까요? 아닙니다. 저렇게 내부적으로 상수값들을 선언을 해주게 되면 유지보수측면이나 코드의 가독성측면에서 좋지 않은 결과를 가져다 줄 것입니다.

매직넘버의 단점

  • 매직넘버의 의미를 알기어렵고 0,1의 의미를 직접알기에 매우 쉽지않습니다.
  • 매직넘버는 수정이 매우어렵고 유지보수를 힘들게합니다. 시간효율성측면에서 좋지않습니다.

캐싱 강제 업데이트(매직넘버 미적용)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 캐시 강제 업데이트
* @param query
* @return
*/
public Map<String, Movie.MovieDto> saveCacheByQuery(final String query) {
long nowTime = System.currentTimeMillis();
if(!CollectionUtils.isEmpty(movieMapCache) || nowTime - cacheLoadTime < 600 * 1000L;){
synchronized (movieMapCache){
cacheInitialized();
ResponseEntity<Movie.MovieDto> exchange = getExchange(query);
List<Movie.Item> ResponseMovieList = Movie.Item.of(exchange);
MovieGroup items = new MovieGroup(ResponseMovieList);
List<Movie.Item> listOrderRating = items.getListOrderRating();
Movie.MovieDto resultList = Movie.MovieDto.of(exchange, listOrderRating);
cacheLoadTime = nowTime;
movieMapCache.put(query, resultList);
}
}
return movieMapCache;
}

캐싱 강제 업데이트(매직넘버 적용)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

// 선언부
private volatile Long cacheLoadTime = 0L;
private volatile Long cacheTimeLimit = 600 * 1000L;

/**
* 캐시 강제 업데이트
* @param query
* @return
*/
public Map<String, Movie.MovieDto> saveCacheByQuery(final String query) {
long nowTime = System.currentTimeMillis();
if(!CollectionUtils.isEmpty(movieMapCache) || nowTime - cacheLoadTime < cacheTimeLimit){
synchronized (movieMapCache){
cacheInitialized();
ResponseEntity<Movie.MovieDto> exchange = getExchange(query);
List<Movie.Item> ResponseMovieList = Movie.Item.of(exchange);
MovieGroup items = new MovieGroup(ResponseMovieList);
List<Movie.Item> listOrderRating = items.getListOrderRating();
Movie.MovieDto resultList = Movie.MovieDto.of(exchange, listOrderRating);
cacheLoadTime = nowTime;
movieMapCache.put(query, resultList);
}
}
return movieMapCache;
}

다음과 같이 매직넘버를 기호 상수로 선언하여 클린코드의 습관을 들여야합니다. 혹은 enum이나 public static final 클래스 필드를 사용하여 명확한 값들을 지정해주어야합니다. 실수를 줄일 수 있고, enum을 사용하여 상수값으로 매직넘버를 직접 사용해도 문제없이 컴파일시점에 처리가 가능합니다.

2. final keyword

final class
다른 클래스에서 상속하지 못하게됩니다.

final method
다른 메소드에서 오버라이딩하지 못합니다.

final variable
변하지 않는 상수값이 되어 새로 할당할 수 없는 변수가 됩니다.

finally
try-catch or try-catch-resource 구문을 사용할 때, 마무리처리 작업 로직을 넣어야할때 사용합니다.

finalize()
keyword 도 아니고 code block 도 아닌 메소드입니다. 해당 메소드는 GC에 의해 호출되는 함수로 절대 호출해서는 안되며 Object 클래스에 정의되어 있으며 GC 가 발생하는 시점이 불분명하기 때문에 해당 메소드가 실행된다는 보장이 없습니다. 한 finalize() 메소드가 오버라이딩 되어 있으면 GC 가 이루어질 때 바로 Garbage Collecting 되지 않기때문에 GC 가 지연되면서 OOME(Out of Memory Exception)이 발생할 수 있는 이슈가 존재합니다.