6. 변수와 가독성
변수를 엉터리로 사용하면 코드를 이해하기 어려워 지는 커다란 이유는 아래와 같다
■ 변수의 수가 많을수록 기억하고 다루기 더 어려워진다.
■ 변수의 범위가 넒어질수록 기억하고 다루는 시간이 더 길어진다
■ 변수의 값이 자주 바뀔수록 현재값을 기억하고 다루기가 더 어려워진다.
이러한 문제를 해결하기 위하여...
변수 제거하기
가독성에 도움이 되지 않는 변수를 제거하는 방법들
■ 불필요한 임시변수
1 2 | now = datetime.datetime.now(); root_message.last_view_time = now; | cs |
위 코드에서 now변수는 꼭 필요한가? 그렇지 않다. 이유는
- 복잡한 표현을 잘게 나누는 것이 아니다
- 명확성에 도움이 되지 않는다 datetime.datetime.now는 그 자체로도 명확하다
- 한 번만 사용되어 중복된 코드를 압축하지 않는다
now가 없다하더라도 코드를 이해하는데 아무린 지장이 없다.
1 | root_message.last_view_time = datetime.datetime.now(); | cs |
now의 경우 남겨진 쓰레기 같은 존재가 된다. 프로그래머 입장에서는 어디선가 사용하겟지 라고 생각하고 만들엇지만 실제론 전혀 사용되지 않는다.
■ 중간 결과 삭제하기
1 2 3 4 5 6 7 8 9 10 11 12 13 | var remove_one = function ( array, value_to_remove ){ var index_to_remove = null; for( var i = 0; i < array.length; i+= 1 ){ if( array[i] === value_to_remove ){ index_to_remove = i; break; } } if( index_to_remove !== null ){ array.splice(index_to_remove, 1); } } | cs |
이 코드에서 index_to_remove는 불필요하게 값을 가지고 있는 셈이 된다
이런 녀석은 굳이 따로 값일 가지는게 아니라 그 자리에서 바로바로 지워주는 게 좋다
1 2 3 4 5 6 7 8 9 | var remove_one = function ( array, value_to_remove ){ var index_to_remove = null; for( var i = 0; i < array.length; i+= 1 ){ if( array[i] === value_to_remove ){ array.splice(i,1); return; } } }; | cs |
불필요한 변수를 사용해 코드를 복잡하게 하는 것 보다 이렇게 최대한 함수를 빨리 반환하는 게 좋다
■ 흐름 제어 변수 제거하기
1 2 3 4 5 6 7 | boolean done = false; while( /* 조건 */ && !done ){ if( ... ){ done = true; continue; } } | cs |
이런 식으로 반복문을 강제로 빠져나가게 하거나, 유지시키기 위해 사용하는 변수를 흐름제어 변수 라고 한다.
하지만 이런 녀석은 전혀 필요없다. 실제 데이터도 저장하지도 않는다!!
이런 흐름 제어 변수는 프로그램의 구조를 잘 설계하면 제거할 수 있다.
1 2 3 4 5 | while( /* 조건 */ ){ if( ... ){ break; } } | cs |
중첩된 여러 루프 때문에 break가 추가로 필요하게 될 경우엔 루프안에서 반복되는 행동을 새로운 함수로 만들면 된다.
■ 변수의 범위를 좁혀라
전역변수를 피하라
전역 변수는 어디에서 어떻게 사용되는지 일일이 확인하기 어렵기 때문이다.
전역 변수의 이름과 지역 변수의 이름이 중복되어 네임스페이스가 더러워 질 수도 있다.
모든 변수의 범위를 좁히는 일은 언제나 좋다!
왜냐하면 코드를 읽는 사람이 한꺼번에 생각해야 하는 변수 수를 줄여주기 때문이다.
모든 변수의 범위를 두 배로 축소시키면 한 번에 읽어야 하는 변수의 수는 평균적으로 반으로 줄어든다.
많은 메소드를 정적 static으로 만들어서 클래스 멤버 접근을 제한해라
- 정적 메소드는 읽는 사람으로 하여금 이코드는 저 변수들로부터 독립적이구나 라는 인식이 생긴다
커다란 클래스를 여러 작은 클래스로 나누는 방법
- 작은 클래스 들이 서로 독립적일 경우 매우 유용하다.
이러한 행위를 하는 이유는 변수를 서로 분리시켜 햇갈림을 방지하기 위함이다.
원래의 C 프로그래밍 언어는 모든 변수의 정의가 함수나 블록의 윗부분에서 이루어 진다.
이러한 방식은 특히 많은 변수를 가지고 있는 긴 함수 일 때 코드를 읽는 사람에게 지금 당장 사용되지 않는 변수조차 일단 염두에 두게 강제하는 방법 이므로 매우 좋지 않다.
1 2 3 4 5 6 7 8 9 10 11 | def ViewFilteredReplies(original_id): filtered_replies = []; root_message = Message.objects.get(original_id); all_replies = Message.objects.select(root_id=original_id); root_message.view_count += 1; root_message.last_view_time = datetime.datetime.now(); root_message.save(); for reply in all_replies: if reply.spam_votes <= MAX_SPAM_VOTES; filtered_replies.append(reply) return filtered_replies | cs |
이런 코드는 읽는 사람으로 하여금 하꺼번에 세 개의 변수를 생각하게 하면서 그 사이에서 왔다갔다 하게 만드는 문제가 있다.
제각각 사용하기 직전의 위치에 두는게 좋다.
1 2 3 4 5 6 7 8 9 10 11 | def ViewFilteredReplies(original_id): root_message = Message.objects.get(original_id); root_message.view_count += 1; root_message.last_view_time = datetime.datetime.now(); root_message.save(); all_replies = Message.objects.select(root_id=original_id); filtered_replies = []; for reply in all_replies: if reply.spam_votes <= MAX_SPAM_VOTES; filtered_replies.append(reply) return filtered_replies | cs |
■ 값을 한 번만 할당하는 변수를 선호하라
변수들의 값이 너무 유동적으로 변화 한다면 프로그램을 따라가는 일은 더욱 어려워 진다.
최대한 적은 횟수로 변하게 하는 것이 좋다.
const,final등을 추천한다