도당탕탕

Item57 : 지역변수의 범위를 최소화하라 본문

JAVA

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

backlo 2023. 1. 12. 11:17

지역변수의 유효 범위를 최소로 줄이면 코드 가독성과 유지보수성이 높아지고 오류 가능성은 낮아진다.

지역변수 초기화

자바에서는 문장을 선언할 수 있는 곳이면 어디서든 변수를 선언할 수 있다. 이렇기에 지역변수의 범위를 줄이는 가장 강력한 기법은 역시 가장 처음 쓰일 때 선언하기이다.

만약 사용하려면 멀었는데, 미리 선언부터 해두면 코드가 어수선해져 가독성이 떨어진다. 변수를 실제로 사용하는 시점엔 타입과 초깃값이 기억나지 않을 수도 있다. 그리고 지역변수를 생각 없이 선언하다 보면 변수가 쓰이는 범위보다 너무 앞서 선언하거나, 다 쓴 뒤에도 여전히 살아 있게 되기 쉽다.

또한 거의 모든 지역변수는 선언과 동시에 초기화해야 한다. 초기화에 필요한 정보가 충분하지 않다면 충분해질 때까지 선언을 미뤄야 한다.

try-catch

하지만 try-catch문은 이 규칙에서 예외이다. 변수를 초기화하는 표현식에서 검사 예외를 던질 가능성이 있다면 try 블록 안에서 초기화해야 한다. 한편, try 블록 바깥에서도 사용해야 한다면 try 블록 앞에서 선언해야 한다.

반복문

반복문은 블록 안의 독특한 방식으로 변수 범위를 최소화해 준다. 그렇기 때문에 반복 변수의 값을 반복문이 종료된 뒤에도 써야 하는 상황이 아니라면 while문보다는 for 문을 쓰는 편이 낫다. 다음 예를 보자.

  • 컬렉션이나 배열을 순회하는 권장 관용구
for (Element e : C) {
    // e로 무언가 한다.
}

만약 반복자를 사용해야 하는 상황이라면 다음과 같이 사용하면 된다.

  • 반복자가 필요할 때의 관용구
for (Iterator<Element> i = c.iterator(); i.hasNext(); ) {
    Element e = i.next();
    ... // e, i로 무언가 한다.
}

또한 다음 예제를 보면 while문 보다 for문을 사용하는 게 좋다는 것을 보여주는 예이다.

  • while 문의 문제
Iterator<Element> i = c.iterator();
while(i.hasNext()) {
    doSomething(i.next());
}
...

// 복사 붙혀넣기한 코드
Iterator<Element> i2 = c2.iterator();
while(i.hasNext()) { // 버그
    doSomething(i.next());
}
...

이런 식으로 복사 붙여 넣기를 통해 버그가 생길 수 있다. 최악으로 런타임시 버그를 찾지 못해 제대로 동작하고 있다고 착각하게 만들 수 있다. 따라서 for문을 사용하면 위 문제를 해결할 수 있다.

  • for문 사용
for (Iterator<Element> i = c.iterator(); i.hasNext(); ) {
    Element e = i.next();
    ... 
}

// i를 사용하면 찾을 수 없다는 컴파일 에러 발생
for (Iterator<Element> i2 = c2.iterator(); i.hasNext(); ) {
    Element e = i2.next();
    ... 
} 

for 문이 복사해 붙여 넣기 오류를 줄여주는 이유는 또 있다. 변수 유효 범위가 for문 범위와 일치하여 똑같은 이름의 변수를 여러 반복문에서 써도 서로 아무런 영향을 주지 않는다.

마지막으로 for문의 장점 또 하나를 말해보자면, 바로 while 문보다 짧아서 가독성이 좋다는 점이다. 다음은 예를 보자.

  • 지역변수의 범위를 최소하하는 또 다른 관용구
for (int i = 0, n = expensiveComputation(); i < n; i++) {
    ... // i, n으로 무언가를 한다.
}

위 코드에서 i와 n을 통해 반복 여부를 걸정 짓는 변수 i의 한계값을 변수 n에 저장하여, 반복 때마다 다시 계산해야 하는 비용을 없앴다. 즉 같은 값을 반환하는 메서드를 매번 호출한다면 이 관용구를 사용하기 바란다.

지역변수 범위를 최소화하는 마지막 방법은 메서드를 작게 유지하고 한 가지 기능에 집중하는 것이다. 한 메서드에서 여러 가지 기능을 처리한다면 그중 한 기능과만 관련된 지역변수라도 다른 기능을 수행하는 코드에서 접근할 수 있을 것이다.

Comments