(코드 컴플리트2) 10장 변수 사용 시 고려할 사항 - 2

2021. 11. 30. 15:00독서

반응형

코드 컴플리트 10장에서 우리는 '변수'에 대해 알아보고 있었고, 

이 글은 변수의 범위부터 시작한다.

📕 선생님, 범위는 어디까지예요??!!


책은 변수의 '범위'를 변수의 명성이라고 말한다.

인기 스타를 상상해보자.

티비의 이 채널에도 나오고, 저 채널에도 나오면 유명하다고 할 수 있지 않을까?

 

변수도 그런 셈이다. 

이 루틴에도 나오고, 저 루틴에도 나오고, 코드 상단에 선언돼서, 하단에 가서도 사용되는 것이 명성이라고 생각한다.

 

그럼 이 범위를 왜 나눠야 할까?

예전 원시적인 언어에서는 모든 변수가 전역 변수였다.

모든 변수가 전역 변수이면 변수가 프로그램이 종료될 때까지 메모리를 점유하고 있고,

개발 중 여러 실수를 유발할 수 있는 문제점들을 안고 있는 등 여러 문제가 발생했다.

 

현재 C++, 자바에는 변수를 범위별로 나눌 수 있지만, 그럼에도 변수의 범위 때문에 여러 문제가 발생하곤 하는데,

이런 문제에 대한 해결책을 책에서 제시하고 있다.

 

 

📕 변수에 대한 참조를 지역화하라


1부의 내용과 일맥상통하는 말처럼 들린다.

변수를 수정할 때, 다른 변수에 영향을 주지 않으면서 최대한 가깝게 두라는 말로 이해하면 편할 것 같다.

// 변수 범위에 대한 자바 예제
a = 0;
b = 0;
c = 0;
a = b + c;


// 범위가 1과 0인 자바 예제
a = 0;
b = 0;
c = 0;
b = a + 1;
b = b / c;

 

변수 참조 사이에 있는 코드를 '취약한 구간'이라고 부른다.

첫 번째 코드의 경우 a의 범위는 2이며, 두 번째 코드의 b에 대한 참조는 각각 1과 0이다.

 

그럼 왜 범위가 짧은 것이 좋을까?

책에서는 변수에 대한 참조를 가깝게 유지하면 코드를 보는 사람이 한 번에 한 영역에 집중할 수 있다고 말한다.

즉, 가독성에 도움을 주기 때문이다.

 

코드를 작성하면서 '이 변수가 마지막으로 값이 변경된 때가 언제이지?' 하면서 찾아본 경험이 한 번쯤은 있을 것이다.

(없으면 말고) 위의 작성방법을 습관화하면 이러한 문제가 발생할 가능성이 많이 줄어들 것으로 기대된다.

 

 

📕 일찍 소멸하면 이득 💰


기계를 생각하면 튼튼하고 오래가면 더 좋은데,

변수는 아니다. 오래 살아남을수록 우리의 메모리를 갉아먹기 때문이다.(다른 문제가 훨씬 크다.)

 

변수의 수명을 낮추면 얻을 수 있는 이점이 뭘까?

  1. 취약구간을 줄일 수 있다.
  2. 코드를 쉽게 이해할 수 있다.
  3. 초기화 오류가 발생할 가능성을 줄여준다.
  4. 코드의 가독성이 높아진다.
  5. 큰 루틴을 작은 루틴으로 나눌 때 유용하다.

왜 다음과 같은 이점이 도출되는지는 조금만 깊게 생각해보면 답을 알 수 있다.

(스스로 생각해보자.)

 

 

📕 어떻게 하면 범위를 최소화할 수 있나요?


책에서는 여러 가지 방법을 제시하고 있다.

변수 초기화의 위치, 변수를 그룹별 분리 등등.

이 중에서 가장 와닿았던 부분은 처음에는 범위를 최대한 제한하고 필요한 경우에만 변수의 범위를 늘리는 것이다.

작성부터 변수의 범위를 최소화하면서, 변수를 가능한 지역화하는 것은 다 작성하고 나서 범위를 줄이는 것보다

훨씬 간편하다. (영화 대본도 작성하고 줄이는 것이 어렵듯이)

 

하지만 이렇게 변수의 범위를 최소화하는 것이 항상 옳지는 않다.

어떤 개발자들은 변수의 범위를 제한해서 이점이 더 많다고 생각하고,

어떤 개발자들은 전역 변수로 사용해서 코드 작성의 편의성에서 오는 이점이 더 낫다고 말한다.

 

'좋은' 코드의 기준에 '가독성'이라는 항목이 반드시 들어간다면,

변수의 범위를 제한하여 코드를 작성하는 게 좀 더 일롭지 않을까 생각한다.

 

 

📕 지속성


변수는 여러 가지의 지속성을 가질 수 있다.

  • 특정한 코드 블록이나 루틴에서만 살아있는 경우.
  • 특정 기간만 살아있는 경우.
  • 프로그램이 종료할 때까지 살아있는 경우.
  • 영원히 살아있는 경우. (데이터베이스에 저장한 값)

 

때에 따라 변수는 다른 지속성을 가져야 하고, 왜 그래야 하는지를 위에서 살펴보았다.

변수의 지속성 때문에 발생할 문제점을 피하기 위한 방법을 다음과 같이 제시한다.

 

  • 중요한 변수가 적절한 값을 갖는지 검사하기 위해서 프로그램에 디버그 코드나 어설션을 사용한다.
  • 변수를 사용하고 나면 그 변수를 '부적절한 값'으로 설정한다.
  • 데이터가 지속적이지 않다고 가정하는 코드를 작성한다.
  • '모든 데이터를 사용하기 바로 직전에 초기화하는 습관을 들인다.

 

📕 내 역할은 오직 하나!


 

변수를 한 가지 목적으로만 사용하자.

코드를 작성하다 보면, i, j , k를 누산으로 사용하는가 하면 어떤 값을 담을 때 사용하는 경우가 있다.

가장 흔히 할 수 있는 오류를 책에서 보여준다.

// 근의 공식
temp = sqrt(pow(p,2)-4*a*c);
root[0] = (-b + temp) / (2 * a);
root[1] = (-b - temp) / (2 * a);

...

temp = root[0];
root[0] = root[1];
root[1] = temp;

 

temp와 root는 어떤 관계가 있으며, 무슨 의미로 사용된 걸까?

살펴보면 아무 관계가 없다는 것과, 처음에는 결괏값을 담는 용도, 그다음은 값을 교환할 때 사용되는 임시 저장소 정도로 사용된 걸 알 수 있다.

이렇게 코드를 작성하면, 각각의 마치 두 변수가 서로 관련이 있는 착각을 불러일으키기도 한다.

그렇기 때문에 두 개의 변수에 나눠서 작성하면 훨씬 가독성 높은 코드를 작성할 수 있다.

// 근의 공식
discriminant = sqrt(pow(p,2)-4*a*c);
root[0] = (-b + temp) / (2 * a);
root[1] = (-b - temp) / (2 * a);

...

oldRoot = root[0];
root[0] = root[1];
root[1] = odRoot;

 

이 외에도 숨은 의미가 있는 변수를 피하고, 선언된 모든 변수를 사용하는지 확인한다면, 더욱 완성도 높은 코드를 작성할 수 있을 것이다.

 

 

반응형