SlideShare a Scribd company logo
1 of 89
낡은 코드 (Legacy Code) 로  효과적으로 일하기 박일 (parkpd.egloos.com)
낡은 코드 (Legacy Code)?
낡은 코드 (Legacy Code) 가 뭐죠 ? ,[object Object],[object Object],[object Object],[object Object],[object Object]
' 소프트웨어 변경 ' 의 어려움 ,[object Object],[object Object]
배경 ,[object Object],if (m_nCriticalError) return; m_nCriticalError=nErrorCode; switch (nEvent) { case FD_READ: case FD_FORCEREAD: if (GetLayerState()==connecting  && !nErrorCode)
소프트웨어 변경의 두 가지 방법 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
낡은 코드의 위험성 ,[object Object],[object Object],[object Object],[object Object]
코드 변경 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
리팩토링이 필요하다
변경의 모순 (Paradox of Change) ,[object Object],[object Object],[object Object],[object Object],[object Object]
UnitTest  가 필요하다
경고 ,[object Object],[object Object],[object Object],[object Object],[object Object]
작업의 모순 (Paradox of Work) ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
억울하지 않은지 ? ,[object Object],[object Object],[object Object]
낡은 코드에 테스트 추가하기
낡은 코드 변경 알고리즘 ,[object Object],[object Object],[object Object],[object Object],[object Object]
변경 지점 찾기 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
변경 지점 찾기 ,[object Object],class CMonster : public CActor { public: void Attack(CActor*); void BeAttacked(CActor*); }; class CBoss : public CMonster { public: void Attack(CActor*); void BeAttacked(CActor*); }; void CPlayer::Attack(CBoss* pTarget) { if (CanHit(pTarget)) { pTarget ->BeAttacked(this); } };
테스트 할 곳 찾기 ,[object Object],[object Object],[object Object],[object Object],void CPlayer::Attack(CBoss* pTarget) { if (CanHit(pTarget)) { pTarget ->BeAttacked(this); } };
의존 제거하기 ,[object Object],[object Object]
결합의 종류 ,[object Object],[object Object],[object Object],[object Object],[object Object]
의존 제거하기 ,[object Object],[object Object],[object Object]
테스트 작성 TEST_FIXTURE(FixtureActor, 70CantHit70) { pActor1->m_Level = 70; pActor2->m_Level = 70; CHECK(!pActor1->CanHit(pActor2)); } TEST_FIXTURE(FixtureActor, 78LevelCanHit70) { pActor1->m_Level = 78; pActor2->m_Level = 70; CHECK(pActor1->CanHit(pActor2)); }
리팩토링 혹은 변경 ,[object Object],[object Object]
의존 제거하기
의존 제거하기  0  단계 인터페이스 추출 (Extract Interface) 구현 추출 (Extract Implementor)
인터페이스 추출 ,[object Object],[object Object],[object Object],[object Object]
인터페이스 추출 ,[object Object],[object Object],[object Object]
인터페이스 추출 순서 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
일반 함수 (Non-Virtual) 오버라이딩 문제 ,[object Object],class CMonster : public CActor { public: void Attack(CActor*); void BeAttacked(CActor*); }; class CBoss : public CMonster { public: void Attack(CActor*); void BeAttacked(CActor*); }; void CPlayer::Attack(CBoss* pTarget) { if (CanHit(pTarget)) { pTarget ->BeAttacked(this); } }
일반 함수 (Non-Virtual) 오버라이딩 문제 ,[object Object],class CMonster : public CActor { public: void Attack(CActor*); virtual void BeAttacked(CActor*); }; class CBoss : public CMonster { public: void Attack(CActor*); void BeAttacked(CActor*); }; void CPlayer::Attack(CBoss* pTarget) { if (CanHit(pTarget)) { pTarget->BeAttacked(this); } } CBoss* pBoss = new CBoss; pBoss->BeAttack(pPlayer);
일반 함수 (Non-Virtual) 오버라이딩 문제 ,[object Object],[object Object],[object Object],[object Object]
구현 추출 (Extract Implementor) ,[object Object]
의존 제거하기  1  단계 함수에 매개변수 추가 (Parameterize Method) 함수 추출 후 오버라이딩 (Extract and Override Call)
함수에 매개변수 추가 ,[object Object],[object Object]
예  :  몬스터가 공격 당할 때 void CMonster ::Attack(CActor* pTarger) { double angerBonus = 1.0; if (m_VeryAngry) { CAngryData* pAngry = new CAngryData(this); angerBonus = pAngry->GetBonus(pTarget); } void CMonster ::Attack(CActor* pTarger) { CAngryData* pAngryData = NULL; if (m_VeryAngry) { pAngryData =  new CAngryData(); } Attack(pTarget, pAngryData); void CMonster ::Attack(CActor* pTarger, CAngryData* pAngryData) { double angerBonus = 1.0; if (pAngryData) { angerBonus = pAngry->GetBonus(pTarget);
함수에 매개변수 추가  -  단계 ,[object Object],[object Object],[object Object]
함수 추출 후 오버라이딩 ,[object Object]
함수 추출 후 오버라이딩  -  단계 ,[object Object],[object Object],[object Object]
함수 추출 후 오버라이딩  -  예 void CPlayer::Attack(CActor* pTarger) { ... WSASend(m_Handle...); //  공격과 함께 데미지 표시 //  변경 후 void CPlayer::Attack(CActor* pTarger) { ... m_Socket.Send(...); //  공격과 함께 데미지 표시 class CSocket { void Send(...) { WSASend(m_Handle, ...); class CMockSocket : public CSocket { void Send(...) { // do nothing
더 할 수 있다 class CMockSocket : public CSocket { void Send(int packetType) { m_PacketRecorder.Push(packetType); TEST_FIXTURE(FixtureBattle, PlayerSendBeAttackedPacket) { pMonster->Attack(pPlayer); CHECK(pPlayer->IsSentPacket(PacketType::BeAttacked)); 이런 걸 감지 변수 (sensing)  이라고 한다 .
의존 제거하기  2  단계 ,[object Object],[object Object],[object Object],[object Object]
Seams? ,[object Object],[object Object]
Seam  예제 void CPlayer::Logout() { g_Database.SavePlayerStatus(this); ... } CDatabase::SavePlayerStatus()  를 하기 위해서는 꼭  DB  에 접근해야 하고 ,  시간이  5 초 이상 걸린다고 하면 ?
가상함수 이용  -  예 CPlayer::CPlayer(CDatabase* pDatabase) : m_pDatabase(pDatabase) {} void CPlayer::Logout() { m_pDatabase->SavePlayerStatus(this); // CDatabase* CPlayer::m_pDatabase; } //  아까의  CMockSocket  과 비슷한 맥락임 . class CMockDatabase : public CDatabase { bool SavePlayerStatus(CPlayer* pPlayer) { return true; } class CMockPlayer : public CPlayer... CMockPlayer* pPlayer1 = new CMockPlayer(new CMockDatabase());
가상함수 이용 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
define  을 이용한 코드 변경  -  예 void CPlayer::Logout() { CDatabase::Inst().SavePlayerStatus(this);  // singleton  사용 ... } class CDatabase { static CDatabase& Inst() { #ifdef __UnitTest__ if (m_bTesting) { static CMockDatabase s; return s; } #endif static CDatabase s; return s; }
define  을 이용한 코드 변경 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
링크  -  예 class CDatabase { void SavePlayerStatus(CActor* pActor) { sql_query(“update ...”); #ifndef __UnitTest__ #pragma comment( lib, "some_sql_library") #else #pragma comment( lib, "fake_sql_library") #endif
링크 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
의존 제거하기  3  단계 정적 함수 노출하기  (Expose Static Method)
예  : CPlayer  의 공격 코드 class CPlayer : public CActor { bool CanHit(CActor*); void Attack(CActor* pTarget); ... void CPlayer::Attack(CActor* pTarget) { if (CanHit(pTarget)) { pTarget->BeAttacked(this); } }
어려운 점 ,[object Object],[object Object]
CPlayer  의 공격 코드  -  수정판 class CPlayer : public CActor { static bool CanHit (CActor* pAttacker, CActor* pTarget); void Attack(CActor* pTarget); ... void CPlayer::Attack(CActor* pTarget) { if (CanHit(this, pTarget)) { pTarget->BeAttacked(this); } TEST_FIXTURE(FixtureBattle, PlayerCanHitMonster) { CHECK(CPlayer::CanHit(pPlayer, pMonster)); pPlayer->m_Level = 40; pMonster->m_Level = 80; CHECK(!CPlayer::CanHit(pPlayer, pMonster)); class CPlayer : public CActor { bool CanHit(CActor*); void Attack(CActor* pTarget); ... void CPlayer::Attack(CActor* pTarget) { if (CanHit(pTarget)) { pTarget->BeAttacked(this); } }
코드가 이상하지 않나 ? ,[object Object],[object Object],[object Object],[object Object],[object Object]
의존 제거하기  4  단계 템플릿 재정의 (Template Redefinition)
예  : test  코드 실행 중  dead lock  이 걸려요 . class CPlayer : public CActor { CMutexLock m_Lock;  // recursive lock  아님 void BeAttacked(CActor* pAttacker) { m_Lock.Lock(); pAttacker.Lock(); pAttacker->BeAttacked();
해결 방법 class CMutexLockImpl : public ILock { void Lock() { WaitForSingleObject(...); class CDummyLockImpl  : public ILock { void Lock() { // do nothing class CLockImp<typename T> { T m_Lock; void Lock() { m_Lock.Enter(); } }; typedef CLockImp<CMutexLockImpl> CMutexLock; typedef CLockImp<CDummyLockImpl> CDummyLock;
더 할 수 있다 ! class CDummyLockImpl : public ILock { void Lock() { if (CDummyLockImpl::Inst().IsDeadLock()) { throw CException(); 테스트를 하면서 , deadlock  를 감지할 수 있다
그 외 임의성 테스트
임의성 테스트 ,[object Object],int GetRand() const { #if defined(_DEBUG) && defined(UnitTestDefined) if (bSettedRandomValue) { return MyTestUnit ::Inst().m_Random; } #endif return ::rand(); } TEST_FIXTURE(FixtureUser2, CheckMagicCritical){ int playerLevel = 60; const double bonus = 50.0; MyTestUnit ::Inst().m_Random = 100.0; //  무조건 성공 . CHECK_EQUAL(true, IsAttackCritical(player, playerLevel, bonus)); MyTestUnit ::Inst().m_Random = 0.0; //  무조건 실패 . CHECK_EQUAL(false, IsAttackCritical(...));
다른 것들 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
테스트의 종류
테스트의 종류 스토리 테스트 비즈니스 의도 ( 제품 설계 ) 사용성 테스팅 탐색적 테스팅 단위 테스트 개발자 의도 ( 코드 설계 ) 특성 테스팅 보안 테스팅 부하 테스팅 조합 테스팅 … 자동 자동 수동 도구
특성 테스트 ,[object Object],[object Object],[object Object],[object Object]
특성 테스트 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
예  :  공격 코드에 특성 테스트를 붙인다면 ? void CPlayer::BeAttacked(CActor* pAttacker) { int damage = GetDamageFromAttacker(pAttacker); TEST_FIXTURE(FixtureAttack, GetDamageFromAttacker) { pPlayer->m_Level = 40; CHECK_EQUAL(760, pPlayer->GetDamageFromAttacker(pMonster); pPlayer->m_Level = 50; CHECK_EQUAL(400, pPlayer->GetDamageFromAttacker(pMonster); pPlayer->m_Level = 60; CHECK_EQUAL(223, pPlayer->GetDamageFromAttacker(pMonster); pPlayer->m_Level = 70; CHECK_EQUAL(0, pPlayer->GetDamageFromAttacker(pMonster); }
더 할 수 있다 . TEST_FIXTURE(FixtureAttack, GetDamage) { struct TestData { int m_Level; int m_Expect; }; TestData data[] = { {40, 760}, {50, 400}, {60, 223}, {70, 0}, {80, 0} }; for (int i = 0; i < sizeof(TestData[]) / sizeof(TestData); ++i) { TestData& d = data[i]; pPlayer->m_Level = d.m_Level; CHECK_EQUAL(d.m_Expect, pPlayer->GetDamager(pMonster));
테스트 코드의 리팩토링 ,[object Object],[object Object]
처음 테스트 붙이는 요령
처음 테스트 붙이는 요령 ,[object Object],[object Object],[object Object],[object Object]
처음 테스트 붙이는 요령 ,[object Object],[object Object],[object Object],[object Object]
처음 테스트 붙이는 요령 ,[object Object],[object Object],[object Object]
처음 테스트 붙이는 요령 ,[object Object],[object Object]
class CTest{ protected: int m_Test; void Test() {} }; class CMockTest : public CTest { public: using CTest::m_Test; //  부모 클래스의 멤버를  public  으로 쓰겠다 . using CTest::Test; }; TEST(AccessTest) { CTest a; //a.m_Test = 1;  // protected  멤버 변수 접근할 수 없음 . //a.Test();  // protected  멤버 함수 접근할 수 없음 . CMockTest* pMockTest = (CMockTest*)(&a); pMockTest->m_Test = 1;  // CMockTest  로 강제 캐스팅  ->  접근 가능 pMockTest->Test(); // a  가  CMockTest  객체가 아니어도 이렇게 쓸 수 있다는 점에 주의 return 0; }
아니 ?  은닉화 (encapsulation)  은 ? ,[object Object],[object Object]
UnitTest  가 아닐 조건 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
프로그래머를 위한  UnitTest ,[object Object],[object Object],[object Object]
프로그래머를 위한  UnitTest ,[object Object],[object Object],[object Object],[object Object]
Test Driven Debugging? ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Test Driven Debugging!! ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Branch & Merge ,[object Object],[object Object],[object Object],[object Object]
UnitTest  는 극히 일부분입니다 ,[object Object],[object Object]
다른 팀과의 협조 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
UnitTest  결과를  email  로 축적 ,[object Object],[object Object],[object Object]
References ,[object Object],[object Object],[object Object],[object Object]
References ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Books
감사합니다 .

More Related Content

What's hot

자바8 나머지 공개
자바8 나머지 공개자바8 나머지 공개
자바8 나머지 공개Sungchul Park
 
C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기Heo Seungwook
 
TDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDDTDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDDSuwon Chae
 
Api design for c++ 6장
Api design for c++ 6장Api design for c++ 6장
Api design for c++ 6장Ji Hun Kim
 
인수테스트 주도 개발
인수테스트 주도 개발인수테스트 주도 개발
인수테스트 주도 개발Jaehoon Oh
 
당신의 디버깅에 니코니코니
당신의 디버깅에 니코니코니당신의 디버깅에 니코니코니
당신의 디버깅에 니코니코니Lusain Kim
 
KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기Ryan Park
 
[C++ lab] 9. 디버깅 테크닉
[C++ lab] 9. 디버깅 테크닉[C++ lab] 9. 디버깅 테크닉
[C++ lab] 9. 디버깅 테크닉MinGeun Park
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)문익 장
 
JUnit 지원 라이브러리 소개
JUnit 지원 라이브러리 소개JUnit 지원 라이브러리 소개
JUnit 지원 라이브러리 소개Hyunil Shin
 
시작하자 단위테스트
시작하자 단위테스트시작하자 단위테스트
시작하자 단위테스트YongEun Choi
 
Visual studio 사용 설명서(고급)
Visual studio 사용 설명서(고급)Visual studio 사용 설명서(고급)
Visual studio 사용 설명서(고급)Lusain Kim
 
Spring 교육 자료
Spring 교육 자료Spring 교육 자료
Spring 교육 자료Hyosang Hong
 
스프링보다 중요한 스프링 이야기
스프링보다 중요한 스프링 이야기스프링보다 중요한 스프링 이야기
스프링보다 중요한 스프링 이야기Sungchul Park
 
TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기Wonchang Song
 
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)Suwon Chae
 
Windows Debugging Technique #2
Windows Debugging Technique #2Windows Debugging Technique #2
Windows Debugging Technique #2Wooseok Seo
 

What's hot (18)

자바8 나머지 공개
자바8 나머지 공개자바8 나머지 공개
자바8 나머지 공개
 
C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기C++ 프로젝트에 단위 테스트 도입하기
C++ 프로젝트에 단위 테스트 도입하기
 
TDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDDTDD&Refactoring Day 03: TDD
TDD&Refactoring Day 03: TDD
 
Api design for c++ 6장
Api design for c++ 6장Api design for c++ 6장
Api design for c++ 6장
 
인수테스트 주도 개발
인수테스트 주도 개발인수테스트 주도 개발
인수테스트 주도 개발
 
당신의 디버깅에 니코니코니
당신의 디버깅에 니코니코니당신의 디버깅에 니코니코니
당신의 디버깅에 니코니코니
 
KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기KGC2010 - 낡은 코드에 단위테스트 넣기
KGC2010 - 낡은 코드에 단위테스트 넣기
 
[C++ lab] 9. 디버깅 테크닉
[C++ lab] 9. 디버깅 테크닉[C++ lab] 9. 디버깅 테크닉
[C++ lab] 9. 디버깅 테크닉
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)
 
JUnit 지원 라이브러리 소개
JUnit 지원 라이브러리 소개JUnit 지원 라이브러리 소개
JUnit 지원 라이브러리 소개
 
C++ api design 품질
C++ api design 품질C++ api design 품질
C++ api design 품질
 
시작하자 단위테스트
시작하자 단위테스트시작하자 단위테스트
시작하자 단위테스트
 
Visual studio 사용 설명서(고급)
Visual studio 사용 설명서(고급)Visual studio 사용 설명서(고급)
Visual studio 사용 설명서(고급)
 
Spring 교육 자료
Spring 교육 자료Spring 교육 자료
Spring 교육 자료
 
스프링보다 중요한 스프링 이야기
스프링보다 중요한 스프링 이야기스프링보다 중요한 스프링 이야기
스프링보다 중요한 스프링 이야기
 
TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기
 
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
 
Windows Debugging Technique #2
Windows Debugging Technique #2Windows Debugging Technique #2
Windows Debugging Technique #2
 

Viewers also liked

즉흥연기와프로그래밍
즉흥연기와프로그래밍즉흥연기와프로그래밍
즉흥연기와프로그래밍Ryan Park
 
AIbyExample - Ch7 raven. version 0.8
AIbyExample - Ch7 raven. version 0.8AIbyExample - Ch7 raven. version 0.8
AIbyExample - Ch7 raven. version 0.8Ryan Park
 
Programming Game AI by Example. Ch7. Raven
Programming Game AI by Example. Ch7. RavenProgramming Game AI by Example. Ch7. Raven
Programming Game AI by Example. Ch7. RavenRyan Park
 
나도기술서번역한번해볼까 in NDC10
나도기술서번역한번해볼까 in NDC10나도기술서번역한번해볼까 in NDC10
나도기술서번역한번해볼까 in NDC10Ryan Park
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010Ryan Park
 
나도(기술서)번역한번해볼까
나도(기술서)번역한번해볼까나도(기술서)번역한번해볼까
나도(기술서)번역한번해볼까Ryan Park
 
온라인 게임에서 사례로 살펴보는 디버깅
온라인 게임에서 사례로 살펴보는 디버깅온라인 게임에서 사례로 살펴보는 디버깅
온라인 게임에서 사례로 살펴보는 디버깅Ryan Park
 
Unicode 이해하기
Unicode 이해하기Unicode 이해하기
Unicode 이해하기Ryan Park
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10Ryan Park
 
위대한 게임개발팀의 공통점
위대한 게임개발팀의 공통점위대한 게임개발팀의 공통점
위대한 게임개발팀의 공통점Ryan Park
 
문자셋과 인코딩
문자셋과 인코딩문자셋과 인코딩
문자셋과 인코딩Jaehoon Jung
 
Domain Driven Design Ch7
Domain Driven Design Ch7Domain Driven Design Ch7
Domain Driven Design Ch7Ryan Park
 
Oop design principle SOLID
Oop design principle SOLIDOop design principle SOLID
Oop design principle SOLIDRyan Park
 
Oop design principle
Oop design principleOop design principle
Oop design principleRyan Park
 

Viewers also liked (18)

즉흥연기와프로그래밍
즉흥연기와프로그래밍즉흥연기와프로그래밍
즉흥연기와프로그래밍
 
Taocp1 2 4
Taocp1 2 4Taocp1 2 4
Taocp1 2 4
 
AIbyExample - Ch7 raven. version 0.8
AIbyExample - Ch7 raven. version 0.8AIbyExample - Ch7 raven. version 0.8
AIbyExample - Ch7 raven. version 0.8
 
Unicode
UnicodeUnicode
Unicode
 
Programming Game AI by Example. Ch7. Raven
Programming Game AI by Example. Ch7. RavenProgramming Game AI by Example. Ch7. Raven
Programming Game AI by Example. Ch7. Raven
 
Unicode
UnicodeUnicode
Unicode
 
나도기술서번역한번해볼까 in NDC10
나도기술서번역한번해볼까 in NDC10나도기술서번역한번해볼까 in NDC10
나도기술서번역한번해볼까 in NDC10
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
 
나도(기술서)번역한번해볼까
나도(기술서)번역한번해볼까나도(기술서)번역한번해볼까
나도(기술서)번역한번해볼까
 
온라인 게임에서 사례로 살펴보는 디버깅
온라인 게임에서 사례로 살펴보는 디버깅온라인 게임에서 사례로 살펴보는 디버깅
온라인 게임에서 사례로 살펴보는 디버깅
 
Unicode 이해하기
Unicode 이해하기Unicode 이해하기
Unicode 이해하기
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
 
위대한 게임개발팀의 공통점
위대한 게임개발팀의 공통점위대한 게임개발팀의 공통점
위대한 게임개발팀의 공통점
 
문자셋과 인코딩
문자셋과 인코딩문자셋과 인코딩
문자셋과 인코딩
 
Domain Driven Design Ch7
Domain Driven Design Ch7Domain Driven Design Ch7
Domain Driven Design Ch7
 
Unicode100
Unicode100Unicode100
Unicode100
 
Oop design principle SOLID
Oop design principle SOLIDOop design principle SOLID
Oop design principle SOLID
 
Oop design principle
Oop design principleOop design principle
Oop design principle
 

Similar to 카사 공개세미나1회 W.E.L.C.

About Visual C++ 10
About  Visual C++ 10About  Visual C++ 10
About Visual C++ 10흥배 최
 
안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계Leonardo YongUk Kim
 
Effective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinEffective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinDong Chan Shin
 
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018Kenneth Ceyer
 
Effective c++chapter4
Effective c++chapter4Effective c++chapter4
Effective c++chapter4성연 김
 
100828 [visual studio camp #1] C++0x와 Windows7
100828 [visual studio camp #1] C++0x와 Windows7100828 [visual studio camp #1] C++0x와 Windows7
100828 [visual studio camp #1] C++0x와 Windows7sung ki choi
 
The roadtocodecraft
The roadtocodecraftThe roadtocodecraft
The roadtocodecraftbbongcsu
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스Sungik Kim
 
[0618구경원]초보 게임프로그래머를 위한 c++
[0618구경원]초보 게임프로그래머를 위한 c++[0618구경원]초보 게임프로그래머를 위한 c++
[0618구경원]초보 게임프로그래머를 위한 c++KyeongWon Koo
 
Ai C#세미나
Ai C#세미나Ai C#세미나
Ai C#세미나Astin Choi
 
C++20 Key Features Summary
C++20 Key Features SummaryC++20 Key Features Summary
C++20 Key Features SummaryChris Ohk
 
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 TestOkjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 Testbeom kyun choi
 
S#03 김용현:VS2010으로 마이그레이션
S#03 김용현:VS2010으로 마이그레이션S#03 김용현:VS2010으로 마이그레이션
S#03 김용현:VS2010으로 마이그레이션codercay
 
Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Nam Hyeonuk
 
ModelSim 기초 매뉴얼
ModelSim 기초 매뉴얼ModelSim 기초 매뉴얼
ModelSim 기초 매뉴얼Jihyun Lee
 
Boost라이브러리의내부구조 20151111 서진택
Boost라이브러리의내부구조 20151111 서진택Boost라이브러리의내부구조 20151111 서진택
Boost라이브러리의내부구조 20151111 서진택JinTaek Seo
 
V8 add on with middleware modules
V8 add on with middleware modulesV8 add on with middleware modules
V8 add on with middleware modulesJay Kim
 
Sonarqube 20160509
Sonarqube 20160509Sonarqube 20160509
Sonarqube 20160509영석 조
 
청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기Chris Ohk
 

Similar to 카사 공개세미나1회 W.E.L.C. (20)

About Visual C++ 10
About  Visual C++ 10About  Visual C++ 10
About Visual C++ 10
 
안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계안드로이드 빌드: 설탕없는 세계
안드로이드 빌드: 설탕없는 세계
 
Effective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshinEffective c++ chapter1 2_dcshin
Effective c++ chapter1 2_dcshin
 
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
우아하게 준비하는 테스트와 리팩토링 - PyCon Korea 2018
 
Effective c++chapter4
Effective c++chapter4Effective c++chapter4
Effective c++chapter4
 
100828 [visual studio camp #1] C++0x와 Windows7
100828 [visual studio camp #1] C++0x와 Windows7100828 [visual studio camp #1] C++0x와 Windows7
100828 [visual studio camp #1] C++0x와 Windows7
 
The roadtocodecraft
The roadtocodecraftThe roadtocodecraft
The roadtocodecraft
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스
 
[0618구경원]초보 게임프로그래머를 위한 c++
[0618구경원]초보 게임프로그래머를 위한 c++[0618구경원]초보 게임프로그래머를 위한 c++
[0618구경원]초보 게임프로그래머를 위한 c++
 
Ai C#세미나
Ai C#세미나Ai C#세미나
Ai C#세미나
 
C++20 Key Features Summary
C++20 Key Features SummaryC++20 Key Features Summary
C++20 Key Features Summary
 
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 TestOkjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
 
S#03 김용현:VS2010으로 마이그레이션
S#03 김용현:VS2010으로 마이그레이션S#03 김용현:VS2010으로 마이그레이션
S#03 김용현:VS2010으로 마이그레이션
 
Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약
 
ModelSim 기초 매뉴얼
ModelSim 기초 매뉴얼ModelSim 기초 매뉴얼
ModelSim 기초 매뉴얼
 
Boost라이브러리의내부구조 20151111 서진택
Boost라이브러리의내부구조 20151111 서진택Boost라이브러리의내부구조 20151111 서진택
Boost라이브러리의내부구조 20151111 서진택
 
V8 add on with middleware modules
V8 add on with middleware modulesV8 add on with middleware modules
V8 add on with middleware modules
 
Sonarqube 20160509
Sonarqube 20160509Sonarqube 20160509
Sonarqube 20160509
 
llvm 소개
llvm 소개llvm 소개
llvm 소개
 
청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기
 

More from Ryan Park

OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.Ryan Park
 
프로그램은 왜 실패하는가 1장
프로그램은 왜 실패하는가 1장프로그램은 왜 실패하는가 1장
프로그램은 왜 실패하는가 1장Ryan Park
 
UnitTest, Tdd For Games Kgc2007 ParkPD
UnitTest, Tdd For Games Kgc2007 ParkPDUnitTest, Tdd For Games Kgc2007 ParkPD
UnitTest, Tdd For Games Kgc2007 ParkPDRyan Park
 
Agile Test Driven Development For Games What, Why, And How
Agile Test Driven Development For Games What, Why, And HowAgile Test Driven Development For Games What, Why, And How
Agile Test Driven Development For Games What, Why, And HowRyan Park
 
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...
Agd   Test Driven Development For Games What, Why, And How)(Game Connect 2006...Agd   Test Driven Development For Games What, Why, And How)(Game Connect 2006...
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...Ryan Park
 

More from Ryan Park (6)

OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.
 
Unicode
UnicodeUnicode
Unicode
 
프로그램은 왜 실패하는가 1장
프로그램은 왜 실패하는가 1장프로그램은 왜 실패하는가 1장
프로그램은 왜 실패하는가 1장
 
UnitTest, Tdd For Games Kgc2007 ParkPD
UnitTest, Tdd For Games Kgc2007 ParkPDUnitTest, Tdd For Games Kgc2007 ParkPD
UnitTest, Tdd For Games Kgc2007 ParkPD
 
Agile Test Driven Development For Games What, Why, And How
Agile Test Driven Development For Games What, Why, And HowAgile Test Driven Development For Games What, Why, And How
Agile Test Driven Development For Games What, Why, And How
 
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...
Agd   Test Driven Development For Games What, Why, And How)(Game Connect 2006...Agd   Test Driven Development For Games What, Why, And How)(Game Connect 2006...
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...
 

카사 공개세미나1회 W.E.L.C.

  • 1. 낡은 코드 (Legacy Code) 로 효과적으로 일하기 박일 (parkpd.egloos.com)
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 10.
  • 11. UnitTest 가 필요하다
  • 12.
  • 13.
  • 14.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23. 테스트 작성 TEST_FIXTURE(FixtureActor, 70CantHit70) { pActor1->m_Level = 70; pActor2->m_Level = 70; CHECK(!pActor1->CanHit(pActor2)); } TEST_FIXTURE(FixtureActor, 78LevelCanHit70) { pActor1->m_Level = 78; pActor2->m_Level = 70; CHECK(pActor1->CanHit(pActor2)); }
  • 24.
  • 26. 의존 제거하기 0 단계 인터페이스 추출 (Extract Interface) 구현 추출 (Extract Implementor)
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34. 의존 제거하기 1 단계 함수에 매개변수 추가 (Parameterize Method) 함수 추출 후 오버라이딩 (Extract and Override Call)
  • 35.
  • 36. 예 : 몬스터가 공격 당할 때 void CMonster ::Attack(CActor* pTarger) { double angerBonus = 1.0; if (m_VeryAngry) { CAngryData* pAngry = new CAngryData(this); angerBonus = pAngry->GetBonus(pTarget); } void CMonster ::Attack(CActor* pTarger) { CAngryData* pAngryData = NULL; if (m_VeryAngry) { pAngryData = new CAngryData(); } Attack(pTarget, pAngryData); void CMonster ::Attack(CActor* pTarger, CAngryData* pAngryData) { double angerBonus = 1.0; if (pAngryData) { angerBonus = pAngry->GetBonus(pTarget);
  • 37.
  • 38.
  • 39.
  • 40. 함수 추출 후 오버라이딩 - 예 void CPlayer::Attack(CActor* pTarger) { ... WSASend(m_Handle...); // 공격과 함께 데미지 표시 // 변경 후 void CPlayer::Attack(CActor* pTarger) { ... m_Socket.Send(...); // 공격과 함께 데미지 표시 class CSocket { void Send(...) { WSASend(m_Handle, ...); class CMockSocket : public CSocket { void Send(...) { // do nothing
  • 41. 더 할 수 있다 class CMockSocket : public CSocket { void Send(int packetType) { m_PacketRecorder.Push(packetType); TEST_FIXTURE(FixtureBattle, PlayerSendBeAttackedPacket) { pMonster->Attack(pPlayer); CHECK(pPlayer->IsSentPacket(PacketType::BeAttacked)); 이런 걸 감지 변수 (sensing) 이라고 한다 .
  • 42.
  • 43.
  • 44. Seam 예제 void CPlayer::Logout() { g_Database.SavePlayerStatus(this); ... } CDatabase::SavePlayerStatus() 를 하기 위해서는 꼭 DB 에 접근해야 하고 , 시간이 5 초 이상 걸린다고 하면 ?
  • 45. 가상함수 이용 - 예 CPlayer::CPlayer(CDatabase* pDatabase) : m_pDatabase(pDatabase) {} void CPlayer::Logout() { m_pDatabase->SavePlayerStatus(this); // CDatabase* CPlayer::m_pDatabase; } // 아까의 CMockSocket 과 비슷한 맥락임 . class CMockDatabase : public CDatabase { bool SavePlayerStatus(CPlayer* pPlayer) { return true; } class CMockPlayer : public CPlayer... CMockPlayer* pPlayer1 = new CMockPlayer(new CMockDatabase());
  • 46.
  • 47. define 을 이용한 코드 변경 - 예 void CPlayer::Logout() { CDatabase::Inst().SavePlayerStatus(this); // singleton 사용 ... } class CDatabase { static CDatabase& Inst() { #ifdef __UnitTest__ if (m_bTesting) { static CMockDatabase s; return s; } #endif static CDatabase s; return s; }
  • 48.
  • 49. 링크 - 예 class CDatabase { void SavePlayerStatus(CActor* pActor) { sql_query(“update ...”); #ifndef __UnitTest__ #pragma comment( lib, &quot;some_sql_library&quot;) #else #pragma comment( lib, &quot;fake_sql_library&quot;) #endif
  • 50.
  • 51. 의존 제거하기 3 단계 정적 함수 노출하기 (Expose Static Method)
  • 52. 예 : CPlayer 의 공격 코드 class CPlayer : public CActor { bool CanHit(CActor*); void Attack(CActor* pTarget); ... void CPlayer::Attack(CActor* pTarget) { if (CanHit(pTarget)) { pTarget->BeAttacked(this); } }
  • 53.
  • 54. CPlayer 의 공격 코드 - 수정판 class CPlayer : public CActor { static bool CanHit (CActor* pAttacker, CActor* pTarget); void Attack(CActor* pTarget); ... void CPlayer::Attack(CActor* pTarget) { if (CanHit(this, pTarget)) { pTarget->BeAttacked(this); } TEST_FIXTURE(FixtureBattle, PlayerCanHitMonster) { CHECK(CPlayer::CanHit(pPlayer, pMonster)); pPlayer->m_Level = 40; pMonster->m_Level = 80; CHECK(!CPlayer::CanHit(pPlayer, pMonster)); class CPlayer : public CActor { bool CanHit(CActor*); void Attack(CActor* pTarget); ... void CPlayer::Attack(CActor* pTarget) { if (CanHit(pTarget)) { pTarget->BeAttacked(this); } }
  • 55.
  • 56. 의존 제거하기 4 단계 템플릿 재정의 (Template Redefinition)
  • 57. 예 : test 코드 실행 중 dead lock 이 걸려요 . class CPlayer : public CActor { CMutexLock m_Lock; // recursive lock 아님 void BeAttacked(CActor* pAttacker) { m_Lock.Lock(); pAttacker.Lock(); pAttacker->BeAttacked();
  • 58. 해결 방법 class CMutexLockImpl : public ILock { void Lock() { WaitForSingleObject(...); class CDummyLockImpl : public ILock { void Lock() { // do nothing class CLockImp<typename T> { T m_Lock; void Lock() { m_Lock.Enter(); } }; typedef CLockImp<CMutexLockImpl> CMutexLock; typedef CLockImp<CDummyLockImpl> CDummyLock;
  • 59. 더 할 수 있다 ! class CDummyLockImpl : public ILock { void Lock() { if (CDummyLockImpl::Inst().IsDeadLock()) { throw CException(); 테스트를 하면서 , deadlock 를 감지할 수 있다
  • 60. 그 외 임의성 테스트
  • 61.
  • 62.
  • 64. 테스트의 종류 스토리 테스트 비즈니스 의도 ( 제품 설계 ) 사용성 테스팅 탐색적 테스팅 단위 테스트 개발자 의도 ( 코드 설계 ) 특성 테스팅 보안 테스팅 부하 테스팅 조합 테스팅 … 자동 자동 수동 도구
  • 65.
  • 66.
  • 67. 예 : 공격 코드에 특성 테스트를 붙인다면 ? void CPlayer::BeAttacked(CActor* pAttacker) { int damage = GetDamageFromAttacker(pAttacker); TEST_FIXTURE(FixtureAttack, GetDamageFromAttacker) { pPlayer->m_Level = 40; CHECK_EQUAL(760, pPlayer->GetDamageFromAttacker(pMonster); pPlayer->m_Level = 50; CHECK_EQUAL(400, pPlayer->GetDamageFromAttacker(pMonster); pPlayer->m_Level = 60; CHECK_EQUAL(223, pPlayer->GetDamageFromAttacker(pMonster); pPlayer->m_Level = 70; CHECK_EQUAL(0, pPlayer->GetDamageFromAttacker(pMonster); }
  • 68. 더 할 수 있다 . TEST_FIXTURE(FixtureAttack, GetDamage) { struct TestData { int m_Level; int m_Expect; }; TestData data[] = { {40, 760}, {50, 400}, {60, 223}, {70, 0}, {80, 0} }; for (int i = 0; i < sizeof(TestData[]) / sizeof(TestData); ++i) { TestData& d = data[i]; pPlayer->m_Level = d.m_Level; CHECK_EQUAL(d.m_Expect, pPlayer->GetDamager(pMonster));
  • 69.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75. class CTest{ protected: int m_Test; void Test() {} }; class CMockTest : public CTest { public: using CTest::m_Test; // 부모 클래스의 멤버를 public 으로 쓰겠다 . using CTest::Test; }; TEST(AccessTest) { CTest a; //a.m_Test = 1; // protected 멤버 변수 접근할 수 없음 . //a.Test(); // protected 멤버 함수 접근할 수 없음 . CMockTest* pMockTest = (CMockTest*)(&a); pMockTest->m_Test = 1; // CMockTest 로 강제 캐스팅 -> 접근 가능 pMockTest->Test(); // a 가 CMockTest 객체가 아니어도 이렇게 쓸 수 있다는 점에 주의 return 0; }
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88. Books

Editor's Notes

  1. 폭탄 돌리기처럼 , 어느 순간 너무 복잡해져서 리팩토링 하지 않고서는 코드를 추가할 수 없는 그 상황이 되기 전까지는 내 일이 아닌 것이다 .