반응형

 

이 글에서 다뤄보고자 하는 내용은 2가지 입니다.

하나는 name mangling 이고 다른 하나는 extern "C" 입니다.

이 두가지는 c와 c++의 호환성과 관련된 부분이기도 하고 라이브러리를 사용하다보면 가끔 문제를 일으키는 부분이기도 한 부분입니다.

1. name mangling 이란?


간단히 말하면 compiler 가 임의로 함수나 변수의 이름을 변경하는 것을 의미합니다.
그렇다면 왜 함수나 변수의 이름을 변경하는 것인가?
이를 설명하기 위해서는  C++언어의 성격상 function overloading을 먼저 설명해야 하는데요.

함수 오버로딩(function overloading)이란 개발자가 소스코드를 작성할때 같은 이름으로 다른 기능들을 수행하는 함수를 만들수 있도록 하는 기능을 예기합니다.

int Add( int a,int b){return a+b;}
float Add( float a,float b){return a+b;}
float Add( float a,float b, float c){return a+b+c;}

 


위와 같이 Add라는 함수를 int형을 더하는 함수, float 형을 더하는 함수, 세개의 변수를 더하는 함수등등 여러개의 함수를 작성하고, 개발자가 이를 용도에 맞게 쓸수 있습니다.

이런것이 가능하도록 해주는 기능이 바로 함수 오버로딩이라는 개념입니다.

그럼 컴파일러(compiler)는 소스 코드에서 Add를 호출 했을때 어떻게 각각의 Add를 알아서 찾는가 하는 의문이 생길수 있을것인데,  이를 가능하게 해주는것이 name mangling 입니다.

compiler는 symbol을 생성할때 함수 이름과 함수 parameter를 고려 하여 symbol을 만듭니다.
즉,
int Add( int a,int b)  -> Add + int+ int --> Addii 와 같은 형식으로 만든다는 것입니다.
물론, compiler 마다 다른 mangling 규칙을 가지고 있습니다.

인터넷에 떠도는 문서들을 찾다보니 아주 한눈에 잘 들어오도록 정리된 표가 있어서 샤샥!! 퍼옴...


 

Compiler void h(int) void h(int, char) void h(void)
Intel C++ 8.0 for Linux _Z1hi _Z1hic _Z1hv
HP aC++ A.05.55 IA-64 _Z1hi _Z1hic _Z1hv
GNU GCC 3.x and 4.x _Z1hi _Z1hic _Z1hv
HP aC++ A.03.45 PA-RISC h__Fi h__Fic h__Fv
GNU GCC 2.9x h__Fi h__Fic h__Fv
Microsoft VC++ v6/v7 ?h@@YAXH@Z ?h@@YAXHD@Z ?h@@YAXXZ
Digital Mars C++ ?h@@YAXH@Z ?h@@YAXHD@Z ?h@@YAXXZ
Borland C++ v3.1 @h$qi @h$qizc @h$qv
OpenVMS C++ V6.5 (ARM mode) H__XI H__XIC H__XV
OpenVMS C++ V6.5 (ANSI mode) CXX$__7H__FI0ARG51T CXX$__7H__FIC26CDH77 CXX$__7H__FV2CB06E8
OpenVMS C++ X7.1 IA-64 CXX$_Z1HI2DSQ26A CXX$_Z1HIC2NP3LI4 CXX$_Z1HV0BCA19V
SunPro CC __1cBh6Fi_v_ __1cBh6Fic_v_ __1cBh6F_v_
Tru64 C++ V6.5 (ARM mode) h__Xi h__Xic h__Xv
Tru64 C++ V6.5 (ANSI mode) __7h__Fi __7h__Fic __7h__Fv
Watcom C++ 10.6 W?h$n(i)v W?h$n(ia)v W?h$n()v

 

위와 같이 컴파일러 마다 다른 mangling 규칙을 가지고 있답니다..

 

 

 

자! 그럼 C에 대한 이야기도 해야 하는데요, C의 경우는 mangled 된 함수 이름이 필요 없습니다.
이유는 C에서는 함수 오버로딩(function overloading)을 지원하지 않기 때문에 한 binary안에서는 하나의 함수만 존재 합니다.( 더 정확히는 하나의 symbol 만 허용됩니다.)
하지만 !!!  실제로 컴파일을 해보면 각 함수 이름을 살짝 바꿔 놓기는 합니다.
void Add(int a,int b) ---> _Add 라는 형식 으로 앞에 '_'를 붙입니다.  C++로 작성된 함수의 심벌(symbol) 과는 다릅니다.

C언어의 경우에는 함수 앞에 _를 붙이는 것이 표준인듯 합니다. 이부분에 대해서 찾아본 것이 아니라서 장담은 할 수 없지만 모든 컴파일러들이 공통일 것입니다.)


이런 변경이름(mangled name) 을 확인 해보는 방법은 컴파일된 object file(xxx.o) 나 실행 화일 또는 .lib 파일을 hex editor로 열어서 확인 해보면 눈으로 볼 수 있답니다.


2. extern "C" ?

C/C++ 호환 및 binary 호환 과 같은 주제들을 다루고 고민하다보면, abi니 eabi 니 name mangling 이니 compiler 호환이니 하는 단어들이 나오게 됩니다.

그중에 이 extern "C" 도 가끔 보이구요.  그래서 extern "C" 에 대해서 좀 더 자세히 다뤄보고 저의 경험을 토대로 예기 해보고자 이 글을 쓰게 되었습니다.

저도 언어를 처음 배울때에는 막연하게 "extern "C"를 붙이면 함수의 이름이 C 처럼 나오기 때문에 C++로 짜여진 함수도 C에서 사용할 수 있다." 라고만 알고 있었습니다.

이런 저런 개발을 하다보니 정확한 용법이나 메카니즘을 이해하지 않고 막연하게 사용하는 코드들이나 개념들은 결국 부메랑이 되어 저에게 돌아오더군요.!!
무슨 말이냐 하면,C++에서 짠 함수가 C에서도 사용할수 있게 하려면  extern "C" 를 붙이라는데 어디다? 어떻게 ? 라는 의문이 생겨날 것입니다.
근데 extern "C"에 대해 잘 모르는 사람이 위와 같은 조언을 들었으면,, 분명 extern "C"를 남발하게 됩니다.!!  이는 결국 나중에 compile error를 양산하기도 하고, 코드를 지저분하게 만들기도 하고, 아무튼 문제를 많이 일으키게 되죠.!!! 그런적 없다구요? 전 당했습니다.!! 


자 그럼 하나 하나 차근 차근 짚어 보겠습니다.


extern "C"  --> 이 형식은 extern "C" 이후에 오는 내용을 name mangling 하지 않고 C처럼 symbol을 만들 어라 라는 명령어입니다.

즉, abc.cpp 라는 소스코드에서 아래 abc라는 함수와 def라는 함수를 예로 들어보면,

[file : abc.cpp]

int abc(int a,int b) //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
{
return 0;
}

extern "C" int def(int a,int b)  // def 라는 symbol을 가지게 되는 것입니다.
{
return 0;
}

def는 ii 같은 것이 추가되지 않고 그냥 def라는 이름을 갖게 됩니다.

그러면, 모든 함수 구현 루틴에 extern "C" 를 붙이는것이 사실 귀찮고 힘든 일입니다.
그래서 , 연륜이 있는 개발자들은(저처럼 ㅋㅋㅋ)  extern "C" {}를 활용하게 되는 것이죠.

[file : abc.cpp]

extern "C"
{//<-- extern 시작
int abc(int a,int b) //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
{
return 0;
}

int def(int a,int b)  // def 라는 symbol을 가지게 되는 것입니다.
{
return 0;
}
}//extern 끝

이렇게 extern "C" {}를 사용하면 {} 안에 있는 모든 내용은 name을 mangling하지 않는 다는 선언이 됩니다.

이렇게 사용하면 모든 함수들을 따라다니면서 extern "C" 를 붙일 필요가 없어지는 것입니다.


또, 다른 형식으로 사용하는 case가 Header file extern "C"를 사용하는 경우가 있습니다.
(대단히 많이 사용하는 형식입니다. 이유는 관리하기가 편해서? )

[file : abc.h]

#ifndef __ABC_H__
#define __ABC_H__

extern "C"
{//<-- extern 시작

#include "sysconfig.h"
#include "hello.h"
#include "test.h"

//function prototype
int abc(int a,int b); //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
int def(int a,int b);  // def 라는 symbol을 가지게 되는 것입니다.


}//extern 끝

#endif //__ABC_H__

자!! 이제 위와 같은 포멧으로 주로 많이들 사용하는데, 위의 내용을 보면 어떤가요? 문제가 있어보이나요 없어보이나요?

얼핏 보기엔 아무런 문제가 없어 보입니다.
하지만!!!!!

한가지 찾아낸 분이 있군요.... 그렇숩니다. ^^a 위의 해더파일은 C 파일에서는 include 해서 사용할 수 없습니다.

#include "abc.h"



int main()
{
  int a = abc(1,2);
}


이유는 extern "C" 는 C++ compiler에서만 지원하기 때문입니다. 
a.c 에서 #include "abc.h"를  사용하면 error가 발생합니다. 
그래서 

#ifdef __cplusplus 를 이용해서 extern "C" 를 묶어서 사용합니다. 

 

[file : abc.h]

#ifndef __ABC_H__
#define __ABC_H__

#ifdef __cplusplus 
extern "C" {//<-- extern 시작
#endif
#include "sysconfig.h"
#include "hello.h"
#include "test.h"

//function prototype
int abc(int a,int b); //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
int def(int a,int b);  // def 라는 symbol을 가지게 되는 것입니다.

#ifdef __cplusplus 
}//extern 끝
#endif
#endif //__ABC_H__

이렇게 사용함으로 해서 C compiler에서는 extern "C"를 사용하지 않고 compile됩니다.
C compiler에서는 c니까 당연히 name mangling이 발생하지 않겠죠.!!!! <-- 요거 중요한 예기...


자 그럼 두번째 문제점은 어디에 있을까요??
못찾겠죠... 흔히들 실수 할 수 있는 부분입니다.

( 찾았다구요?? 이 글 왜 읽고 있습니까?? 자리로 돌아가서 일하세요.. ㅎㅎ 다 아시는 분이.. ~~)

두번째 문제는 사실 편하게 쓰고자 extern "C" {} 를 사용하는데 이게 아래와 같이 사용하면 문제를 만듭니다. 무슨 말이냐 하면.. extern "C" {} 중간에 header file을 포함하고 있죠??

그래서 abc.h 가 sysconfig.h를 include 하고 있고, sysconfig.h는 def.h를 include하고 있다면,
extern "C"{ //<-- abc.h
    extern "C" { //<--sysconfig.h
           extern "C"{//<-- sysconfig.h 내에서 include 하고 있는 def.h
 
런 형식으로 가다가 결국 extern "C"가 너무 많이 중복 사용되었다는 에러메세지를 받고 당황하게 되실 것입니다. ㅎ
 
결국 VC에서는 아래와 같은 에러를 내면서 컴파일 에러를 냅니다.
fatal error C1045: compiler limit : linkage specifications nested too deeply
visual Studio 에서는 depth 제한이 10으로 되어있습니다.
 
그래서 당황하여 여기저기 extern "C"를 찾아서 지우고 옮기고 하다보면, 나중에 name mangling 되어 link error를 메세지를 받고 뒷목을 붙잡고 쓰러질 수도 있습니다.
이래서 어설프게 알고 사용하면 절대 안된다는 의미입니다.
저는 그래서 아래와 같이 header file 선언부 아래에 extern "C"를 사용하기를 권합니다.

 

[file : abc.h]

#ifndef __ABC_H__
#define __ABC_H__


#include "sysconfig.h"
#include "hello.h"
#include "test.h"

#ifdef __cplusplus 
extern "C" {//<-- extern 시작
#endif 
//function prototype
int abc(int a,int b); //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
int def(int a,int b);  // def 라는 symbol을 가지게 되는 것입니다.

#ifdef __cplusplus 
}//extern 끝
#endif
#endif //__ABC_H__

모든 header file들이 위와 같이 include file 아래서 부터 extern "C"를 사용하면, 아래와 같이 중복되지 않게 되어 depth가 늘어나지 않습니다.  <-- 요거 꽤 중요한 팁이니 자기가 맡고 있는 프로젝트가 있다면 한번 살펴보세요!! ㅎ

extern "C"
{//<-- sysconfig.h 내에서 include 하고 있는 def.h
}
extern "C" 
{ //<--sysconfig.h
}
extern "C"
{ //<-- abc.h
           :
           :
}


자!! 이제 가장 중요하고 핵심이 되는 문제가 남았습니다.

이 문제는 위에 있는 해더파일 내용으로만 봐서는 절대로 찾을 수 없는 내용인데요..

뭐냐하면..

위와 같이 header 파일을 잘 만들었다 하더라도 link error를 당할 수 있는 경우가 있다는 것입니다.!!

어떤 경우일까요? 흠흠.


어떤 경우냐 하면 ,  우리가 만든 abc 와 def 함수의 몸체는 abc.cpp 에 있죠?
function name 이 mangling 될때가 언제라고 했죠?
link 할때? 아니죠~~ compile 할때.. 즉 compiler가 abc.o를 만들때 name이 mangling됩니다.
즉, name mangling을 막을려면 abc.cpp가 compile될때 막아야 합니다.
즉 그말은 abc.cpp가 compile될때 이미 extern "C"가 함수들에 선언 되어 있어야 name mangling을 막을 수 있다는 예기 입니다.

이미 abc.h에 extern "C"로 잘 감싸 놨는데 무슨 예기냐 ~~ 모르겠다... 하시는 분들 계실 겁니다.

abc.cpp가 아래와 같이 extern "C"가 없다고 합시다. 그리고 main.c에서 아래와 같이 abc를 사용했다고 합시다.


[file : abc.cpp]

int abc(int a,int b) //abcii 라는 mangled 된 이름을 symbol로 가지게 됩니다.
{
return 0;
}

int def(int a,int b)  // defii 라는 symbol을 가지게 되는 것입니다.
{
return 0;
}

[file : main.c]

#include "abc.h"  //<-- error 발생

void main()
{
    abc(10,20);
}
아.. 하시는 분 있을거 같은데 ㅎㅎㅎ. 좀 감이 오시나요? 어쨌든 설명을 이어 가겠습니다.

main 에서 abc를 호출하면 main은 c 파일이기 때문에 mangliing 안된 abc 를 symbol로 link 합니다.

하지만 abc.cpp를 compiler가 컴파일 할때는 abcii, defii 로 mangling 된 이름으로 symbol을 만듭니다.
왜? abc.cpp를 보십시오. abc.cpp안에는 어디에도 extern "C"라고 선언된 부분이 없습니다.
그래서 C++ compiler는 함수 이름을 mangling해버립니다.
그래서 main에서 부른 abc는 symbol만있고 body가 없기 때문에 link 시에 에러가 발생합니다.

이제 아셨죠.?? 이런 정확한 메카니즘을 모르면 왜 링크에러나는지 모르고 이것 저것 삽질하다 수정되면 그냥 넘어가 버리게 됩니다.!!! 코드만 지저분해지게 만들구요..

그러면 abc, def가  mangling 안되게 만들려면 어떻게 할까요? 맨 위에 예제 처럼 cpp 파일 처음부터 끝까지 extern "C"로 감싸면 될까요?
제가 적극 추천하는 방법은  abc.h를 abc.c 에서 include 하는 방법을 추천합니다.

[file : abc.cpp]

#include "abc.h"


int abc(int a,int b) //_abc 라는 mangled 된 이름을 symbol로 가지게 됩니다.
{
return 0;
}

int def(int a,int b)  // _def 라는 symbol을 가지게 되는 것입니다.
{
return 0;
}

이렇게 하면 compiler가 abc.cpp 를 컴파일 할때 abc.h에 있는 extern "C"{} 로 되어있는 영역 내부의 내용에 해당하는 abc,def함수들을 모두 mangling안되게 해준답니다. 


3.마치며!!

항상 강조하지만 100% 이해하지 못하는 code나 함수를 내 프로그램에 추가하게 되면 반드시 그 대가를 치르게 됩니다.!!! 이는 불변의 진리입니다.!!!
그러니 여러분들도 "남들이 이렇게 쓰니 나도 이렇게 써야지 " 이렇게 하지 마시고, 자신이 사용하고자 하는 것에 대한 내용을 최대한 깊게 이해하려고 노력하십시오.

그러면 나중에 돌아올 부메랑을 막을 방법도 갖게 될 것입니다.!!

 

 

'개발 Note > it 이야기' 카테고리의 다른 글

Modal의 구현 형태  (0) 2009.01.12
UI Modal 컨셉  (0) 2009.01.06
Feature modeling - 아직 정리되지 않은 주제.  (0) 2009.01.04
Refactoring  (0) 2009.01.04
S60 platform architecture  (0) 2009.01.04
반응형
<세미나 내용>


Feature Modeling Guideline


[배경 설명]

[RUP]-Rational Unified Process

User와 System간의 상호작용을, Usecase 로 표현하고, Usecase내에서 객체를 추출하는 방법을 예기하고 있다.

하나의 Usecase에서는 적어도 Inteface class와 Object, 그리고 일반 데이타에 해당하는 Entity Object 이 발생된다.(기본 공식과도 같다고함)
 -> 이말은 반대로 예기하면 Usecase를 작성해놓고 Interface class 와 object ,entity object 를 축축 할 수 없다면 잘못된 usecase라고 생각해야 할지도 모른다.즉, 제 검토가 필요하다.


[OOAD]
  -UML Notation
  -RUP(Usecase diagram)
=>"재사용"
(class 모듈 단위)
=> Framework 
( Design pattern
)
(IT와는 잘맞고 적합하다.)
=> Business logic 단위로 재사용
(Component Based Development)



IT와 SOA 가 달라서 다른 디자인이 필요하게됨..
-> "제품군 단위로 제사용을하자" 

- Product Line Engineering : Nokia /...

- 공통적으로 Architecture
S/W Platform : 제품군 + Scopping => Samsung 




S/W Platform   -  공통 가변 설계 (50%이상)  <- 제품군의 공통 가변 식별 <- Featrue Model 기법

Domain - 제품군으로 보면 된다.


[UML과 Feature model의 차이]
UML Usecase  --> Requirement Eng.(Analysis)   단위 Target Sys
       '사용자'

Feature
       사용자 관점 + Architect + 개발자  --> Domain Eng.(Analysis)     Product Line

       Feature 관점에서 나오는 모듈이나 요구사항들은 사용자 Level에서 이해가 가지 않는 부분들 많다.
       따라서, Feature model를 추진할때는 Domain Knowlage 를 가진 개발자들이 참여해야한다.


객체지향에서는 
Object type   <<Entity>> /   <<Boundry>> /   <<Control>> 
Feature model에서는
Feature type   <<Mandantoy>> /   <<Optional>> /   <<Alternative>> 



Feature Based Platform Develop Method
                        [방법론 가이드]
                    <강 교 철 교수 Postech >

Feature-Oriented Product Line Software Engineering
  Feature 기반 재사용 방법론


도메인 분석을 하고 어떻게 설계 구현을 해나가야 하나.



Feature Based Platform Develop Method
   (Samsung . Platform 설계 방법)

S/W Patform    -> Forward    - 완전히 새로 시작할때      
                     -> Re-Eng.    - 기존 s/w가 있는 상황에서 개발이 될때.
                    -- 방법의 차이는  Legacy 가 있냐 없냐의 차이가 있다.

--> 미완성 테그

Feature Identification & Analysis 

Behavior Analysis 
Platfrom building Platofrm design & Evaluation
가변 설계 --> 
이걸로 안되기 때문에  -->
QAW
Quality attribute 식별
Scenario 도출 및 상세화 
Architecture decision 도출
플렛폼 아키텍쳐 설계
Static view /Dynamic view
부품등록




아키텍쳐 : 시스템을 구성하는 기본단위인 컴포넌트와 이러한 컴포넌트를 어떻게 연결되어있는지 파악할수 있는 커넥터로 표현한것,
아키텍쳐 사상:               
<--

[Architecture modeling procedure]
Step 1. 아키텍쳐 구조 기본이 될 Layer선정
Step 2. Feature모델로부터 아키텍쳐 말단 구성 요소인 class 선정
Step 3. 동일 Layer하에서의 Shared data선정
Step 4. Later간 통신을 위해 Interface Mechanizm 구성
Step 5. 아키텍쳐 말단 구성 요소인 class간의 관계 설정
Step 6. Subsystem 수중의 관리를 위해 class를 package 화
    - 관련성 있는 .c 파일을 어떻게 관리할건가.
Step 7. 서비스 제공을 위한 Package Interface 설정
Step 8. 전체 시스템 구조를 Package들간의 관례로 구성


- detail
Step 2. Feature model로 부터 아키텍쳐 말단 구성 요소인 class 선정
   Feature model로 부터 optional/ Alternative Feature 들을 분리하여 독립 class로 선정.
       - 초기에 설계할때 가변부 파일들은 각각 분리 한다.

Static Architecture Design Principle


FORM ( Feature oriented reuse method)

'개발 Note > it 이야기' 카테고리의 다른 글

UI Modal 컨셉  (0) 2009.01.06
C++ 상에서 발생하는 name mangling 에 관한 내용  (15) 2009.01.04
Refactoring  (0) 2009.01.04
S60 platform architecture  (0) 2009.01.04
S60 Webkit & Nokia Browser architecture  (0) 2009.01.04
반응형
리펙토링에 대한 예기를 꺼내는데 먼저 Clear case같은 형상관리 툴에 대한 예기를 먼저 꺼내게 되었는데, 
S/W관리 및 유지보수를 위해 매우 중요한 일이기 때문이다, 더군다나 refactoring 시에도 매우 중요하게 적용되는 사항이기 때문에 먼저 예기하고자 한다.



[형상관리툴의 check-in]

형상관리시에 check in의 범위에 대해 다음과 같은 scope 에서 처리되어야 한다.

1 각각의 버젼은 단위 작업 내용이어야 한다.
    - 이전 코드와 이후 코드를 비교할때, 단위 작업이 아니라 이것 저것 수정한 경우에는 코드 비교시 많은 시간이 소비된다.
    - 2008.7.3일 퇴근 버젼!! <- 이런건 정말 난해한 버젼이 된다.
    - bug fix: ... 수정한 사항.   - refactoring: 코드 뭐 수정.... 이런식으로 버젼이 표시되어야 한다.

    이렇게 진행하는 이유는 코드 수정의 목적이 명확하고 ,수정 내역이 정확하여야 각 노드별 비교 분석이 가능해 지기 때문이다.
    우리가 흔히 하는 실수는 채크인 하는 목적과 실제 체크인 되는 내용이 다를때가 있다.
    코드 채크인 하는 이유는 bug fix인데,   실제 체크인 된내용은 맘에 안들던 함수 이름도 바뀌고, 변수도 수정하고, 다른 버그도 수정된 사항이 포함된다.
    그래서 형상관리상에 어떤 버그가 수정되었는지에 대한 기록이 없게 된다.

그러면 Refactoring 시 형상관리툴의 check-in은 왜 중요한 사항일까?
답은 간단하다.
Refactoring의 목적을 이해하면 왜 중요한 사항인지 파악하기가 쉽다.
Refactoring의 목적은 원래의 기능을 유지하면서 code를 여러가지 목적으로 수정하는 것을 의미한다.
        - 기존의 코드를 읽기 쉽도록( Readablity) 하여,
        - 유지 보수성(maintainability)을 높이는 것을 의미한다.
즉, 기존의 버그 수정이나 구조적 개선이 목적이 아니라 , 현제의 구조 및 기능에서 코드의 개선을 의미하는 것이다.
따라서, 이전 버전과 현재 수정된 버젼에서 무엇이 바뀌었는가? 이 코드 변경으로 인해 기능상의 변화가 있는가 등을 검토해보기 위해서는
이전 코드와 현재 코드를 비교하는 것은 꼭 필요하다.
이때문에 위와 같은 형상관리 툴의 check - in 정책은 꼭 필요한것이다.
또, 단순히 Refactoring을 위한 것 뿐만아니라 버그수정시에도 이와 같은 법칙은 적용된다고 봐야 한다.



[Refactoring]

목적
1.원래의 기능을 유지
2.이해하기 쉽고 수정하기 쉽도록 수정하는 것

리팩토링중 흔히 하는 실수중에 가장 조심해야 할것은,
   리팩토링 중에는 code 개선 작업만 해야하지 리팩토링중 발견된 버그를 수정해서는 안된다.
   *** 버그 수정으로 인한 코드 수정이 리팩토링이 올바르게 되었는지를 판단할수 없게 만들수도 있다.
          때로는 버그 수정으로 이로인해 비정상 동작이 나올수도 있는데, 이것이 리팩토링때문에 발생된 결과인지 
          버그 수정때문에 발생된 결과인지 판단하기 불분명해 지기 때문이다.
   리팩토링시 발견된 버그는 리팩토링 후에 따로 bug 리포팅후 fix 하는 시간을 따로 가져야 한다.
        

테스트 자동화 구현
원래 기능이 유지되는지 수정시 꼭 테스트 해야한다.
이를 위해 매번 수동 테스트를 하는 것보다 테스트 자동화를 구현하는 것이 편리하다.
기능 자동화 테스트가 없다고 한다면 Refactoring 결과를 매번 수동으로 확인해야 하고, 또 이러다보면 반드시 결과를 확인하지 않는 상황도 만들어지게 된다.



함수이름 변경
상당히 많은 내용을 내포하고 있다.

1.의미 있는 함수 이름으로 변경



2. OnceAndOnlyOnce
   : 함수 하나는 한가지 일만 하도록 작성 되어야 한다.
    동사 하나와 목적어 하나로 요약 할수 없다면.... 

    바람직하지 않은 구조--> 리팩토링 필요.

 바람직한 함수이름은   - 동사 하나 + 목적어 하나
 잘못된 이름의 예 ) MeasureRectAndDrawBorder....    -> MeasureRect 와 DrawBorder 를 나눌 필요가 있다.

The philosophy that information on how a piece of software operates - be it an algorithm, a set of constants, human-readable documentation, or something else - should exist in only one place. The practice of this is not always easy; in most languages (CommonLisp advocates claim that practicing OAOO is significantly easier for them), there are many types of situations where there is no obvious way to follow OnceAndOnlyOnce, or where following it requires more effort than simple duplication. The essence of it, however, is: Write everything once and only once - locate and fold together any duplication you find while adding the current feature. 

3. 함수이름이 적절하다면, 개발자입장에서는 그 함수에 대해 따로 문서가 필요 없다.
(문서화가 필요없다는 예기가 아니라, 개발자 입장에서 문서없이도 개발할 수 있을만한 함수라는 것이다. )

공유 자료구조에 대한 접근
전역변수, 공유자료에 대한 직접 접근을 피해야 한다.
 - 코드 중복 발생
 - 기타 예기치 못한 많은 문제들을 발생.
 - 절대 피해야함.
** standard lib에서 제공되는 기능이라면 이를 사용하라!!!
   이미 standard lib에서 테스트와 옵티마이즈가 끝난 함수들이기 때문에 믿을 수 있다.

전역변수->지역변수
 변수의 life cycle이 짧으면 짧을 수록 버그의 발생 요인을 줄일 수 있다.
 global>static>파일>함수>블럭 순으로 버그를 발생시킬 영역이 줄어든다.


expression 추출

반복된 문장 패턴이나 반복되는 expression 을 추출 대상으로 놓는다.

대표적인 예로, 영역 검사 루틴들이다.

if(( x>0&& x<maxw && y>0 && y<maxh) && pszText == NULL) ...
                    :
if(( x>0&& x<maxw && y>0 && y<maxh && winH<= MAX_HEIGHT)) ...
                    :
if(bEnter && ( x>0&& x<maxw && y>0 && y<maxh )) ...


이런식의 코드는 다음과 같이 수정
if( x>0&& x<maxw && y>0 && y<maxh)... -> if( PtInRc(x,y,&rcMax))




2개의 함수를 합칠때
**2개의 함수를 합치려 할때
    2개의 함수에서 공통으로 사용하는 변수는 서로 다른 이름으로 바꾼다.
    1. 사용되어지는 함수(put_stone) 에서 입력 parameter  x,y --> xx,yy 로 변경
    2. 만약 , xx,yy가 변경되지 않고 참조를 위해 읽기만 하는 경우라면 process_key 내에서 제거 가능하다.

Process_key()
{
   : 
  x = 10;
  y = 15;
  if( 어쩌고 저쩌고)
  {
    x = getUserX();
    y = getUserY();
  }
  put_stone(x,y);
}

bool  put_stone(int x,int y)
{
  :
  GameSysSetX(x);
  GameSysSetY(y);
 return 0;
}

    2개의 함수에서 공통으로 사용하는 변수는 서로 다른 이름으로 바꾼다.
    1. 사용되어지는 함수(put_stone) 에서 입력 parameter  x,y --> xx,yy 로 변경


Process_key()
{
   : 
  x = 10;
  y = 15;
  if( 어쩌고 저쩌고)
  {
    x = getUserX();
    y = getUserY();
  }
  put_stone(x,y);
}

bool  put_stone(int xx,int yy)
{
  :
  GameSysSetX(xx);  
  GameSysSetY(yy);
 return 0;
}
    2. 만약 , xx,yy가 변경되지 않고 참조를 위해 읽기만 하는 경우라면 process_key 내에서 제거 가능하다.
Process_key()
{
   : 
  x = 10;
  y = 15;
  if( 어쩌고 저쩌고)
  {
    x = getUserX();
    y = getUserY();
  }
    :
    GameSysSetX(
xx);  
    GameSysSetY(
yy);

}

    3. 알다 시피 xx,yy -> 해당 변수로 바꾸는 작업을 한다.





이와 같이 refactoring 전략은 보면 다들 머리속으로는 알고 있는 내용입니다.
딱 봐도 '당연한거 아냐' 라는 생각이 들 정도이죠.

허나 중요한것은 알고 있냐 가 아니라, 이렇게 하고 있는가 가 중요한것이겠죠.
처음부터 이러한 코딩을 해왔더라면, 따로 리팩토링이란걸 할 필요도 없는거죠.
다시 한번 강조하지만 리펙토링은 기존의 코드를 일기 쉽고 관리하기 편하도록 제 정리하는 작업이라고 
생각해야 합니다.

계층화

계층화는 리펙토링에서 사실 고난이도의 작업인데요. 리펙토링보다는 리스트럭쳐링에 가깝다고 보는 것이 옳습니다.( 리펙토링에도 리스트럭쳐링까지는 아니지만 계층화를 요구하는 경우가 있기 때문에 포함한 내용)

전체로직 계층
- 어플리케이션의 전체 로직의 흐름이 구현된 층
- 먼저 무엇을 하고, 그다음에 무엇을 하고...
-전체 작업의 흐름이 보인다.

단위작업 계층
- 단위 작업을 수행
- 세부 작업이 구현됨

유틸리티 계층
- 범용함수


Platform 화 할때:
  유틸리티 계층은 잘 만들어서 포함시키는 것이 맞고,
  단위작업 계층의 경우는 단번에 Pltform으로 이동은 힘들기 때문에 선행작업이 단위작업별로 잘 정리를 하는 것이 우선이다.
  그 후 단위 작업 계층이 많이 쌓이게 되면 그 후에 플렛폼으로 포함할수 있는 부분들만 포함시킨다.(물론 가공해서 platform에 맞게 정리함)
반응형


Mr.Blog...

일어나기 어려운 아침에 시끄러운 알람 대신 좋아하는 음악이나 사람의 목소리로 깨면 훨씬 좋을 것 같아요. 여러분의 기분 좋은 모닝콜은 어떤 것인가요?
 
사실 드라마나 영화에서 여친이 감미로운 목소리로 아침에 출근시간에 맞춰 모닝콜을 해준다거나.
아침을 알리는 노랫소리가 들리는 알람을 들으면서 일어난다는거...

이런거 실재로는 진짜 짜증납니다.

 

 

발로 차주는거!!!!

 

발로 차서 깜짝 놀래주는게 최고!!!!

짜증 날 겨를도 없이 "놀람"만 남을 뿐~~

 

아주 깔끔한 방법입니다. ~~ 하지만 이것도 자주 반복되면 짜증이~~~..

반응형

The melody, Mika, 휘성

 

사실 더 멜로디 라는 그룹의 음악때문에

집에 있는 스피커도 바꿨지만 정작 출퇴근 할때 이어폰으로 듣는거 외에 집에서는 거의 들을시간이 없어서 아쉬움이 많다.

 

Mika는 회사 후배가 추천해줬는데, 음악에 경쾌함이 묻어나는 것 같아서 좋다.

   Big girl~~ you are beautiful~~~

 

 

휘성 엘범은 내가 가지고 있는 것이 좀 된 엘범인데,

만져주기 - 이노래 좋다... 근데 앞부분에 사회적인 뉴스같은 나레이션은 좀 없었으면 좋겠건만...

         제목도 좀 맘에 안들지만.. (스킨쉽을 연상케 해서.).... 어쩌겠나.. 가수랑 작곡가가 이리 이름을 붙여놨으니.. 내가 뭐라 할 만한

 

이 3 엘범이 나에게 아침을 열어주고 기분을 좋게 만들어 준다.!

 

 

반응형

가끔 회사의 가치는 어떻게 먹여지나.. 하는 생각들을 해봤는데..

 

요즘은 과연 내가 하는 업무가 회사의 가치를 얼마나 상승 시켜주는가를 상상 해본다.

 

정말 내가 밤세워 열씸히 일을 하면 회사의 가치는 내가 밤을 샌 만큼 오르는 것일까?

 

비록 당장은 아니지만, 결과적으로 회사의 가치를 올리는데 일조 한것일까?

 

만약 그렇다면, 나는 우리 회사 주식을 많이 사놓고 , 내가 열씸히 밤새워 일한다면

 

주식을 당연히 오를것이고 그렇게 되면 나의 수익도 그만큼 상승하는것이 아닌가

 

음.....

 

그럼 내일 당장에라도 회사 주식을 사고,, 열씸히 일해서 ^^a 월급보다 더 많은 수익을 챙겨야징~ 풋!!!

 

요런 누가 들으면 발끈할만한 상상들을 해본다.!!!

반응형

오늘에 할일!!!! 쩝..

 

List에 대해서 알아보기..
하도 오래전에 써보고 최근에 써본적이 없는 내용이라 ... 기억이 가물가물해서
다시한번 여기저기 찾아보고 기록해 봐야지!!!.!!

 

요 페이지가 몇일만에 업데이트 될까낭?



-2008/11/17



-진짜로 업뎃이 안되네 ㅎㅎㅎ

- 2009/10/12
 좀 지난 사안이었지만, STL Open source 쪽에서 솔루션을 찾아서 써보기로 결정했다.



반응형



아...

요즘 나에게 떨어지는 개발 업무가 코딩 보다는 생각을 해야 하는 일이 점점 더 많아지는듯해!!

 

어떻게 개발해나가야 할까 Control과 View를 분리 해야지!!

근데 요렇게 요렇게..

 

좋아 분리는 다 했으니 밑에 있는 똘똘이한테 시켜야지..

 

근데.. 요렇게 하는게 앞으로 관리상 편의를 가져다줄까?

 

기존 코드들 이런 구조로 바꿀려면 다 뒤집힐텐데... 흠.. 반발은 없을라나....

 

.... 요런게 내 머리속에서 왔다리 갔다리..

 

점점더 뭔가를 결정내리기 어려워저가지!!!

 

코딩에만 전념하던때가 단순하고 편했던것 같아.~~



개발자 넉두리 같은 일기가 되어버렸네...


-2008/11/24

+ Recent posts