긴 메소드(Long Method)

최적의 상태로 가장 오래 살아 남는 객체 프로그램은 메소드가 짧다. 인디렉션(indirection)의 이점은 모두 짧은 메소드에 의해 제공되는 것이다.

인디렉션이란?

닫기

Indirection

From Wikipedia, the free encyclopedia

Jump to: navigation, search

In computer programming, indirection is the ability to reference something using a name, reference, or container instead of the value itself.

The simplest form of indirection is the act of manipulating a value through its memory address. For example, accessing a variable through the use of a pointer. A stored pointer that exists to provide a reference to an object by double indirection is called an indirection node.

In some older computer architectures, indirect words supported a variety of more-or-less complicated addressing modes.

Object-oriented programming makes use of indirection extensively, a simple example being dynamic dispatch. Higher-level examples of indirection are the design patterns of the proxy and the proxy server. Delegation is another classic example of an indirection pattern.

In strongly-typed interpreted languages with dynamic datatypes,most variable references require a level of indirection: first the typeof the variable is checked for safety, and then the pointer to theactual value is dereferenced and acted on.

닫기


원문에는 더 많은 내용이 나와있지만 간략히 요약하면 인디렉션이란 실제 값 자체가 아닌 그것을 참조하는 다른 이름을 사용하는 기능을 말한다는 것 같다. 이렇게 함으로써 프록시와 dynamic dispatch도 가능한 듯하다.

책의 82쪽에는 이런말이 있다.

컴퓨터 과학은 인디렉션 계층을 한 단계 더 만들면 모든 문제를 풀 수 있다고 믿는 학문이다.
-Dennis DeBruler

프로그래밍 초창기에는 서브루틴을 호출 할 때 오버헤드가 있어서 짧은 메소드 사용을 꺼려 했다고 한다. 그러나 요즘엔 프로세스 내부 호출(in-process call)로 인런 오버헤드가 상당부분 제거됐다고 한다. 하지만 서브루틴이 무엇인지 보려면 일단 그 부분으로 가보야 하기 때문에 사람들에게는 여전히 오버헤드가 존재한다. 그 오버헤드를 줄이기 위해서는 메소드의 이름을 잘 지어야 한다.

부분의 경우 메소드의 길이를 줄이기 위해서는 Extract Method를 사용한다. 메소드에 파라미터와 임시변수가 많으면 메소드를 추출하기가 어렵다.
  • 임시변수를 줄이기 위해서는 Replace Temp with Query를 사용할 수 있고
  • 긴 파라미터 리스트는 Introduce Parameter Object와 Preserve Whole Object로 짧게 할 수 있다.
  • 그럼에도 여전히 임시변수와 파라미터가 많다면 Replace Method with Method Object를 사용한다.
뽑아낼 코드 덩어리 식별 방법으로는 주석을 찾는 것이 좋다. 그리고 조건문과 루프 또한 추출이 필요하다는 신호를 준다. 조건식을 다루지 위해서는 Decompose Conditional을 사용한다. 루프의 경우는 Extract Method에서 예제로 다루고 있다.

Posted by 모과이IT
,

1장2장을 통해서 리팩토링이 어떻게 돌아가는지 알게 됐습니다. 하지만 리팩토링을 어떻게 하는지 안다고 해서 할 수 있는 것은 아닙니다. 언제 해야 하는지를 알아야 하는데... 그게 어려운 것 같네요. 3장을 Kent Beck이랑 Martin Fowler가 썼는데도 명확한 시점이라기 어떤 "냄새"가 날 때 라는 모호한 시점을 제기했네요. 경험적으로 인간의 직관보다 나은 기분은 없기 때문이라고 합니다. 그럼 이제 부터 어떠한 "냄새"들이 있으며 그런 "냄새"들은 어떻게 제거할지 살펴봅시다.

중복된 코드(Duplicated Code)

악취 중에 일등이 중복된 코드라고 하네요.
  • 한 클래스의 서로 다른 두 메소드 안에 같은 코드가 있는 경우 => Extract Method로 메쏘드로 뽑아내고 호출하도록 변경.
  • 동일한 슈퍼클래스를 갖는 두 서브 클래스에서 같은 코드가 나타나는 경우 => 양쪽 클래스에서 Extract Method를 한 뒤 Pull UP Method를 사용할 수 있슴.
  • 만약 메소드들이 같은 작업을 하지만 다른 알고리즘을 사용한다면 => 더 명확한 것을 선택하여 Substitute Algorithm을 사용할 수 있습니다.
  • 서로 관계가 없는 두 클래스에서 중복된 코드가 있는 경우에는 한쪽 클래스에서 Extract Class를 사용한 다음 양 쪽에서 이 클래스를 사용하도록 하는 것을 고려할 것.
  • 다른 가능성 : 메소드가 클래스 중 하나에 포함되어 있고, 다른 클래스에서 호출되어야 하거나 또는 세 번째 클래스에 속하는 그 메소그가 원래 두 클래스에서 참조되어야 하는 경우. => 뭔말인지...전혀 감이 안잡히는데요;;;
Posted by 모과이IT
,
리팩토링의 정의는 명사형과 동사형으로 나뉘어 있다.

리팩토링(명사형)-소프트웨어를 보다 쉽게 이해할 수 있고, 적은 비용으로 수정할 수 있도록 겉으로 보이는 동작의 변화 없이 내부 구조를 변경하는 것.

리팩토링 하다(동사형)-일련의 리팩토링을 적용하여 겉으로 보이는 동작의 변화 없이 소프트웨어의 구조를 바꾸다.

이 부분에서 주목할 것은...
첫 째 리팩토링의 목적은 소프트웨어를 보다 이해하기 쉽고, 수정하기 쉽도록 만드는 것이다.
두 번째로 강조하고 싶은 것은, 팩토링은 겉으로 보이는 소프트웨어의 기능을 변경하지 않는 다는 것이다.

왜 리팩토링을 해야 하는가?

  • 리팩토링은 소프트웨어의 디자인을 개선시킨다.
  • 리팩토링은 소프트웨어를 더 이해하기 쉽게 만든다.
  • 리팩토링은 버그를 찾도록 도와준다.
  • 리팩토링은 프로그램을 빨리 작성하도록 도와준다.
여기서 Kent Beck이 자신에 대해 했던 멋있는 말이 하나 나온다. "나는 훌륭한 프로그래머는 아니다. 그냥 훌륭한 습관을 가지고 있는 좋은 프로그래머이다."

다른 건 그렇다 치고.. 네 번째 프로그램이 빨리 작성하도록 도와 준다는데.. 어떻게 코딩->리팩토링->코딩->리팩토링을 하는데 코딩 쭉~~~~ 보다 빠를 수 있을까 잠시 의아했었지만.. 유지보수 하는데 엄청난 비용이 들어간다는 점을 고려했을 때 소 잃고 외양간 고치는 폭포수 개발 절차에 비해 외양간에 못을 틈틈히 박아줌으로 써 외양간을 새로 짓는 일이 안생기도록 한다는 측면에서 빠르다고 생각한다.(물론 비유는 별로 적절치 않은 듯하다.)

언제 리팩토링을 해야 하는가?
  • 삼진 규칙(세 번째로 비슷한 것을 하게 되면 리팩토링 한다.).
  • 기능을 추가할 때 리팩토링을 하라.
  • 버그를 수정해야 할 때 리팩토링을 하라.
  • 코드 검토(code review)를 할 때 리팩토링을 하라.
여기서 또 Kent Beck의 '리팩토링이 작동하는 이유'라는 글이 나온다. 프로그램은 두 종류의 가치를 가지고 있는데 하나는 오늘 당장을 위한 것, 하나는 내일을 위한 것이라고 한다. 오늘 할일은 확실하지만 내일 할일은 알 수 없다. 하지만 오늘만을 위해서 일한다면 내일은 전혀 일을 할 수 없을 지도 모른다. 리팩토링은 이런 상황에서 빠져 나오는 방법이다.

관리자에게는 뭐라 말해야 하나?

관리자에 따라 다르다. 만약 관리자가 기술적인 지식이 있는 사람이라면 어렵지 않다. 품질을 고려하는 사람이라면 리팩토링이 버그를 줄이고 따라서 개발 속도를 빠르게 한다고 설득하면 된다. 하지만 보통은 시간을 중요시 하는데 이때는 리팩토링에 대해 말하지 말라.

자.. 여기서 또다시 Kent Beck의 '인디렉션과 리팩토링'이라는 글이 나온다. 인디렉션은 양날의 칼과 같다. 하나를 둘로 나누면 그만큼 관리해야 하는 것도 많아지게 된다. 하지만 그만큼 충분한 가치가 있다. 그 예로는 로직의 공유(서브 메소드), 의도와 구현을 분리하여 설명(클래스의 이름과 메소드의 작명은 의도를 설명할 기회 클래스와 메소드의 내부는 구현), 변경의 격리(하나의 객체가 두 곳에서 사용될 때 나는 그것의 서브클래스를 만들고 바꾸려는 것에서 이 객체를 참고하게 한다.), 조건 로직의 부호화(조건문 말고 다형성을 이용)다.

리팩토링을 할 때의 문제
  • 데이터베이스
  • 인터페이스 변경
  • 리팩토링이 어려운 디자인 변경
  • 언제 리팩토링을 하지 말아야 하는가?
데이터베이스에서 리팩토링이 어려운 이유는 대부분의 비즈니스 애플리케이션이 DB 스키마와 밀접하게 결합되어 있기 때문이고 또하나 데이터 마이그레이션의 어려움이다.

완전하지 않은 인터페이스를 공표하지 마라. 매끄러운 리팩토링을 위해 코드 소유권 정책을 수정하라.

다른 사람이 코드를 바꿀 수 있도록 코드 소유권 정책을 수정하라는 것이며 페어 프로그래밍에서 이와 같이 하는 것이 좋다.

코드를 처음부터 다시 작성해야 할 떄는 하지 않는 것이 좋으며 또한 마감일이 얼마 남지 않은 시점에서는 리팩토링을 부채의 개념으로 생각해야 한다.

리팩토링과 디자인

리팩토링은 디자인을 보완한다. 리택토링이 없다면 초기 디자인을 할 때 완벽하게 하려고 많은 시간과 노력을 들이게 된다. 그렇게 디자인을 하고 개발을 해도 어차피 처음에 디자인한 것이 변경되는 경우가 자주 생기는데 그 때 디자인을 변경하는 것은 비용이 너무 크다. 하지만 리팩토링을 하게되면 초기 디자인을 할 때 그러한 부담이 없으며 따라서 단순한 디자인을 가지고 시작하게 된다. 리팩토링은 변경의 위험에 대한 접근을 다르게 한다. 또 리팩토링은 융통성의 희생 없이 단순한 디자인을 유도한다.

이번에는 Ron Jeffries의 '아무것도 한 것 없이 시간만 보냄'이라는 글이 나온다. 이 글에서는 Date에 대한 5분여 간의 리팩토링을 통해 시스템의 속도가 2배나 빨라 졌다고 한다. 팀원이 Kent랑 Martin이였다는데 이 둘은 여기 참여 한적이 없다고 부인하고 있다고 한다.ㅋ;;
이 글의 교훈 : 시스템이 어떻게 돌아가는지 정확하게 알고 있다 하더라도, 추측만 하지 말고 실제로 퍼포먼스를 측정해보라. 무엇인가 배울 것이고, 십중팔구는 추측이 틀렸을 것이다.

리팩토링과 퍼포먼스

퍼포먼스 향상을 위해 가장 효율적으로 보이는 접근 방법은 일단 개발을 하고 그 뒤 최적화 단계에서 프로그램을 모니터 하여 특별하게 시간을 지체하거나 공간을 많이 차지 하는 부분을 발견하여 집중적으로 튜닝하는 것이다.

프로그램을 잘 분해하는 것은 이런 최적화를 수행할 때 두 가지 측면에서 도움이 된다. 첫째, 코드가 잘 분해되어 있으면 퍼포먼스에 집중할 수 있는 시간이 늘어난다. 둘째, 퍼포먼스를 분석할 때 좀 더 세밀한 분석이 가능하다.

리팩토링 기원

1980년대 초 smalltalk 사용자인 Ward Cunningham과 Kent Beck으로 부터 시작하여 Ralph Johnson도 스몰토크 계를 선도 했고.. 이 분의 제자인 Bill Opdyke의 박사학위 논문이 지금까지도 리팩토링 분야의 가장 중요한 연구 결과라고 한다.

2장은.. 코드가 없네... 그래도 재밌게 읽었습니다.

Posted by 모과이IT
,

먼저 리팩토링이란? 외부 동작을 바꾸지 않으면서 내부 구조를 개선하는 방법으로, 소프트웨어 시스템을 변경하는 프로세스이다. 이것은 버그가 끼어 들 가능성을 최소화하면서 코드를 정리하는 정형화된 방법이다.

"코드가 작성된 후에 디자인을 개선한다."

물론 그 코드는 디자인을 거쳐 작성이 되었겠지만 코드가 디자인을 잘 따르지 않았거나 디자인이 잘 못 됐을 수도 있기 때문에 어감이 반대로 된 듯해도 맞는 말이다.
새로운 기능을 추가해야 하는데 프로그램의 코드가 새로운 기능을 추가하기 쉽도록 구조화되어 있지 않은 경우에는 먼저 리팩토링을 해서 프로그램에 기능을 추가하기 쉽게 하고, 그 다음에 기능을 추가한다.

유지보수에는 네 종류의 유지보수가 있는데 기억이 가물가물 하지만 억지로라도 떠올려 보면
에러가 발생하여 수정하는 유지보수(corrective maintanance)
환경의 변화에 따라 적응시키는 유지보수(adaptive maintanance)
미래에 발생할 문제를 미리 예방하는 유지보수
완벽을 기하기 위한 기능을 추가하는 유지보수 가 있다고 배웠다.(시스템 분석 및 설계 시간에...)
여기서는 네번째 유지보수 측면을 고려한 듯하다. 하긴 리팩토링 자체를 유지보수로 본다면 위 네가지 모두 고려대상인 듯하다.

리팩토링을 시작하기 전에 견고한 테스트 세트를 가지고 있는지 확인하라. 이 테스트는 자체 검사여야 한다.

테스트의 중요함을 할 수 있다. 요새 Agile Java 책을 스터디 하면서 TDD(Test Driven Development)를 공부하고 있는데 하나의 습관인지라 역시 쉽지 않다. 습관을 바꾸는게 가장 힘든일인듯 하다.(내 글씨는 악필인데 초등학교 때 서예학원도 다녀보고 맞기도 엄청 맞았지만 아직도 악필이다 --)

리팩토링은 작은 단계로 나누어 프로그램을 변경한다. 실수를 하게 되더라도 쉽게 버그를 찾을 수 있다.

조금씩 고쳐 나갈 때마다 계속해서 test를 해줘야 한다. 그래야 쉽게 버그도 찾을 수 있고 오히려 한번에 왕창 해두고 버그가 발생해서 어디가 문제인지 찾는데 시간이 더 오래 걸린다.

컴퓨터가 이해할 수 있는 코드는 어느 바보나 다 짤 수 있다. 좋은 프로그래머는 사람이 이해할 수 있는 코드를 짠다.

아~ 감명깊은 말이다. 주석의 중요함에 대해 써있는 책을 몇 번 봤었다. 그러나 주석이 잘 달린 프로그램 보다는 주석이 없어도 이해가 되는 프로그램인 듯하다. 물론 주석도 없고 이해도 안되는 코드는...최악이겠지만 말이다. 그러려면 역시 작명에도 신경을 잘 써야 하지만 대부분의 프로그램 언어가 영어인 관계로 작명+작문 이 합쳐지게 된다는 태생적인 문제가 있다.(영어 공부도 열심히?ㅋ)

오늘은 여기까지 보고 자야겠다. 내일 데이트를 해야한다.

Good Night!

1장을 다 보았다.(자랑인가? ㅋ) 보기만 했고 손으로 안따라 해봤기 때문에 아직 제대로 본건 아니다.

추가할 요약사항이 있어서 수정한다.

리팩토링의 리듬!

테스트 -> 조금 수정 -> 테스트 -> 조금 수정

Posted by 모과이IT
,
위키백과 ― 우리 모두의 백과사전.

소프트웨어 공학에서 리팩토링(refactoring)은 주로 '결과의 변경 없이 코드의 구조를 재조정함'을 뜻한다. 주로 가독성을 높이고 유지보수를 편하게 한다. 버그를 없애거나 새로운 기능을 추가하는 행위는 아니다. 사용자가 보는 외부 화면은 그대로 두면서 내부 논리나 구조를 바꾸고 개선하는 유지보수 행위이다.

마틴 파울러의 저서 《리팩토링》에 다양한 리팩토링 패턴들이 정리되어있다. 그 중 대표적인 것 몇 가지를 들자면, 필드 은닉, 메소드 추출, 타입 일반화, 메소드 이름 변경 등이 있다.[출처 필요]

Posted by 모과이IT
,

팀 프로젝트를 수행할때 필요한것 중 하나가..
서로의 변수명과 함수명등을 결정하는 것이다.
팀 내의 규칙에 다라서 결정하는 방법도 있고..
그냥 자신의 습관에 따라 결정하는 방법도 있겠지만..

그래도 추후 타 독자의 이해를 도우면서 가독성을 높일 수 있는 방법이 가장 좋지 않을까?
그런 의미에서 헝가리안 표기법은 많은 도움을 줄 수 있다.
헝가리 태생 MS의 연구원 Charles Simonyi 가 고안한 것으로 알려져 있다.

현재 인터넷에 너무나 많은 관련 글 들이 있어.. 어디가 원본인지.. 찾아 보기 어려워..
몇군데의 내용을 모아서 정리를 해보고자 한다.. 거의 글어다 붙이기 정도지만... ㅎㅎㅎ

 

헝가리안 표기법의 목적은 개체에 대한 정보를 간결하고 효율적으로 전달하는 것이다.


헝가리안 표기법은 익숙해지려면 시간이 조금 걸리지만, 한번 익숙해지면, 그 다음부터는

아주 자연스럽게 되어 버린다.

헝가리안식 개체 이름의 형식은 다음과 같다.


[접두어] 태그 [기본이름 [접미어] ]


  * 꺾쇠괄호([])는 개체 이름에 있어서 선택적 사항임을 나타낸다.


다음은 각 항목에 대한 설명이다.


접두어 
 부가적인 의미를 나타내기 위해 태그를 보조한다. 접두어는 모두 소문자이다.
 이들은 대개 이 문서에 나오는 표준적인 접두어들 중에서 선택된다. 
 
태그
 문자들의 준말로서 그 개체의 형식을 나타낸다. 모두 소문자로 이루어지고
 마찬가지로 이 문서에 나오는 표준적인 태그들 중에서 선택된다.
 
기본이름
 개체가 무엇을 나타내는 지를 알려주는 한 두 개의 단어.
 각 단어의 첫 문자는 대문자로 만든다.
 
접미어
 기본이름의 의미를 부수적으로 도와준다. 접미어의 각 단어의 첫 문자는
 대문자로 만든다. 그리고 접미어는 이 문서에서 나오는 표준적인 접미어들
 중에서 선택된다.
 

개체 이름으로서 필수적으로 요구되는 항목은 태그이다.
이것은 조금 이상하게 보일 수 있다; 여러분은 기본이름이 개체 이름 중에 가장
중요한 요소라고 느낄 것이다. 하지만, 임의의 폼 상의 한 프로시저를 생각해 보자.
이 프로시저가 중요하긴 하지만, 그 폼 전체를 나타내는 것은 아니다.
이 프로시저가 다른 많은 형식의 폼 상에서 작동될 수 있기 때문에, 여러분이
필수적으로 기본이름을 가져야만 하는 것은 아니다.
어쨌든, 만일 여러분이 프로시저 내에서 하나 이상의 참조되는 개체를 가지고 있다면,
그들을 구분하기 위해 기본이름이 필요하다.


실 생활에서 사용되는 헝가리안 표기법은 다음과같다


a           배열
b           또는 f BOOL형 변수(b는 "bool",f는 "flag"의 약자)
by         BYTE(unsigned char)형 변수
c           카운터로 사용되는 변수
ch         char형 변수
cx,cy     x,y길이를 나타내기 위해 사용되는 변수
d           날짜형 변수
dbl        double형 변수
h          핸들(HANDLE)형 변수
n 또는 i   int형 변수
l            long형 변수
p          포인터 변수
lp          long(far)포인터 변수(32비트 프로그래밍에서는 일반 포인터와 같음)
s          문자열
sz        널(NULL)로 끝나는 문자열
u          unsigned int형 변수
w          WORD(unsigned short)형 변수
dw        DWORD(unsigned long)형 변수
str        CString형 변수
m_       멤버 변수

----------------------------------------------------
x_xXxxxxxx
0123456789


0 : 변수의 위치를 지정한다. g(전역변수), m(멤버변수), 없음(지역변수)
1 : 0 위치에 g 나 m 을 지정한 경우 _ 을 기술한다.
2 : 자료형의 종류를 나타낸다.


   n, i : 정수형(n 은 카운트 목적, i 는 인덱스 목적)
   l : long 형 (과거 int 와 구분하기 위해서 사용했다.)
   u : 부호없는 정수형
   w : 부호없는 2 byte 정수형
   dw : 부호없는 4 byte 정수형
   p : 포인터 타입
   f, d : 실수형(f 는 float, d 는 double)
   sz : char 배열(문자열 표현)
   클래스 이름에 대해서는 관습적으로 자음축약형을 사용한다.

3 ~ : 변수의 의미 있는 이름을 기술하며, 3 위치는 대문자를 사용한다. 변수 이름이 너무 긴 경우 자음만을 기술한다.
예) g_nCnt
_______________________________________________________________________________

사용자 삽입 이미지

Table 1. Some examples for procedure names

Name

Description

InitSy

Takes an sy as its argument and initializes it.

OpenFn

fn is the argument. The procedure will "open" the fn. No value is returned.

FcFromBnRn

Returns the fc corresponding to the bn,rn pair given. (The names cannot tell us what the types sy, fn, fc, and so on, are.)



Table 2. Standard type constructions

pX

Pointer to X.

dX

Difference between two instances of type X. X + dX is of type X.

cX

Count of instances of type X.

mpXY

An array of Ys indexed by X. Read as "map from X to Y."

rgX

An array of Xs. Read as "range X." The indices of the array are called:

iX
index of the array rgX.

dnX

(rare) An array indexed by type X. The elements of the array are called:

eX


(rare) Element of the array dnX.

grpX

A group of Xs stored one after another in storage. Used when the X elements are of variable size and standard array indexing would not apply. Elements of the group must be referenced by means other then direct indexing. A storage allocation zone, for example, is a grp of blocks.

bX

Relative offset to a type X. This is used for field displacements in a data structure with variable size fields. The offset may be given in terms of bytes or words, depending on the base pointer from which the offset is measured.

cbX

Size of instances of X in bytes.

cwX

Size of instances of X in words.



Table 3. Standard qualifiers

XFirst

The first element in an ordered set (interval) of X values.

XLast

The last element in an ordered set of X values. XLast is the upper limit of a closed interval, hence the loop continuation condition should be: X <= XLast.

XLim

The strict upper limit of an ordered set of X values. Loop continuation should be: X < XLim.

XMax

Strict upper limit for all X values (excepting Max, Mac, and Nil) for all other X: X < XMax. If X values start with X=0, XMax is equal to the number of different X values. The allocated length of a dnx vector, for example, will be typically XMax.

XMac

The current (as opposed to constant or allocated) upper limit for all X values. If X values start with 0, XMac is the current number of X values. To iterate through a dnx array, for example:

for x=0 step 1 to xMac-1 do ... dnx[x] ...

or

for ix=0 step 1 to ixMac-1 do ... rgx[ix] ...

XNil

A distinguished Nil value of type X. The value may or may not be 0 or -1.

XT

Temporary X. An easy way to qualify the second quantity of a given type in a scope.



Table 4. Some common primitive types

f

Flag (Boolean, logical). If qualifier is used, it should describe the true state of the flag. Exception: the constants fTrue and fFalse.

w

Word with arbitrary contents.

ch

Character, usually in ASCII text.

b

Byte, not necessarily holding a coded character, more akin to w. Distinguished from the b constructor by the capital letter of the qualifier in immediately following.

sz

Pointer to first character of a zero terminated string.

st

Pointer to a string. First byte is the count of characters cch.

h

pp (in heap).



- 참조 -

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvsgen/html/HungaNotat.asp

http://web.archive.org/web/20001018073323/www.strangecreations.com/library/c/naming.txt

http://ttongfly.net/bbs/view.php?id=windowsc&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=2

http://blog.naver.com/shadovv13?Redirect=Log&logNo=50012280887

http://blog.haz3.com/tag/%C7%EB%B0%A1%B8%AE%BE%C8%20%C7%A5%B1%E2%B9%FD


Posted by 모과이IT
,

내 맘대로 정한 헝가리안 표기법... 

MS의 MFC와 WTL에 사용된 코딩 규칙을 대부분 적용 하였다.


약간 변형 시키긴 했다만...

 

이런 규칙을 정하는 이유는 코딩 또한 하나의 문서라고 보는 철학에서 나왔다.

문서란 작성하는 사람위주가 아니라. 보는 사람 위주로 만들게 된다.

 

일관된 패턴과,

보는 사람관점의 '파악하기 쉬운'(?)

이라는 철학으로 코딩규칙을 정하고 개발 하게 되면

 

팀프로젝트에서 다른 팀원이 개발한 코드, 또는 몇년이 지나고 자신이 개발한 코드를 볼때도 빠르게 파악하게 된다.

 

아래 규칙은 "코드를 파악하기 쉬운 규칙"이라는 단 하나의 기준 만으로 정해 놨다.

 

불합리 하다고 생각되시는 분은 리플 달아 주심 감사 하겠습니다.

 

Prefix

Type

Example

dw 

double word

dwTotal

w

WORD

wNumber

l

long

lTotal

i

Integer

iNumber

f

float

fAvarage

b

bool

bCheck

n

short

nCount

by

BYTE

byOffset

ch

CHAR

chKey

sz

CHAR[] Null Terminatied

szFlag

sz

WCHAR[] Null Terminatied

szPin

C

Class

CButton 

s

static

sHelper

p

Pointer

pButton

str

CString 

strAddress

r

RECT

rDraw

a

Array

aBags

g_

Global Val

g_bShow

m_

Member Val

m_iMans

si

size_t

siCount

 

 

 

vec

vector

vecMan

map

map

mapWoman

lst

list

lstHome

hsh

hash

hshHome

h

handle

hWindow

 

 

 

 

Original

Type

Example

unsigned char

BYTE

byOffset

unsigned short

WORD

nCount

unsigned long

DWORD

dwTotal

long

LONG

lNumber

int

int

iNumber

BYTE

BOOLEAN

bChecked

WCHAR *

LPWSTR

pszCaption

const WCHAR *

LPCWSTR

pcszCaption

LPCWSTR

LPCTSTR

pcszCaption

char *

LPSTR

pszCaption

const char *

LPCSTR

pcszCaption

 

 

1. 변수의 접두어는 모두 소문자

   ex) m_pCheckBox, m_CheckBox, g_nTotal, g_SessionManager

         nCount, strCaption, pListBox


2. 변수에서 접두어가 없는 경우 첫 단어는 소문자로 시작

   ex) m_checkBox, g_total, g_memberCount; m_memberList;

        로컬 변수일경우:  checkbox, item, 


3. 함수의 첫글자는 대문자

   DestroySession(), Connect(), Close(), ViewMap(),


4. 함수의 이름은 동사+명사

   GotoURL(), ViewMap(), PlayMovie(), ParseURL()


5. Class는 접두어를 제외한 첫번째는 대문자

   CCaption, CMembers, CResourcePaint, CFileStream


6. 여러 단어가 합쳐 졌을때는 각 단어의 시작은 모두 대문자

   ConnectToTheServer(), SendToMetaData() g_nMetaDataCount


7. Typedef, #define, enum, union등의 type은 모두 대문자

typedef enum {
    T_1,
    T_2,
    T_3
}TEST_DATA;

단 struct와 union의 맴버는 m_를 붙이지 않으며 모두 대문자를 사용하지 않고 위의 표기법으로 사용한다.
맴버는 맴버이지 하나의 type이 아니기 때문이다.

8. if문 및 switch등 제어문의 표기법

   if( i = 1 )

   {           <== 반드시 개행시켜서 표현한다.

....

   }

 

   for( i = 0; i < 100 && !myIterator.empty() ; i++ )   {

      do {

          if( a == b ) {


          }

     

          switch( nCount ) {

        

          }

       }while( nCount < 100 )

   }


   이런 식의 사용은 if문 및 switch문에서 문장의 전체 범위가 한번에 들어 오지 않는다.  

   따라서 개행해서 코딩 하도록 한다.

  

   for( i = 0; i < 100 && !myIterator.empty() ; i++ )  

   {

       do

       {

           if( a == b )

           {


            }

     

           switch( nCount )

           {

        

           }

       } while( nCount < 100 )

    }



   switch( nCount )

   {

    case CNT_FIRST:

            {

            }

            break;

   }


9. 문단으로 구분한다.

   하나의 함수 안에서도 처리 하는 부분들이 구분 될 수 있다. 이럴때는 아래위 공백을 하나씩 사용해서 구분 해준다.


10. 제어문에서 ( )는 본문과 한칸씩 띄워준다.

   위의 switch나 if, while문등이 명령어 다음 바로 (가 붙고 조건 맨끝에서 한칸뒤에 )가 붙어 있다.

   이것또한 조건과 명령어등이 명확히 보이도록 하고 내부에서 ()가 사용되었을 경우 정확히 끝이 어디인지 한눈에 알아보기 쉽기 위해서 

   다

  1.  if (nTotal < 1000 && myIterator !=  m_vecStudent.end())


  2.  if( nTotal < 1000 && myIterator !=  m_vecStudent.end() )  


   두개의 문장중 어떤것이 조건의 시작과 끝을 보기 편한가?


11. Class와 함수의 윗줄에 구분줄을 표시 한다.

   이 규칙은 Borland C++이나 Delphi에 있던 규칙인데 이것을 사용하게 되면 함수의 구분과 class의 영역 구분 또한 명확해 진다.

   만약 Doxygen이나 JavaDoc 같은 주석을 사용한다면 명확히 구분이 되기 때문에 사용하지 않아도 된다.

 

ex)   아래 코드는 즉석해서 만들어낸 예제 코드임으로 코드적 결함이 있을 수 있다.

//--------------------------------------------------------------------------------------------------------

class CBookmark

{

private:

 

public:

       CBookmark();

       ~CBookmark();
}  

 

//--------------------------------------------------------------------------------------------------------

class CInputBox

{

private:

 

public:

       CInputBox();

       ~CInputBox();
}  

 

//--------------------------------------------------------------------------------------------------------

class CViewMap

{

private:

 

public:

       CViewMap();

       ~CViewMap();
}  

 

//--------------------------------------------------------------------------------------------------------

void CViewMap::StopRandering(CParent * pParent)

{

      if( pParent->m_bsState == BS_RUNNING )

      {

            .

            .

       }

     

     pParent->Cancel();

}

 

//--------------------------------------------------------------------------------------------------------

BOOL CViewMap::BeginRandering(CParent * pParent)

{
.

.

}

 

//--------------------------------------------------------------------------------------------------------

CHandle* CViewMap::InitRanderer(CParent * pParent)

{

.

.

}

 


Posted by 모과이IT
,