2012년 3월 1일 목요일

코딩스탠다드, 정말 이리 빡셀 필요있나?


이젠 피할 수 없는 진실이 되고 말았습니다. 사실 실력도 좋은데... 워낙 꽃미남이 되어놓으니... 비주얼로 자꾸 기억해주시는군요.... 뭐 사실은 사실 겸허하게 받아들이겠습니다... -_-

거부할 수 없는 진실은 힘들다.. 어쩌지 이제 잡지 표지모델 제의도 들어오는데...



왠만한 게임 회사에는 프로그래머가 준수해야하는 코딩스탠다드(코딩 스타일이라고도 하죠)가 있는 것 같습니다. 제가 여태까지 프로그래밍을 해오면서도 상당히 많은 코딩 스탠다드들을 봤는데요  (수백만장씩 팔린 패키지 게임에 사용한 엔진만도 5~6개 만져봤으니 뭐 온갖 꼴은 다 봤죠) 요즘들어 코딩스탠다드가 정말 이렇게 빡셀 필요가 있나 하는 의문이 들고 있답니다. (잡생각이 많죠.. 때로...)

우선, 대충 배경지식..... 코딩스타일에서 정의하는 것은 대충 다음과 같습니다.
  • 인덴테이션/줄바꿈
  • 빈칸의 사용
  • 변수이름 짓는 법
  • 함수이름 짓는 법
  • 주석다는 규칙
  • 등등...

코딩스타일의 존재이유?
결국 코딩스타일을 강제함으로 인해 회사에서 얻으려고 하는 건 가독성입니다. 코드 스타일을 통일시키면 다른 프로그래머의 코드를 읽을 때 쉽게 이해할 수 있고, 따라서 생산성을 높일 수 있다는 미신적인 믿음이 존재하죠.

이렇게 하면 프로그래머의 생산성이 높아진다는 부두교의 미신이 있다..... (믿거나 말거나)


코딩 스타일에서 정의하는 것들의 예
우선 코딩 스타일의 예부터.....

인덴테이션/줄바꿈
다음 형태 중에 어떤 놈을 이용할까? 하는 고민...

a)
for ( int i = 0; i < 10; ++i ) {
  sum += i;
}

b)
for ( int i = 0; i < 10; ++i )
{
    sum += i;
}

c)
for ( int i = 0; i < 10; ++i )    sum += i;


등등

빈칸(white space)의 사용
대충 이런 것들 중에 어떤 놈을 써야하는지...

a)
int a = c * ( d + e );

b)
int a=c*(d+e);

등등

변수이름 짓는 법
단어별 대소문자, 멤버변수앞에 m 접두어를 붙이는지 등등...

a)
mMemberVariable = temp_variable * 2.0f;

b)
MemberVariable = tempVariable * 2.0f;

등등

함수이름 짓는 법
단어별 대소문자, private, public 대소문자 등등

a)
int MyClass::getNumPrivate();
int MyClass:GetNumPublic();
int do_something();

b)
int MyClass::_getNumPrivate();
int MyClass:getNumPublic();
int doSomething();

등등

주석다는 규칙
  • 클래스 선언 마다 주석을 달아야 하는가?
  • 함수 선언마다 주석을 달아야 하는가? 변수명 설명? 반환값 설명?
  • 그 외 어떤 코드에 주석을 달아야하는가?
  • 주석 달때 스타일은 어떤걸로? /* ... */,  //, ///, /**...**/ 등등
  • 기타 잡다한 것들...


하지만 의문이 들다
저도 좀 뭔가 깔끔하게 정리되어 있는 걸 좋아하는 놈이라 한동안 이런 미신에 푹 빠져살았습니다. 그런데 최근 몇 년 동안에 '정말정형화된 코딩스타일이 생산성을 향상시키나?'하는 의문이 들더군요. (물론 게임업계에 한정된 이야기입니다. 의료업계에서는 계속 빡세게 해주세요... 수술대 올라갔다가 버그 때문에 뻗은 기계 대문에 죽긴 싫습니다... -_-)

사실 코딩 스타일이란게 종교와도 같은 것이어서 이렇다 할 정답이 없습니다. 프로그래머 10명 잡고 물어보면 다들 선호하는 코딩 스타일이 다릅니다. 일례로 함수이름만 들어도 어떤 프로그래머는 private함수는 getNum() 이란식으로 작성하고 public 함수는 GetNum()이라고 작성하자고 하는 반면 다른 프로그래머는 get_num()과 GetNum()이라고 하자고도 할 겁니다.

어차피 회사란 집단체니까 그냥 일률적으로 정해놓고 프로그래머들을 다 강요하면 된다고 생각하는 건데... 정작 문제는 이 스타일로 개종해야하는 사람들에게는 이게 오히려 생산성 저하의 요소가 됩니다.

중요한건 프로그래머의 상식/배려/역량
그리고 참 웃겼던건.. 제가 지금까지 함께 작업했던 프로그래머만 해도 수백명인데... 그리고 이 엔진 저 엔진 옮겨다니면서 거친 코딩 스탠다드만도 대여섯은 될텐데..... 코딩 스탠다드하고 가독성은 정말 별 상관이 없었단 겁니다. 그보다는 오히려 어떤 코딩 스타일을 사용하던 간에 깨끗한 코드를 작성할 수 있는 프로그래머의 역량이 더 중요하더군요. 이런 분들이 대부분 이었습니다. 즉 굳이 코딩 스탠다드가 필요없는 인간들이 대부분...

회사에서 아무리 철저한 코딩 스탠다드를 만들어 놓아도 코드 드럽게 쓰는 애들(소수에 그칩니다)은 여전히 코드 이해 안되게 쓰더군요. 그래서 이런 애들을 좀 더 잘 관리하려고 코딩 스탠다드에 규칙을 더 추가합니다. 이러면 얘네들이 좀 나아질까요? 아닙니다. 얘네들이 코드가 드러운 이유가 있습니다. 남생각을 별로 안하거든요. 규칙이 얼마나 철저하던 간에 어떻게든 빠져나갑니다. 그 덕에 오히려 원래부터 깔끔한 코드 쓰던 사람들만 고생하죠. 이 사람들은 악법도 법이라고 존중하고, 다른 프로그래머들도 배려할 줄 아는 분들이므로 새로 생긴 규칙에 맞게 또 열심히 코드를 작성합니다. 이 규칙 없어도 원래부터 이해잘되는 깔끔한 코드를 작성하던 사람들인데 따라야 할 규칙만 늘어버렸죠. 

이게 배려라는 거다....  밥그릇 까지도 깔끔하게... (이미지 출처: http://garul.tistory.com)

결국 제값주고 산 놈들만 손해란 건가?
이렇게 생각을 하다보니.... 꼭 게임에 DRM 입히는거와 마찬가지란 생각이 들더라구요. DRM을 아무리 빡세게 입혀도 해적질 할 애들은 다 해적질하고 쓰니 아무 상관없는데, 정가내고 산 사람들만 그 DRM에 얽매여서 온갖 귀찮은 일을 다 당해야 하는....

해석은 귀찮으니 생략..... 그림만 봐도 대충 뭔 귀찮은 일을 당하는 지 알거다...


차라리 개별적으로 갈구자. 짜르던가. 칼부림도 가끔?
결국 제가 내린 결론은 저희가 너무도 당연하게 여기며 쓰던 코딩 스탠다드가 생각보다 별로 효과적이지 않단 겁니다.

물론 코딩스탠다드를 싸그리 없애자는 건 아닙니다. 좀 최소한으로 줄이자는 거죠. 그리고 코드 드럽게 쓰는 애들을 개별적으로 갈궈서 좀 고치게 하던가... (인간이 직접 갈구는게 문서 던져주고 따라하라는 것보다 훨씬 효율적입니다... 칼부림이 가끔 날 뿐이지... -_-)...... 안되면 그냥 짜르던가....

이런 생각을 하게 된 또 다른 계기는 게임업계가 엄격한 코딩스타일이 필요한 분야가 아니란 겁니다. 어차피 코드작성한 건 다 내부적으로 쓰는거고, 문제 있으면 소스코드가 다 떡하니 있으니 아무나 가서 고칠 수 있으니까요. 게임업계가 아니라 미들웨어를 만들어서 판매하는 회사라던가 군사업체 및 의료장비에 들어가는 소프트웨어를 만드는 회사에서는 이게 좀 더 엄격해야겠죠. 미들웨어 회사는 라이브러리만 던져주는 경우가 많으니 그렇고, 군사업체 및 의료장비는 사람 생명이 걸린 일이라서 어쩌다 뭔 짓을 하더라도 버그를 아예 처음부터 만들지 않는게 중요하니까요. 어차피 게임이 엔터테인먼트 산업이고, 게임의 요구사항은 하루가 멀다하고 바뀌므로 차라리 유연하게 재빨리 코드를 작성할 수 있는게 게임 품질 향상에 더 기여한다고 봅니다. 게임의 품질이란건 사실 게이머가 느끼는 품질일 뿐이거든요. 인간의 목숨이 걸린 의료소프트웨어에서의 품질하고는 전혀 다르죠.

그냥 이정도면 하면 안될까요?
그래서 과연 '코딩스탠다드를 어디까지 줄일 수 있을까?' 하는 걸 좀 생각해봤죠. 이게 좀 간단해야 정작 남 배려할 줄 아는 프로그래머의 인생도 편해지지 않을까 해서....

나도 좀 단순히 편하게 살고 싶다... 물론 패리스 힐튼과 함께.... 근데 토토샵 질이 좀 심한데? -_-

위에서 들었던 목록을 한번씩 살펴보면서 이야기하죠.

인덴테이션
코드의 가독성을 위해서는 여전히 중요하다고 생각합니다. 특히나 코드의 scope를 보여주는데 도움이 되니까요. 근데 이제 Visual Studio 가 이런 인덴테이션을 직접 알아서 해주므로 크게 걱정할 필요가 없습니다. 20년 전에 이런 게 자동으로 안될때나 문제였지...

빈칸사용
뭐 이건 사실 int k = a * ( b + c );로 해주냐 int k=a*(b+c);로 해주냐 차인데... 어떻게 쓰던 코드 이해하는데 별 차이가 없습니다.... 굳이 목숨 걸 필요 없지 않나요? -_-

변수명/함수명
일단 멤버변수 이름앞에 m을 붙이니 public 함수는 대문자로 시작하니 마니 하는 건 이젠 별 의미가 없는거 같습니다. 어차피 IDE가 워낙 좋아져서 그냥 마우스만 올려도 나오는 경우가 많고 아니면 F12키 한번 누르면 곧바로 선언된데로 이동하니까요. 그리고 다시 돌아올땐 Ctrl + -키 누르면 끝이고... Visual Studio의 인텔리센스가 잘 작동안하면 Visual Assist 를 깔아도.....

단, 가독성을 위해 변수명이나 함수명을 잘 작성해주는 건 찬성입니다. 즉 int a = 1; 이라기보단 int numLoop = 1; 이란 식으로 변수명을 작성해주는거죠.. 딱 보면 이해가 되게... 함수명도 마찬가지고요.

주석다는 규칙
사실 주석달아야 할 곳에 안달아서 헷갈리는 경우도 많고, 달지 않아도 될 곳에 달아서 오히려 코드만 지저분해지는 경우 허다하죠... 이건 사실 어떻게 정의해도 코드 드러운 애들은 여전히 드럽고 코드 깔끔한 분들은 여전히 깔끔한.. 그런 부분...

저 개인적으로는
  1. 클래스 이름만 잘 정하면 굳이 클래스마다 주석을 달 필요가 없다. 이름보고 이해안될때만 기재.
  2. 함수/변수 이름만 잘 정하면 굳이 함수/변수마다 주석을 달 필요가 없다. 이름보고 이해 안되거나 변수의 반환값이 기묘할 떄만 기재.
  3. 코드에서 곧바로 이해되면 주석은 필요없다.
  4. 옆에 앉은 놈이 코드만 보고 곧바로 이해가 안되면 코드블럭 별로 그 위에 주석으로 기재
정도가 젤 난거 같습니다.


대충 정리
이렇게 써보고 보니 결국 제가 괜찮다고 생각하는 법은 코딩 스타일의 통일성을 유지하려고 괜히 쓸데없는 규칙을 만드는 대신에 개발자들의 상식을 믿으란 쪽이 되어버린듯...

어쨌든 제가 좋다고 생각하는 코딩스타일은 이것 정도입니다.
  • 변수명/함수명에 의미를 담을것
  • 코드의 스코프를 보여주기 위해 인덴테이션을 잘 할 것
  • 동료 프로그래머가 코드에서 곧바로 이해못할 만한 내용이면 코드 블럭 위해 간단히 주석을 달 것

개종 안하셔도 되요~
뭐, 다들 이러세요~ 라는 걸로 쓴 글은 아니고.... 그냥 한 번 생각해보시라고... 그리고 토론 좀 해보잔 의도로... (어차피 종교적인 토론이라... 난장판이 될 가능성이 높지만...-_-)







댓글 4개:

  1. http://blog.dahlia.kr/post/18035893350

    개인적으로는 작성 의도만 주석으로 남기고 나머지는 읽기 쉬운 코드로만 쓰면 무슨 상관이겠느냐, 이런 생각입니다만 그래도 위 링크 같이 코딩 컨벤션을 맞추는게 실용적인 상황이 있기도 합니다. 밸런스를 잘 맞추는게 중요할 듯 하네요.

    답글삭제
    답글
    1. 뭐 개발환경이 저렇다면야 뭐 저런 거엔 반대안하죠. 근데 제가 쓰는 Diff 프로그램은 전부다 whitespace를 무시하는 옵션이 있어서.... 저희쪽 개발환경에서는 별 의미가 없어요.

      아.. 생각해보니... python으로 작업한다면 scope를 바꾸는걸 tab으로 할거냐 아니면 white space로 할거냐에 대한 규칙이 있긴 해야겠네요... (제가 그래서 python을 별로 안좋아함... 그래도 반드시 써야한다면 쓰죠.....)

      삭제
  2. 헝가리안 표기법은 현업에서 잘 안쓰이나요? 이번에 NDC 갔다왔는데 거기 강연하신 분께서 헝가리안 비웃으시던데...(나쁜의미가 아닌 조크정도로)

    답글삭제
    답글
    1. 곧이곧대로 쓰는 회사는 없는거 같아요.. 다 자기에 맞게 변형해서 쓰죠.. 일단 헝가리안 표기법이 IDE가 꽤 후졌던 80년대에 나온놈이라...

      멤버변수앞에 m붙이는건 주로 하는거 같구요.. 클래스 앞에 c붙이는건 안하는 회사가 많고.. 등등이죠.... 전역변수앞에 g붙이느것도 많이봤고 static변수 앞에 s붙이는것도 종종 봤습니다.

      하지만 MSDN C# 예제를 보면 그런것조차 잘 안하니.. 점점 사라질듯해요.. IDE만 잘 지원해준다면 저런부분은 꽤 필요없다고 생각합니다...

      삭제