Home Item57 (지역변수의 범위를 최소화하라)
Post
Cancel

Item57 (지역변수의 범위를 최소화하라)

지역변수의 범위를 최소화하라

아이템 15인 클래스와 멤버의 접근 권한을 최소화하라와 비슷한 맥락의 이야기이다.

지역 변수의 유효 범위를 최소화해 코드 가독성과 유지 보수성을 높이자. 오류 가능성 또한 줄어든다.

그렇다면 지역 변수의 범위를 최소화하는 방법을 알아보자.

가장 처음 쓰일때 선언하기

지역변수 범위를 최소화하는 방법 중 가장 강력한 방법은 가장 처음 쓰일 때 선언하는 것이다.

사용하는 위치에서 먼 곳에 선언부터 한다면, 가독성이 떨어진다. 변수를 실제로 사용하는 시점에는 타입과 초깃값이 기억이 나지 않는 경우까지 생긴다.

지역변수를 생각 없이 마구잡이로 선언하다 보면 변수가 쓰이는 범위보다 너무 앞서 선언하거나 다 쓴 뒤에도 여전히 살아있도록 하는 경우가 생길 수 있다.

또 모든 지역 변수는 선언과 동시에 초기화해주어야 한다. 초기화에 필요한 정보가 충분하지 않을 경우 지역변수 선언을 미루면 된다.

단 try-catch문은 예외이다.

1
2
3
4
5
6
Class<? extends Set<String>> c1 = null; //지역 변수
try {
	c1 = (CLass<? extends Set<String>>) Class.forName(args[0]);
} catch (ClassNotFoundException e) {
	//...
}
  • 변수를 초기화하는 표현식에서 검사 예외를 던질 가능성이 있다면 try 블록 내에서 초기화해야 한다.
    • try 블록 내에서 초기화하지 않으면 예외가 블록을 넘어 메서드에까지 전파될 수 있다.
  • 변수값을 try 블록 바깥에서도 사용해야 한다면 정확히 초기화할 수 없더라도 위 예시 코드처럼 try 블록 앞에서 선언하면 된다.

for문을 사용해 변수 범위를 최소화하기

for-each, while 등 여러 반복문이 있다.

그 중 for문은 반복 변수의 범위가 반복문의 몸체, 그리고 for 키워드와 몸체 사이의 괄호 안으로 제한된다.

반복 변수의 값을 반복문이 종료된 뒤에도 써야 하는 경우가 아니라면 while문보다 for문을 사용하는 것을 권장하고 있다.

1
2
3
4
5
6
7
8
9
10
Iterator<Element> i = c.iterator();

while (i.hasNext()) {
	doSomething(i.next());
}

Iterator<Element> i2 = c2.iterator();
while (i.hasNext()) {
	doSomething(i2.next());
}
  • 위 코드는 for문이 더 나은 경우를 보여주는 예시이다.
  • 단순히 복사 붙여넣기를 하다가 실수로 새로운 iterator를 쓰지 않고 이전 iterator를 그대로 사용한 것이다.
  • i는 여전히 유효하기 때문에 에러가 나지 않아 찾기 힘들 수 있다.

이러한 실수는 for문을 이용하면 컴파일 타임에 잡아낼 수 있다.

1
2
3
4
5
6
7
8
9
for (Iterator<Element> i = c.iterator(); i.hasNext();) {
	Element e= i.next();
	//...
}

for (Iterator<Element> i2 = c2.iterator(); i.hasNext();) {
	Element e2= i2.next();
	//...
} //컴파일 에러!
  • for문을 사용하는 경우에는 i가 이전 for문에서만 유효한 범위에 있기 때문에 그 코드를 복사해 수정한 i2 코드에서는 i를 찾을 수 없다는 컴파일 에러를 내게 된다.
  • 또한 for문은 변수 유효 범위가 for문과 일치하기 때문에 같은 이름의 변수를 다른 반복문에 써도 된다.
  • for문은 while문보다 짧아 가독성 또한 뛰어나다.
1
2
3
for (int i = 0, n = expensiveComputation(); i < n; i++) {
	//...
}
  • for문의 또다른 장점이다.
  • 변수 i의 한계값을 n에 저장한다.
    • 반복때마다 다시 계산하는 비용을 없앤다.
    • 같은 값을 반환하는 메서드를 매번 호출하게 되는 경우 이러한 관용구를 사용하는 것을 권장한다.

메서드를 작게 유지하고 한 가지 기능에 집중하기

하나의 메서드에서 여러 기능을 처리한다면 그 중 한 가지 기능과 관련된 지역변수라도 다른 기능을 수행하는 코드에서 접근할 수 있게 된다.

메서드를 기능별로 쪼개면 해당 기능에만 사용되는 지역변수들만을 선언할 수 있고, 혼동되는 일이 없을 것이다.

정리

아이템 15처럼 지역변수의 범위를 최소화하는 것은 코드 가독성, 관리, 오류 발생 가능성 줄이기 등에 이점을 가져다준다.

최소화하는 방법으로는 처음 쓰일 때 선언하고, 메서드를 작게 유지하는 것이다.

기본적인 내용일 수 있지만, 인지하고 신경쓰는 것과 아닌 것의 차이는 명확하다고 생각한다.

또한 while문 대신 for문을 이용하는 것이 더 나은 이유를 알 수 있었다.

This post is licensed under CC BY 4.0 by the author.

Item56 (공개된 API 요소에는 항상 문서화 주석을 작성하라)

Item58 (전통적인 for문보다는 for-each문을 사용하라)