안녕하세요, 개발자 윤진입니다.


코더로서 개발을 막 시작하고 얼마 후-

코딩컨벤션으로 개발자들끼리 핏대를 세워가며 언성을 높이는 것을 목격하였습니다.

당시에는 '간단한 함수의 경우 헤더에 함수를 정의해도 되는가'라는 주제로 피튀기게 양 진영이 거세게 싸웠는데요,

이후에 파일명, 함수명, 변수명의 이른바 '온갖 것에 대한 작명'에 대한 혈투가 개전되어, 모두가 가열차게 답메일을 보내 메일함이 폭발한 적이 있습니다.

그리고, 프로그래밍에서는 '작명'이 가장 어렵다는 결론을 내리며 훈훈하게 마무리되었죠.

'작명'이 가장 어렵다는 결론은 아직까지 유효합니다. :)

함수나 변수의 역할을 그 이름만으로 정확하게 파악할 수 있게 만드는 것은 프로그래밍의 영역이라기 보다는 예술의 영역에 가깝습니다.

그리고 이 영역에서 프로그래머의 센스와 자질이 드러나죠.


사실, 코딩컨벤션은 코드의 성능이나 안정성과는 거리가 멀지만,

코드독해에 직접적인 영향을 주는 요소입니다.

눈에 익숙하게 들어오는 코딩컨벤션이 아무래도 빨리 읽히는 법이죠.

그렇기 때문에 개발자들이 그렇게나 코딩컨벤션에 열을 올립니다.

코드는 짜고 난 뒤에도 수많은 개발자들에게 되풀이되며 읽히기 때문에, 개발자들의 원활한 정신상태를 위해 코딩컨벤션을 제대로 지켜줘야합니다.

개인적으로 일관성없는 코딩컨벤션으로 점철된 코드를 보면, 두통이 생기며 고치고 싶다는 욕망이 생깁니다.


C언어로 개발을 할 때는 기본적으로 linux_kernel_coding_style을 따랐습니다.

리눅스 스타일 문서에서는 작명에 대한 기준도 볼 수 있습니다.


4. 이름짓기 


C 언어는 간소한(Spartan) 언어이므로, 이름짓기 규칙도 이를 따라야 한다. Modula-2 나 파스칼 프로그래머와는 달리, C 프로그래머들은 ThisVariableIsATemporaryCounter 와 같은 귀여운(?) 이름을 사용하지 않는다. C 프로그래머들은 "tmp" 와 같이, 쓰기 쉽고 이해하기도 그리 어렵지 않은 이름의 변수를 사용할 것이다.

하지만, (대소문자를 섞어쓰는 것은 보기 안좋지만) 전역 변수에 대해서는 반드시 충분한 설명이 될 만한 이름을 붙여야 한다. 전역 함수의 이름을 "foo" 라고 짓는 것은 범죄 행위(shooting offense) 이다 (FIXME!)

전역 변수는 (정말로 필요한 경우에만 사용하자) 충분한 설명이 될 만한 이름을 가져야 하며, 이는 전역 함수에 대해서도 마찬가지이다. 만약 활동 중인 사용자의 수를 세는 함수를 작성했다면 이 함수의 이름은 "count_active_users()" 혹은 이와 비슷한 형태가 될 것이며, "cntusr()" 과 같은 형태가 되어서는 안 된다.

함수의 이름에 타입을 포함시키는 방식 ("헝가리안 표기법"이라고 한다) 은 멍청한 짓이다. 컴파일러는 타입을 알고 체크할 수 있으며, 이러한 표기법은 단지 프로그래머를 혼동스럽게 할 뿐이다. MicroSoft 에서 버그가 많은 프로그램들을 만들어 내는 것을 보면 당연하다.

지역 변수는 짧게 핵심만을 나타내는 이름을 사용한다. 만약 어떤 임의의 정수 루프 카운터가 필요하다면 그 이름은 "i" 가 될 것이다. 이를 "loop_counter" 라고 표기하는 것은 오해를 살 만한 여지가 없는 경우에는 생산적이지 않다. 마찬가지로, "tmp" 일시적인 값을 가지는 어떤 타입의 변수에도 사용될 수 있다.

혹시 여러분이 지역 변수 이름이 많아져 뒤섞이지 않을까 걱정하고 있다면, 여러분은 함수-성장-호르몬-불균형 증후군이라는 다른 문제를 가지고 있는 것이다. 6장 (함수) 부분을 보기 바란다.



C언어를 사용할때 대문자는 #define문 정도에서만 사용하였습니다.

온갖 이름은 소문자와 '_'(언더스코어)의 조합만으로 아름답게 명명되었죠.

함수나 변수도 그 적용범위에 따라 제각각의 작명법이 있었지만 모두 소문자와 '_'만으로도 충분했습니다.


그렇지만, C#의 세계에서는 C언어의 linux_kernel_coding_style은 '읽기 쉽지 않은' 코딩 컨벤션의 부류에 들어가더군요.

그 동안 줄곧 언더스코어의 세계에서 행복하게 살았는데,

C#의 세계에서는 (상대적으로 그리고 개인적으로) 읽기 번거로웠던 camelCase와 PascalCase의 세계에서 살아나가야 합니다.

이 세계에는 '_'는 죄악과 마찬가지입니다.


Capitalization Rules for Identifiers

To differentiate words in an identifier, capitalize the first letter of each word in the identifier. Do not use underscores to differentiate words, or for that matter, anywhere in identifiers. There are two appropriate ways to capitalize identifiers, depending on the use of the identifier:

  • PascalCasing

  • camelCasing


Microsoft의 코딩컨벤션 문서에서는 camelCase와 PascalCase를 읽기 쉽다고 콕 찝어 표현합니다.

Microsoft의 입장과 같은 맥락에서,

1) '_'로 단어간 구분한 문장과,

2) 대문자로 구분한 문장을 두고,

어느 쪽이 빨리 읽히는지 실험한 자료도 읽은 기억이 납니다.

그 때는 대문자로 구분한 문장이 더 빨리 읽혔기에 자바에서 camelCase를 선택했다고 주장하는 글을 읽은 기억이 있습니다.


하지만, 비교적 최근인 '10년에 Eye tracking으로 독해속도와 오타교정속도을 조사한 논문[각주:1]이 나옵니다.

이 논문은 과거에 읽었던 내용과는 상반되는 결론을 보여주는데요.

독해속도에서 with_underscore 표기법이 withoutUnderscore 표기법보다 무려 20% 정도나 빠르다고 합니다.

오타교정속도도 독해속도가 빠른 with_underscore 방식이 더 빨랐습니다.

Microsoft가 어떤 기준으로 camelCase나 PascalCase가 더 읽기 쉬운 코딩컨벤션으로 선택했는지 모르겠지만,

분명, 치밀하게 고민하고 결정했다고 생각합니다.


어느 코딩컨벤션이 더 좋든, 기본적으로 코딩컨벤션은 기존 코드에서 사용한 코딩컨벤션을 따라주는게 맞습니다.

만약 기존 코딩컨벤션이 정 맘에 안들면, 

해당 커미터들과 치열하게 싸워 결론을 내린 후,

코드 전체에 동일한 코딩컨벤션을 유지시켜면 됩니다.

실제로 이런 번거로운 과정을 거쳐, 자동화툴로 코딩컨벤션을 바꿔서 diff가 수만줄 남긴 기억이 있습니다.


어쨌든, C#의 세계에 발을 담그는 지금부터,

camelCase와 PascalCase에 적응하고자 합니다.

머리가 굳었으니 그만큼 시간이 더 걸리겠네요.


그럼 좋은 하루 보내세요.



  1. Bonita Sharif and Jonathan I. Maletic, "An Eye Tracking Study on camelCase and under_score Identifier Styles", 2010, Kent State University [본문으로]
  1. 2017.02.13 13:31

    비밀댓글입니다

    • 안녕하세요, 양인황님. :)
      지적하신게 맞습니다. 이제 타이젠도 객체지향으로 나아가고 있어요. 현재는 홈피 등지에서 알 수 있듯 아직은 개발중인지라 정확히 어느 시점에 오픈이 될지는 모릅니다. 우선은 Xamarin 코드부터 보시는게 도움이 될 겁니다. ;)

얼마전 일입니다.

소스코드를 외부에 오픈하기 전, C코드를 위한 코딩 컨벤션을 정리하였습니다.

코딩 컨벤션은 비교적 의사소통이 잘되는 국내 개발자 뿐만 아니라-

상대적으로 소통이 적었던 해외 개발자에게도 전달되었습니다.

대부분의 규약들은 구렁이 담 넘어가듯 모두가 동의하였습니다.


하지만...

헝가리안 표기법 일부를 차용한 코딩 컨벤션에서,

해외 개발자의 문제제기를 시작으로 수많은 개발자들의 격렬한 논쟁이 시작되었습니다.

'70년대 감성을 갖고 있는 구닥다리 프로그래머'라든가

'읽기 힘든 코드를 끊임없이 양산해내는 두뇌파괴자'라는 식의 설전이 오고간 후,

우리는 헝가리안 표기법을 갖다버리기로 거국적으로 합의하였습니다.

그리고 아주 제한적인 경우에만 사용하기로 하였습니다.


목차격으로 마인드맵을 하나 붙입니다.







헝가리안 표기법이 혜성처럼 어느날 문득 시야에 나타난 것은 아닙니다.

타입시스템이 없는 BCPL(Before C Programming Language)과 같은 고대 언어에서는,

변수명으로 변수의 타입을 명시하여 사용하였습니다.


그러한 흐름이 자연스럽게 이어져,

70년대에 등장한 언어에서도 변수명에 타입이 함께 기입되었습니다.

설사 타입시스템이 있는 언어라 할지라도,

에디터나 컴파일러가 고도화되지 않은 환경에서는 변수명만으로 타입을 확정지을 수 있는 방식이 여러므로 유용하였습니다.


그 중 Smalltalk라는 객체지향언어에서는,

타입을 변수의 뒤에 붙여 기입하는 방식을 사용하였는데,

이는 유럽인들의 이름 뒤에 성이 오는 방식에서는 지극히 자연스러운 현상이었습니다.

타입은 일종의 가문과 같은 집단이라 볼 수 있으므로 변수고유의 이름과 타입이 순서대로 배치됩니다.


하지만, 유럽에서도 특이하게 성이 이름 앞에 오는 관습을 지닌 헝가리에서 온 청년-

Charles Simonyi이 타입을 앞에 붙이는 방식을 시전하게 됩니다.


80년대 마이크로소프트의 아키텍트가 된 Charles Simonyi은,

마이크로소프트에서 개발하는 앱의 기본 코딩컨벤션으로 자신이 제창한 헝가리안 표기법을 선정합니다.



컴파일러나 에디터가 아직은 조악했던 시절,

변수명만 가지고 타입을 확정지어 사용할 수 있는 방법은 여러므로 유용하였습니다.

코드작성자와 코드독해자가 동일한 헝가리안 표기법을 숙지하고 있다면,

변수의 타입을 해석하는데는 아무런 불편이 없습니다.


bBusy, chInitial, wCount, dwLength 등의 변수명만 보고도,

각각 bool, char, word, double word인 것을 파악할 수 있기에,

변수에 엉뚱한 값을 할당하는 실수를 예방할 수 있습니다.


이러한 점을 높이 사서,

마이크로소프트에서는 21세기 초반까지 헝가리안 표기법을 사용하고 지속적으로 권장하였습니다.

1999, "Hungarian notation... easier to write, and easier to read."[각주:1]


그 결과,

헝가리안 표기법은 유행처럼 전세계 프로그래머들에게 퍼져나갔습니다.

학부 프로그래밍 강좌에서도 시험문제로 단골출제되었고,

전문프로그래머 사이에서는 지극히 당연한 교양처럼 여겨졌습니다.

80~90년대 격동의 학번을 경험한 중장년층 프로그래머들에게는 헝가리가 일종의 마음의 성지였죠.


하지만, 컴파일러는 더욱 똑똑해져서 컴파일 중에 수많은 warnings으로 개발자의 실수를 찾아주고,

에디터는 변수에 마우스 포인터를 갖다대는 것만으로 변수의 타입을 친절하게 팝업으로 보여주게 됩니다.

이러한 환경의 변화로 헝가리안 표기법에 대한 사람들의 인식도 바뀌어 갑니다.



2005, "Systems Hungarian had far less useful... But there’s still a tremendous amount of value to Apps Hungarian"[각주:2]

2008, "Do not use Hungarian notation"[각주:3]

2009, "vUsing adjHungarian nNotation vMakes nReading nCode adjDifficult."[각주:4]

         

"변수명에 굳이 타입을 prefix로 붙여야만 할까요?"

2005년, <조엘 온 소프트웨어>로 유명세를 타고 있는 조엘 스폴스키는 자신의 블로그에서 포문을 열었습니다.

헝가리안 표기법의 창시자인 Charles Simonyi의 논문을 언급하며,

본래의 헝가리안 표기법은 단순히 타입을 반복하여 적는 것이 아니라고 주장했습니다.


단순히 타입을 반복하는 표기법을 시스템 헝가리안 표기법이라고 말하며,

그 대신 필수적으로 명시해야할 변수의 의미를 prefix로 표기하는 앱 헝가리안 표기법을 사용하라고 권장하였습니다.


이를테면,

count에 사용하는 변수엔 'n',

index에 사용하는 변수엔 'i',

두 변수값의 차이를 가지는 변수엔 difference의 약자인 'd',

database의 각 row에 해당하는 변수엔 row의 약자인 'rw',

code injection 등의 공격을 받을 수 있는 스트링 변수에는 unsafe의 약자인 'us'를 붙입니다.



앱 헝가리안 표기법은 통일된 prefix가 없습니다.

(혹은 모두가 합의하여 정리된 prefix가 없습니다.)

한 쪽에서는 치밀한 분석과 고민으로 prefix를 썼지만,

다른 쪽에서는 공유되지 않은 semantics로 해석하기 힘든 변수가 될 수 있습니다.


이에 따라 2008년에는 헝가리안 표기법을 널리 퍼뜨렸던 마이크로 소프트가,

.NET Framework 4.5 General coding conventions 에서 헝가리안 표기법을 사용하지 말라고 합니다.




그리고 온라인에서는 서서히 헝가리안 표기법을 조롱하며 웃는 분위기가 조성됩니다.

"vUsing adjHungarian nNotation vMakes nReading nCode adjDifficult."

위의 문장은 제법 유명세를 탔는데,

각 단어 앞에 헝가리안 표기법에 따라 동사, 부사, 명사 등을 나타내는 prefix를 붙였습니다.

읽기... 쉬운가요?


이런 상황에서 해외 개발자에게 헝가리안 표기법을 사용하자고 제안했으니,

'두뇌파괴자(brain breaker)'라는 소리를 들을만 했죠.


하지만, 그 와중에도 살아남아 고이 간직하게 된 헝가리안 표기법이 있습니다.

바로 변수의 scope를 나타내는 prefix.


local 변수에는 'l_'을,

argument 변수에는 'a_'를,

member 변수에는 'm_'을,

global 변수에는 'g_'를,

클래스 스태틱 변수에는 's_'를,

함수 스태틱 변수에는 'c_'를 붙입니다.




로컬변수와 아규먼트변수에 사용하는 prefix는 거의 사용하지 않지만,

나머지 것들은 아직도 코드에 살아남아 그 명맥을 유지하고 있습니다.


코딩 컨벤션이 뭐라고 조선시대에 벌인 예송논쟁처럼 수많은 개발자들이 핏대를 높였지만,

시대와 환경에 따라 유연하게 대처하며 사용하면 됩니다.


끝_


  1. Microsoft : Hungarian Notation, https://msdn.microsoft.com/en-us/library/aa260976(VS.60).aspx [본문으로]
  2. Joel on Software : "Making Wrong Code Look Wrong", http://www.joelonsoftware.com/articles/Wrong.html [본문으로]
  3. Microsoft : "General Naming Conventions". https://msdn.microsoft.com/en-us/library/ms229045.aspx [본문으로]
  4. stackoverflow : "Why shouldn't I use “Hungarian Notation”?", http://stackoverflow.com/questions/111933/why-shouldnt-i-use-hungarian-notation [본문으로]
  1. 시온스 2015.11.01 16:17

    감사합니다. 그런데 StackOverFlow의 부정적인 의견 수렴은 무슨 의미인가요? 그냥 사람들끼리 그렇게 토론했다는건가요? 혹시 관련 주소를 알 수 있을까요?

    • 안녕하세요, 시온스님.
      타입을 변수명에 적어넣는 방식에 대한 토론은 아래 주소에 있습니다.
      http://stackoverflow.com/questions/111933/why-shouldnt-i-use-hungarian-notation
      타입을 일괄적으로 붙이는 헝가리안 표기법 말고,
      앱단에서 safe vs unsafe를 가리기 위해서나 변수의 범위를 가리는 표기법은 지금도 유용하게 사용되고 있습니다.
      도움이 되셨으면 좋겠습니다.
      감사합니다.

    • 시온스 2015.11.05 13:17

      감사합니다!

+ Recent posts