사내 Review 시스템 상에서 if 문 관련된 코딩 스타일에 대해서 의견을 확인하는 기회가 있었다. "처리할 것이 없는 데, 불필요하게 코드가 추가 되는 것이 아니냐?"라는 의견이 있어 다른 분들의 의견을 묻는 것이었다.


if ( a == b ) 
{
    a++;
} 
else
{ 
    /* do nothing */ 
}

이런 스타일에 부정적인 의견들은 다음처럼 나왔습니다.
  • 필요성을 못 느낀다. 따라서, 불필요한 코드가 많이 차지한다.
  • 신입 개발자들이 엄격한 코딩 스타일에 대한 거부 반응이 있다.
  • 엄격한 코딩 스타일때문에 자유로운 생각에 방해가 된다.
  • 깊은 수준의 indentation을 유발한다.

다음과 같은 긍정적인 의견들이 나왔습니다.
  • 실수를 줄이는 데 도움이 된다.
  • 가독성을 높여준다.
  • else { /* do nothing */ }을 보면 다시 코드를 의심하고 본다.

인원 수로 보면 저를 포함해서 긍정적으로 생각하시는 분들이 많았습니다.

어떻게들 생각하시나요?

C에서 실수를 줄이는 코딩 스타일

프로그래밍 2010. 1. 14. 22:42 posted by whiterock
프로그램의 소스 코드는 사람이 작성을 한다. 다른 작업들도 그렇겠지만, 사람들은 상황에 따라서 실수들을 종종한다. 따라서 실수를 가능한 하지 않게 여러가지 방법들을 이용하여 보완을 하는 게 현실이다. 경험적으로 C 언어를 종종 사소한 실수를 많이 했던 것들에 대해서 보완하는 방법 중 한가지가 코딩 스타일이다. 그 중 몇 가지를 정리를 해본다.

조건절 비교

조건절에서 상수 값과 변수의 값이 일치하는지 비교할 때, 대부분의 예제 코드들 보면 이런 스타일로 나온다.

[code c] if (a == 1) { a++; } [/code]


간혹 실수로 "==" 대신 "="를 쓰는 경우가 있다. 컴파일 옵션으로 경고 수준을 높이지 않으면 경고로도 나오지 않는다. 경고 수준을 높이고 가능한 모든 경고는 제거하는 습관은 말 안해도 기본이다.

이 경우는 다음과 같은 스타일로 코딩을 하면 실수를 문법 에러로 잡아낼 수 있다.

[code c] if (1 == a) { } [/code]

if .. else .. 문

디버깅을 하다 보면 심심치 않게 실수를 하게 되는 부분이 if ... else ... 관련된 부분이다. C언어 메뉴얼에서도 if else 관련 주의 사항으로 {} 없는 경우에 대한 얘기가 나온다. 수 많은 코드를 눈으로 그냥 훑고 지나가다 보면 모양만 유심히 보다가 놓치게 되는 경우가 많다. 다음 경우 같은 경우가 되겠다.

[code c] if (1 == a) a++; a++; [/code]

그리고, 디버깅하다가 간혹 보게되는 실수인 경우가 조건을 만족하지 않았을 때, 해줘야 할 것들을 빠뜨리는 경우가 있는 것을 보게 된다. 그래서 거짓일 때 처리할 게 없다는 것을 명확히 표시를 해 주는 것도 실수를 줄이는 데 도움이 된다.

그래서 if 문 관련 코딩 스타일로 다음 형태로 명확하게 블럭으로 묶어 주고, 처리할 게 없다는 것을 명확하게 표시를 해준다.

[code c] if (1 == a) { a++; } else { /* do nothing */ } [/code]

Return 값 처리 무시 표시

라이브러리들의 함수들을 보면 대부분 처리 결과에 따라 Return 값을 넘겨준다. 이런 결과들을 제대로 처리를 해주는 것 또한 튼튼한 프로그램을 만드는 것에 대한 기본이다. 그러나 때로는 실행에 별다른 영향이 없어서 이 Return 값을 무시할 수 도 있다. 그래서 의도적으로 무시를 한다는 표시로 (void)를 함수 앞에 붙여준다.

[code c] (void)close(fd); [/code]

( )를 이용하여 명확한 연산자 우선 순위 표시

10년 넘게 C 언어를 사용해 왔지만, 아직도 연산자 우선 순위가 아리까리 하다. 간혹 이런 연산자 우선 순위를 잘 못 알고 있어, 디버깅 하다 보면 의도하지 않게 동작하는 코드들을 종종 만나기도 한다. 그래서 가장 높은 우선 순위를 가진 ( )를 이용하여 명확하게 한다.

[code c] a = (a + (a * 2)) / 2; [/code]


그 외에도 더 있겠지만, 지금 생각나는 것들만 정리를 해보았다. 핵심은 명확하게 표현을 하는 것이다.
지금 회사에서는 함수 안에서 return 문을 딱 2개만 쓸 수 있게 코딩 스타일로제한을 했다. 그래서 대부분 구현된 함수 구조를 보면 다음과 같다.

function( ) 
{ 
    /* 로직 구현 부분 */ 

    return 성공을 나타내는 코드; 

    /* 예외 처리 부분 */ 

    return 에러를 나타내는 코드; 
}

이런 형태로 제약을 하면서 실행 흐름을 단순하게 하여 가독성을 높이고, 버그를 줄이는 효과가 있다.

이런 형태로 구현될 수 있게 도와주는 예외 처리를 위한 매크로들이 있는데, 자세한 내용은 다른 포스트로 정리를 하겠다. 예외 상황 조건을 충족하면 예외 처리 부분으로 넘어가게 goto 문을 이용한 매크로라는 것만 알면 된다.