83
코드 생성을 사용해 개발 속도 높이기 김이선 (veblush at neople | gmail) 네오플 던파개발실

코드 생성을 사용해 개발 속도 높이기 NDC2011

Embed Size (px)

Citation preview

Page 1: 코드 생성을 사용해 개발 속도 높이기 NDC2011

코드 생성을 사용해

개발 속도 높이기

김이선 (veblush at neople | gmail)

네오플 던파개발실

Page 2: 코드 생성을 사용해 개발 속도 높이기 NDC2011

BNB 프로그래머

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

버블파이터 프로토타입

리드 프로그래머

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

던전엔파이터 테크니컬 디렉터

게임 프로그래밍 10년차

Page 3: 코드 생성을 사용해 개발 속도 높이기 NDC2011

생산성!

Page 4: 코드 생성을 사용해 개발 속도 높이기 NDC2011

생산성은 왜?

Page 5: 코드 생성을 사용해 개발 속도 높이기 NDC2011

1. enum 으로 보는 코드 생성

2. CodeGen 3. 에버플래닛의 사용 예

Page 6: 코드 생성을 사용해 개발 속도 높이기 NDC2011

enum Fruit { apple = 1, banana, grape };

Page 7: 코드 생성을 사용해 개발 속도 높이기 NDC2011
Page 8: 코드 생성을 사용해 개발 속도 높이기 NDC2011

const WChar* Fruit_strs[] = { L"apple", L"banana", L"grape" }; void fillValue(CComboBox* cb) { cb->Clear(); for (int i=0; i<_countof(Fruit_str); i++) cb->AddString(Fruit_strs[i]); }

Page 9: 코드 생성을 사용해 개발 속도 높이기 NDC2011

enum 에게 필요한 것은?

Page 10: 코드 생성을 사용해 개발 속도 높이기 NDC2011

enum ↔ 문자열 String toString(Fruit f)

banana(2) <-> L"banana"

Page 11: 코드 생성을 사용해 개발 속도 높이기 NDC2011

멤버 iteration for (f in Fruit) { print f } apple, banana, grape

Page 12: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Macro | Template 이라면?

Page 13: 코드 생성을 사용해 개발 속도 높이기 NDC2011

ENUM_BEGIN(Fruit) ENUM_V(apple, 1) ENUM(banana) ENUM(grape) ENUM_END(Fruit)

Page 14: 코드 생성을 사용해 개발 속도 높이기 NDC2011

#define ENUM_BEGIN(t) \ char* t ## _table [] = { #define ENUM(n) #n, #define ENUM_END(t) };

Page 15: 코드 생성을 사용해 개발 속도 높이기 NDC2011

적은 비용. 외부 의존성 낮음. 때문에 좋은 해결책이기도 하다

Page 16: 코드 생성을 사용해 개발 속도 높이기 NDC2011

기능 추가에 유연하지 않음. 코드 마술이 늘 쉬운 것만은 아님

Page 17: 코드 생성을 사용해 개발 속도 높이기 NDC2011

기술 코드

C++ 헤더 코드

C++ 소스 코드

코드 생성

<Enum name="Fruit"> <C n="apple"/> <C n="banana"/> <C n="grape"/> </Enum>

struct Fruit { enum T { apple, banana, grape }; }; String toString(Fruit::T v) { … } void fromString(WChar* str, Fruit::T* v) { … }

Page 18: 코드 생성을 사용해 개발 속도 높이기 NDC2011

구현 기능에 제한이 없음 코드로 할 수 있다면 뭐든지!

Page 19: 코드 생성을 사용해 개발 속도 높이기 NDC2011

코드 생성 툴에 종속성이 생김 개발 과정에 꼭 필요한 툴 추가

Page 20: 코드 생성을 사용해 개발 속도 높이기 NDC2011

구현 가능성 > 툴 종속성

Page 21: 코드 생성을 사용해 개발 속도 높이기 NDC2011

1. enum 으로 보는 코드 생성

2. CodeGen 3. 에버플래닛의 사용 예

Page 22: 코드 생성을 사용해 개발 속도 높이기 NDC2011

CodeGen ?

코드 생성을 수행하는 Visual Studio 플러그인

(C# LOC:3K)

Page 23: 코드 생성을 사용해 개발 속도 높이기 NDC2011

소스 작성 중

CodeGen 코드 작성

CodeGen 플러그인 실행

소스 작업 계속

C++ 코드 생성

Page 24: 코드 생성을 사용해 개발 속도 높이기 NDC2011

CodeGen 데모

Page 26: 코드 생성을 사용해 개발 속도 높이기 NDC2011

소스 편집 중에 바로 코드 생성

Page 27: 코드 생성을 사용해 개발 속도 높이기 NDC2011

생성된 코드를 바로 확인! Intellisense!

Page 28: 코드 생성을 사용해 개발 속도 높이기 NDC2011

빌드 자체에는 툴 종속성이 없음

Page 29: 코드 생성을 사용해 개발 속도 높이기 NDC2011

작업 코드 중간에 들어갈 수 있음

Page 30: 코드 생성을 사용해 개발 속도 높이기 NDC2011

코드 생성을 위해 별도 파일 불필요

Page 31: 코드 생성을 사용해 개발 속도 높이기 NDC2011

유저 코드 삽입이 자연스러움

Page 32: 코드 생성을 사용해 개발 속도 높이기 NDC2011

코드 생성으로 얻는 것?

Page 33: 코드 생성을 사용해 개발 속도 높이기 NDC2011

빠르게 원하는 기능 구현 구현 코드는 CodeGen 이 생성! 프로그래머는 내용에 집중!

Page 34: 코드 생성을 사용해 개발 속도 높이기 NDC2011

신뢰성/일관성 있는 코드 기계적으로 생성하는 코드!

Page 35: 코드 생성을 사용해 개발 속도 높이기 NDC2011

사소하지만 필요한 기능

Page 36: 코드 생성을 사용해 개발 속도 높이기 NDC2011

<Enum name="Fruit" dllDecl="LibDecl"> <Const name="apple" value="1"/> <Const name="banana"/> <Const name="grape"/>

struct LibDecl Fruit // LibDecl=__declspec(dllexport) … { enum T { apple = 1, banana, grape,

라이브러리 형태 지원

Page 37: 코드 생성을 사용해 개발 속도 높이기 NDC2011

<!--! 과일을 나타냅니다 --> <Enum name="Fruit"> <Const name="apple" value="1" comment="사과"/> <Const name="banana" comment="바나나는 맛있어"/>

//! 과일을 나타냅니다 struct Fruit { enum T { apple = 1, //!< 사과 banana, //!< 바나나는 맛있어

doxygen 주석 붙이기

Page 38: 코드 생성을 사용해 개발 속도 높이기 NDC2011

<Enum name="Fruit"> <Const name="apple" value="1"/> … <HText><![CDATA[ Bool isMyFavorate(Fruit::T v); ]]></HText>

struct Fruit { enum T … Bool isMyFavorate(Fruit::T v); };

생성된 코드에 유저 코드 삽입

Page 39: 코드 생성을 사용해 개발 속도 높이기 NDC2011

주의사항?

Page 40: 코드 생성을 사용해 개발 속도 높이기 NDC2011

문법은 확장 가능하도록! 유연하게! 일반적인 문법! XML?

Page 41: 코드 생성을 사용해 개발 속도 높이기 NDC2011

생성된 코드가 수정되지 않게! 기계적인 느낌이 나도록 생성? #pragma region?

Page 42: 코드 생성을 사용해 개발 속도 높이기 NDC2011

모두가 같은 버전의 툴! 예전버전을 사용하면 곤란. 자동 업데이트?

Page 43: 코드 생성을 사용해 개발 속도 높이기 NDC2011

1. enum 으로 보는 코드 생성

2. CodeGen 3. 에버플래닛의 사용 예

Page 44: 코드 생성을 사용해 개발 속도 높이기 NDC2011

기계적이고 반복적인 부분에 적용. 적용 영역이 지속적으로 확대.

적용한 부분은?

Page 45: 코드 생성을 사용해 개발 속도 높이기 NDC2011

사용한 CodeGen 영역

Enum

Packet Data

DbCall DbRowset

Page 46: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Enum : 열거형 확장

문자열 변환 기능 추가 멤버 순회 기능 추가

Page 47: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Enum : CodeGen

<Enum name="Fruit"> <Const name="apple" value="1"/> <Const name="banana"/> <Const name="grape"/> </Enum>

Page 48: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Enum : Generated

struct Fruit { enum T { apple=1, banana, grape }; … }; String toString(…); fromString(…);

Page 49: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Enum : Usage

toString(Fruit::banana); // "banana" fromString<Fruit::T>(L"grape"); // 3 Fruit::enumCount; // 3 Fruit::enumValue[1]; // Fruit::banana

Page 50: 코드 생성을 사용해 개발 속도 높이기 NDC2011

template <class EnumType> void fillValue(CComboBox* cb) { cb->Clear(); for (size_t i=0; i<EnumType::enumCount; i++) cb->AddString(EnumType::enumStr[i]); };

Page 51: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Packet : 패킷 Serialization

패킷 내용을 구조체로 구성 Byte Serialization 코드 작성

Page 52: 코드 생성을 사용해 개발 속도 높이기 NDC2011

패킷은 지속적인 작업 귀찮은 Serialization 코드 작업

Page 53: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Packet : CodeGen

<Packet name="TestPacket"> <Field name="code" type="Int4"/> <Field name="name" type="String"/> </Packet>

Page 54: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Packet : Generated

struct TestPacket : public Packet { TestPacket(Int4 code, String name); virtual Int4 getStreamSize() const; virtual void readFrom(Stream& is); virtual void writeTo(Stream& os); public: Int4 code; String name; };

Page 55: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Packet : Usage

send() { TestPacketPtr p = new TestPacket; p->code = 1; p->name = L"Test"; sendPacket(p); // or sendPacket(new TestPacket(1, L"Test")); } recv(TestPacket* p) { p->code; p->name; }

Page 56: 코드 생성을 사용해 개발 속도 높이기 NDC2011

패킷 멤버 모두가 단순 타입이면 read/write 를 단순 memcpy로

코드 생성이라 최적화 전략 가능

Page 57: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Packet : Optimized

// Member Int4 userId; Int4 itemId; Int4 presetId; Vector2 pos;

// Read is >> userId; is >> itemId; is >> presetId; is >> pos;

// Read (Optimized) is.read(this, sizeof(TestPacket));

Page 58: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Data : POD 확장

멤버 변수를 XML | 바이트 스트림으로

Serialization

Page 59: 코드 생성을 사용해 개발 속도 높이기 NDC2011

아이템, 퀘스트 등을 기술하는데 이러한 구조체가 필요

이러한 데이터는 파일에 있기 때문에 I/O 코드 필요

Page 60: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Data: CodeGen

<Data name="Item"> <Field name="id" type="Int4"/> <Field name="name" type="String"/> <Field name="desc" type="String"/> <Field name="level" type="Int4" init="0"/> <Field name="itemClass" type="ItemClass::T" init="ItemClass::kMisc"/> </Data>

Page 61: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Data : Generated

struct Item { Item(); void readFrom(Stream& is); void writeTo(Stream& os) const; void readFrom(XmlElement* xel); void writeTo(XmlElement* xel) const; Int4 id; String name; … };

Page 62: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Data : Usage

Item item; item.readFrom(xml); item.id; item.name;

<Item id="100" name="무쇠 갑옷" desc="무척강하다" itemClass="armor" />

Page 63: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Data CodeGen 데모

Pet 구조체 만들기 ItemSpawn 은 이미 있음

Page 64: 코드 생성을 사용해 개발 속도 높이기 NDC2011

http://www.youtube.com/watch?v=kRrYj3Lx5Pw

Page 65: 코드 생성을 사용해 개발 속도 높이기 NDC2011

용량 16% 속도 x3

<Pet id="10" name="monkey" food="banana" > <Items> <ItemSpawn itemId="100" /> <ItemSpawn itemId="200" count="5" /> </Items> </Pet>

07 0a 00 00 00 06 00 00 00 6d 00 6f 00 6e 00 6b 00 65 00 79 00 02 00 00 00 02 00 00 00 00 64 00 00 00 01 c8 00 00 00 05 00 00 00

Page 66: 코드 생성을 사용해 개발 속도 높이기 NDC2011

개발 때는 XML 사용 포맷 개방, 공동 작업!

배포 때는 Binary 사용 포맷 고정, 빠른 속도, 보안!

Page 67: 코드 생성을 사용해 개발 속도 높이기 NDC2011

DbCall : SQL/SP 호출

호출 전후에 파라미터 변수 바인딩

Page 68: 코드 생성을 사용해 개발 속도 높이기 NDC2011

DbCall : CodeGen

<DbCall name="DcLogin" spName="spLogin"> <Param name="id" type="String" maxLen="24"/> <Param name="ret" type="Int4" io="out"/> </DbCall>

CREATE PROCEDURE spLogin @id as nvarchar(24), @ret as int OUTPUT

Page 69: 코드 생성을 사용해 개발 속도 높이기 NDC2011

DbCall : Generated

struct DcLogin { static HRESULT exec(DbSession* s, const String& id, Int4* ret); struct Param : public DbCallParam { String id; Int4 ret; virtual HRESULT exec(DbSession* s); }; };

Page 70: 코드 생성을 사용해 개발 속도 높이기 NDC2011

DbCall : Usage

hr = DcLogin::exec(s, "userid", &ret); // or p = new DcLogin::Param; p->id = "userid"; p->exec(s); p->ret;

CREATE PROCEDURE spLogin @id as nvarchar(24), @ret as int OUTPUT

Page 71: 코드 생성을 사용해 개발 속도 높이기 NDC2011

DbRowset : Rowset 읽기

Rowset 을 읽어 컬럼 변수에 바인딩

Page 72: 코드 생성을 사용해 개발 속도 높이기 NDC2011

DbRowset : CodeGen

<DbRowset name="DrInven"> <Field name="id" type="Int4"/> <Field name="count" type="Int4"/> <Field name="expireTime" type="DateTime4"/> </DbRowset>

SELECT id, count, expireTime FROM tblInven WHERE charId=1

Page 73: 코드 생성을 사용해 개발 속도 높이기 NDC2011

DbRowset : Generated

struct DrInven : public DbRowset { Int4 id; Int4 count; DateTime4 expireTime; protected: virtual HRESULT onInit(...); virtual void onNext(); };

Page 74: 코드 생성을 사용해 개발 속도 높이기 NDC2011

DbRowset : Usage

DrInvenPtr rs; hr = DcInvenGet::exec(dbSession, &rs); while (rs->next()) { rs->id; rs->count; rs->expireTime; }

SELECT id, count, expireTime FROM tblInven WHERE charId=1

Page 75: 코드 생성을 사용해 개발 속도 높이기 NDC2011

적용 비중?

Page 76: 코드 생성을 사용해 개발 속도 높이기 NDC2011

사용한 CodeGen 개수

0 200 400 600 800 1000

Enum

Packet

Data

DbCall

DbRowset

Page 77: 코드 생성을 사용해 개발 속도 높이기 NDC2011

CodeGen 코드 라인 수

원본코드

10,946

생성코드

69,391

x7

Page 78: 코드 생성을 사용해 개발 속도 높이기 NDC2011

생성코드의 비중

생성코드

69,391

그외코드

559,517

11%

Page 79: 코드 생성을 사용해 개발 속도 높이기 NDC2011

Total: 11261 revs

Packet:

1646 revs (14%) x2

Data/Item:

215 revs (2%) x215

Page 80: 코드 생성을 사용해 개발 속도 높이기 NDC2011

결론

Page 81: 코드 생성을 사용해 개발 속도 높이기 NDC2011

코드 생성은 생각보다 많은 영역에 사용 가능 기대보다 많은 코드 작성을 대신

Page 82: 코드 생성을 사용해 개발 속도 높이기 NDC2011

시도해보자!

Page 83: 코드 생성을 사용해 개발 속도 높이기 NDC2011

감사합니다!