자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif...

98
자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 김이선 veblush@[nexon|gmail]

description

 

Transcript of 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif...

Page 1: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기

김이선

veblush@[nexon|gmail]

Page 2: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

BNB 프로그래머

카트라이더 리드 프로그래머

버블파이터 프로토타입

리드 프로그래머 에버플래닛

리드 프로그래머 던전엔파이터

테크니컬 디렉터 GTR

프로그래머

게임 프로그래밍 11년차

Page 3: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

프로젝트 소스 코드의

유지보수성 (Maintainability) 관리가 중요!

Page 4: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

[던전엔 파이터] 에서 했던

코드 관리 중 하나인

불필요한 #if - #endif 제거 작업

Page 5: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

분석 처리 검증 결론 결과 도입 도입

Page 6: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

오늘 알아볼 코드

[던전엔 파이터]

Page 7: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

“퀘스트 시스템”

추가 작업

Page 8: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

// 김철수: 퀘스트 시스템 구현

//#define _QUEST_SYSTEM

Flags.h

1단계

플래그 정의

Page 9: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

#ifdef _QUEST_SYSTEM

ui.questWnd.setButton(…);

ui.questWnd.setEvent(…);

#else

ui.questWnd.setDisable();

#endif

*

2단계

기능 구현

Page 10: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

// 김철수: 퀘스트 시스템 구현

#define _QUEST_SYSTEM

Flags.h

3단계

기능 플래그 켬

Page 11: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

작업 중인 코드가

다른 작업자, 라이브 코드에

영향을 주지 않음

(장기간 작업, 빠른 롤백, 이벤트)

Page 12: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

국가별 소스 코드 공유에 도움

(국가별 플래그, …)

Page 13: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

간단한 작업 방식

(교육 비용이 낮음)

Page 14: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

플래그 켬/끔이 Rebuild 를 초래

(Flags.h 파일을 모든 파일이 #include 하므로)

Page 15: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

코드가 점차 읽기 어렵고 수정하기 어려워짐

(#ifdef - #endif 블록이 코드에 가득 차기 시작함)

Page 16: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

코드가 점차 읽기 어렵고 수정하기 어려워짐

(#ifdef - #endif 블록이 코드에 가득 차기 시작함)

Page 17: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

죽은 코드가 생겨남

(꺼진 플래그나 #else 에 묶엔 코드들)

Page 18: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

그럼 플래그가 얼마나?

Page 19: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012
Page 20: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

5400 개

+1500 /1yr

2015 년 10000 개

Page 21: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

플래그 개수가 늘어남에 따라

발생하는 추가적인 문제!

Page 22: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

#ifdef _EVENT_2006

ui.notice.setText(“월드컵 이벤트!”);

ui.notice.setVisible(1);

ui.notice.setEventHandler(…);

#endif

문제 1

죽은 코드

Page 23: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

#ifdef _NEW_UI_COMPONENT

ui.notice.setText(“…”);

ui.notice.setVisible(1);

#else

set(UI_NOTICE, TEXT, “…”);

set(UI_NOTICE, VISIBLE, 1);

#endif

문제 2

중복 코드

Page 24: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

플래그 작업 방식은 유지하되

불필요하게 늘어난 플래그 개수를 줄여보자

Page 25: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

불필요한 플래그 제거!

Page 26: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

ui.quest.setVisible(1);

ui.quest.setEventHandler(…);

플래그 켜서 제거

#ifdef _QUEST_SYSTEM

#endif

Page 27: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

ui.quest.setVisible(1);

ui.quest.setEventHandler(…);

플래그 켜서 제거

Page 28: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

#ifdef _EVENT_2006

ui.notice.setText(“월드컵 이벤트!”);

ui.notice.setVisible(1);

ui.notice.setEventHandler(…);

#endif

플래그 꺼서 제거

Page 29: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

플래그 꺼서 제거

Page 30: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

#define _NEW_QUEST

플래그 병합

제거

#ifdef _NEW_QUEST

# define _NEW_QUEST_FIX

#endif

#ifdef _NEW_QUEST

ui.event.setText(…);

# ifdef _NEW_QUEST_FIX

ui.event.setPos(…);

# endif

#endif

Page 31: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

#define _NEW_QUEST

플래그 병합

제거 #ifdef _NEW_QUEST

ui.event.setText(…);

ui.event.setPos(…);

#endif

Page 32: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

개운하다!

Page 33: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

제거할 플래그 선택

소스에서 플래그 제거

테스트

Page 34: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

수천개를 수작업으로?

Image: http://www.flickr.com/photos/15271532@N00/1172675049

Page 35: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

리팩토링 딜레마! 실수하면?

누가하지?

Page 36: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

자동화

Image: http://www.enggtechsolutions.com/?page_id=5

Page 37: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

제거할 플래그 선택

소스에서 플래그 제거

테스트

선택 자동화

제거 자동화

검증 자동화

Page 38: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

분석 처리 검증 도입 결론 결과

Page 39: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

플래그에 대한 정보 얻기 (삭제할 플래그를 추리기 위해)

Page 40: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

소스 파일

Page 41: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

#define F | #undef F

#ifdef F | #ifndef F | #if defined(F)

Page 42: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

국가별 Flags.h 파일에 정의된 플래그 추리기

Page 43: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

#define 뒤에 있는 주석도 가져오기

Page 44: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

Subversion Log

Page 45: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

모든 커밋의 Rev#, 날짜, 작성자, 로그

변경한 파일에 포함된 플래그 목록

Page 46: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

플래그 정보 _QUEST_SYSTEM

사용: 한국, 중국

날짜: 2008-06-21

파일: Interface/QuestWindow.h

Interface/QuestWindow.cpp System/Quest.h

System/Quest.cpp

SVN: #29110, ironwater

“[추가] 퀘스트 시스템 1차 작업”

주석: 김철수, 퀘스트!

Page 47: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

판단을 내릴 정보 가공! (단순한 정보 나열을 구체화)

Page 48: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

플래그 정보 쿼리 결과

DB 테이블 쿼리 수행

Page 49: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

DB 를 통해 유연한 분석 가능

Page 50: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

국가별 / 연도별 플래그 등장 표

Page 51: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

DB: 큰 그림 분석

시간별 증감 추이

국가별 사용 현황

작업자별 플래그 추가 파일별 플래그 추이

플래그 영향력

Page 52: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

DB: 오류 분석

정의만 되고 사용되지 않음 (버려짐?)

정의는 없고 사용만 있음 (오타?)

정의가 여러 곳에 있음 (응?)

정의가 여러 곳에 있으면서 값이 다름 (으악!)

Page 53: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

모두 켜거나 끈 플래그 목록 추리기

Page 54: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

모든 국가에서 켜고 끈

플래그 수집

작성자 및 상급자에게 삭제 리뷰

요청

피드백을 받아 진행

Page 55: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

분석 처리 검증 도입 결론 결과

Page 56: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

제거할 플래그를

소스에서 제거

Page 57: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

ui.quest.appendMsg(“…”);

questDlg.show();

플래그 켜서

제거

#define _QUEST_SYSTEM // 퀘스트

#ifdef _QUEST_SYSTEM

#endif

Page 58: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

ui.quest.appendMsg(“…”);

questDlg.show();

플래그 켜서

제거

Page 59: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

ui.event.setVisible(0);

플래그 꺼서

제거

#ifdef _EVENT_2008 // 2008 설 이벤트

ui.event.setText(…);

ui.event.show();

#else

#endif

Page 60: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

ui.event.setVisible(0);

플래그 꺼서

제거

Page 61: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

#define _NEW_QUEST

플래그 병합

제거

#ifdef _NEW_QUEST

# define _NEW_QUEST_FIX

#endif

#ifdef _NEW_QUEST

ui.event.setText(…);

# ifdef _NEW_QUEST_FIX

ui.event.setPos(…);

# endif

#endif

Page 62: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

#define _NEW_QUEST

플래그 병합

제거 #ifdef _NEW_QUEST

ui.event.setText(…);

ui.event.setPos(…);

#endif

Page 63: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

http://dotat.at/prog/unifdef

Page 64: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

Unifdef 가 기본적인 기능은 잘 해줌

Page 65: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

다만 부분 평가는 해주지 않음

#if defined(A) && defined(B)

A=켬|끔 B=그냥둠

#if 1|0 && defined(B)

Page 66: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

병합 제거는 따로 구현

#ifdef A

# ifdef A_fix

# endif

#endif

#ifdef A

#endif

Page 67: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

작업 흐름

unifdef 부분 평가 병합 제거

원시소스

제거 플래그 리스트

결과소스

Page 68: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

분석 처리 검증 도입 결론 결과

Page 69: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

처리 원시소스 결과소스

원시EXE 결과EXE =

Page 70: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

동일한 소스를 두 번 빌드 후 EXE

빌드시간, 디버그 정보 등이 EXE 에 포함

Page 71: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

동일한 소스를 두 번 빌드 후 OBJ

디버그 정보가 OBJ 에 포함

Page 72: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

# name

#1 .drectve

#2 .debug$S

#3 .text

#4 .debug$S

#5 .rdata

#6 .text

#7 .debug$S

#8 .debug$T

OBJ 비교할 때

debug 섹션은 제외!

Page 73: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

처리 원시소스 결과소스

원시OBJ 결과OBJ =

Page 74: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

원시OBJ 결과OBJ ≠

DUMPBIN

Page 75: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

처리 원시소스 비교 OK 같음

다름

Page 76: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

다른 함수 찾기

원인 파악 툴 버그

소스 문제

플래그 켬/끔 오류

Page 77: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

#include “show.h” //#include “Flags.h” void show() { #ifdef _QUEST_SYSTEM ui.quest.print(…); ui.questDlg.show(); #endif }

오류의 예

Page 78: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

ASSERT 매크로 등에 있음!

검증 단계의 unifdef 는 행을 유지하도록.

__LINE__

__TIME__

작업 전에만 지웠다가 다시 살림.

Page 79: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

분석 처리 검증 도입 결론 결과

Page 80: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

제거 플래그 후보 선택

작업자의 리뷰

처리 / 검증 / 커밋

자동화 자동화

Page 81: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

작업자 리뷰에 시간이 들기 때문에

리뷰 플래그 개수를 한번에 300~500 개로 유지

Page 82: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

6 번의 플래그 제거 작업

총 2,107 개의 플래그 제거

Page 83: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012
Page 84: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

2,309 파일에서

191,979 라인 제거

Page 85: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

90%

10%

라인

코드 제거

Page 86: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

작성한 툴

분석

처리

검증

Track

Uniform

CompareBin

소스 & SVN 에서 정보 수집

Unifdef + 추가 소스 처리

OBJ 파일 동일 검사

BatchRun 플래그 제거 및 검증을 일괄 실행

Page 87: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

작성한 툴

분석

처리

검증

Track

Uniform

CompareBin

소스 & SVN 에서 정보 수집

Unifdef + 추가 소스 처리

OBJ 파일 동일 검사

BatchRun 플래그 제거 및 검증을 일괄 실행

총 LOC:

1500

Page 88: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012
Page 89: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012
Page 90: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

분석 처리 검증 도입 결론 결과

Page 91: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

불필요한 #if - #endif 제거는

소스 코드를 깔끔하게 유지하는데 도움!

Page 92: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

소스의 유지보수성을 확보하는 작업을

자동화 시키고 신뢰성 있게 만드는 것이 중요!

Page 93: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

자동화된 솔루션은 반복해서 사용할 수 있어

계속해서 도움을 받을 수 있음!

Page 94: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

분석은 처리 뿐 아니라 대상을 바라보는

다른 관점을 제시하는 데에도 도움을 줌!

Page 95: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

분석, 수행, 검증의 틀을

코드 / 데이터를 개선하는데 사용해보자!

Page 96: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

문제되는 이름 추리기

소스에서 자동 변경

빌드 테스트

자동화된 Rename 리팩토링 ?

Page 97: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

여러분들도!

Page 98: 자동화된 소스 분석, 처리, 검증을 통한 소스의 불필요한 #if - #endif 제거하기 NDC2012

감사합니다!