본문 바로가기

Java

[Java] for loop에서 카운터를 조작하지 맙시다.

간단한 소스를 보겠습니다.


어떤 문제가 보이시나요?

일단, 변수 i를 두개의 for문에서 조건 counter로 사용하고 있는 것이 보이실 것 입니다.
이런 경우 i를 여러 for문이 공유하게 되면 문제가 발생 할 가능성이 커지고
디버그 하기도 매우 어렵습니다.

일반적으로, 변수는 사용하기 바로 직전에 초기화 하는 것이 좋다고 하죠..
위와 같은 경우는
for(int i = 0; i< 10; i++) {
..
}
이렇게 되겠네요..

중요한 것은 여기서 얘기하고 싶은 것은 변수의 초기화 시점이 아닙니다.
i라는 변수는 for문에서 loop를 계속 돌릴지 빠져나갈지를 결정하는 제어변수로 사용되고 있습니다.
그런 변수 i를 for문 내부에서 임의로 값을 할당하여 변경하고 있습니다.

int result = getXXXXX();
i = result;

어떤 의도였는지 잘 모르겠지만 (위와 같은 소스의 문제점 중 하나가 바로.. 소스를 읽는 사람이 그 의도를 파악하기 어렵다는
것 입니다.)

아무튼 위와 같은 로직이 되어 있을 때 getXXXXX(); 메서드가 0을 리턴하면 어떤 일이 벌어질까요?

실제로 전체 800라인이 넘어가는 메서드 안에
저렇게 i를 공유한 for문이 6개 정도 있는 클래스가 있었습니다.

어디선가 무한루프가 돌아가는데
메서드의 크기도 길고
하나의 for문 자체도 길다보니 실제 개발을 한 사람도 2-3시간 동안
원인을 찾지 못 하고 있었습니다.

개발 해 놓고 1-2주 지나면.. 또 금새 가물가물한 것이 인지상정 --;

몇 가지 원칙을 가지고 보면 대략 문제가 될만한 곳이 보입니다.

1. for문에서 카운터 i를 다른 for문과 공유하지 말 것.
2. 사용하기 바로 직전에 초기화 할 것.
3. 카운터 i를 for문 로직안에서 변경하지 말 것. (특정 조건에 의해 loop를 빠져나가야 한다거나 한다면, for문 대신 while문을 고려해 볼 것)
4. loop의 길이는 한페이지에 다 보일 수 있을 정도의 길이를 유지하도록 노력 할 것.


위 내용은 effective java나 code complete와 같은 책에 항상 나오는 내용입니다.

실제로 3번을 지키지 않아 무한 로프가 돌고 있는 메서드였으며
이것을 찾아내는데 10분도 걸리지 않았습니다.

요즘 이클립스등 개발 툴이 좋아져서 보고 싶은 변수 찍으면 어디어디에 사용되고 있는지
다 나오니까.. 더 쉽죠..