Technique/Readable Code

6. 변수와 가독성

kaelina 2015. 12. 10. 22:24
반응형

변수를 엉터리로 사용하면 코드를 이해하기 어려워 지는 커다란 이유는 아래와 같다


■ 변수의 수가 많을수록 기억하고 다루기 더 어려워진다.

■ 변수의 범위가 넒어질수록 기억하고 다루는 시간이 더 길어진다

■ 변수의 값이 자주 바뀔수록 현재값을 기억하고 다루기가 더 어려워진다.


이러한 문제를 해결하기 위하여...


변수 제거하기

가독성에 도움이 되지 않는 변수를 제거하는 방법들

■ 불필요한 임시변수

 

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;
    forvar 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;
    forvar 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등을 추천한다 


반응형