SlideShare a Scribd company logo
변화에 대처하기 (Responding to change) 남기룡 마이에트 엔터테인먼트
변하지 않는 것은 없다 변하지 않는 유일한 진리  =  변하지 않는 것은 없다 요구사항은 끊임없이 변한다 . 만들어봐야 재미있는지 안다 .
변화에 대한 대처법 많은 의사소통 유연한 설계 테스트 지속적인 통합 피드백
설계
설계의 악취 경직성 (Rigidity) -  설계를 변경하기 어려움 취약성 (Fragility) -  설계가 망가지기 쉬움 부동성 (Immobility) -  설계를 재사용하기 어려움 점착성 (Viscosity) -  제대로 동작하기 어려움 불필요한 복잡성 (Needless Complexity) -  과도한 설계 불필요한 반복 (Needless Repetition) -  마우스 남용 불투명성 (Opacity) -  혼란스러운 표현
설계 원칙 SRP  –  단일 책임 원칙 (Single Responsibility Principle) OCP  -  개방 - 폐쇄 원칙 (Open-Closed Principle) LSP  -  리스코프 교체 원칙 (Liskov Substitution Principle)  DIP  -  의존 관계 역전 원칙 (Dependency Inversion Principle)  ISP  -  인터페이스 격리 원칙 (Interface Segregation Principle)
SRP(Single Responsibility Principle) 단일 책임 원칙 객체는 하나의 책임만을 맡아야 한다 . 책임  =  변화의 축 ( 산탄총 수술 )
SRP 예시 국제적 은행의 계좌 관리 케이스
SRP 예시
OCP(Open Closed Principle) 개방-폐쇄 원칙 소프트웨어 개체 ( 클래스 ,  모듈 ,  함수 등등 ) 는 확장에는 열려 있어야 하고 ,  변경에는 닫혀 있어야 한다 .
OCP
OCP
OCP 상속을 통한 다형성을 이용한 호출
Command Pattern
LSP(Liskov Substitution Principle) 리스코프 치환 원칙 기반 클래스는 서브 클래스로 대체 가능해야 한다 . Is-A  관계
잘못된 상속 관계
DIP(Dependency Inversion Principle) 의존 관계 역전의 법칙 클라이언트는 구체 클래스가 아닌 인터페이스나 추상 클래스에 의존해야 한다 . Don’t call us, we’ll call you
Template Method Pattern
ISP(Interface Segregation Principle) 인터페이스 분리의 원칙 클라이언트에게 특화된 여러 개의 인터페이스가 하나의 범용 인터페이스보다 낫다.
ISP 적용 전
ISP 적용 후
테스트
테스트 유형 스토리 테스트 비즈니스 의도 (제품 설계) 사용성 테스팅 탐색적 테스팅 단위 테스트 개발자 의도 (코드 설계) 특성 테스팅 보안 테스팅 부하 테스팅 조합 테스팅 … 자동 자동 수동 도구
Test Example (단위 테스트) TEST(TestCapsuleIntersectRay) { // test1 vec3 t = vec3(0.0f, 2000.0f, 100.0f); vec3 b = vec3(0.0f, 2000.0f, 0.0f); float fDistance = 0.0f; MCapsule tCapsule(b, t, 50.0f); vec3 vRayOrigin = vec3(0.0f, 0.0f, 0.0f); vec3 vRayDir = vec3(0.0f, -1.0f, 0.0f); bool bPick = tCapsule.IntersectRay(vRayOrigin, vRayDir, fDistance); CHECK(bPick == false); CHECK(fDistance > 0.0f); // test2 t = vec3(0.0f, 2000.0f, 100.0f); b = vec3(0.0f, 2000.0f, 0.0f); MCapsule tCapsule2(b, t, 50.0f); vRayOrigin = vec3(0.0f, 0.0f, 0.0f); vRayDir = vec3(0.0f, 1.0f, 0.0f); bPick = tCapsule2.IntersectRay(vRayOrigin, vRayDir, fDistance); CHECK(bPick == true); CHECK_CLOSE(fDistance, 1950.0f, 0.01f); // test3 t = vec3(0.0f, 2000.0f, 100.0f); b = vec3(0.0f, 2000.0f, 0.0f); MCapsule tCapsule3(b, t, 100.0f); vRayOrigin = vec3(0.0f, 0.0f, 0.0f); vRayDir = vec3(101.0f, 2000.0f, 0.0f).Normalize(); bPick = tCapsule3.IntersectRay(vRayOrigin, vRayDir, fDistance); CHECK(bPick == false); CHECK(fDistance < 1.0f); }
Test Example(스토리 테스트) TEST(PlayerJumpTest) {  const vec3 player_pos = vec3(1000,1000,0); World world; world.Create(); Player player; player.Create(world, player_pos); player.Jump(); player.Update(0.1f); CHECK(player.GetPosition().z > 0); CHECK(player.GetAni() == ANI_JUMP); }  TEST(ShieldCanBeDamaged)  {  Player player; player.SetHealth(1000); Shield shield; shield.SetHealth(100); player.Equip(shield); player.Damage(200); CHECK(shield.GetHealth() == 0); CHECK(player.GetHealth() == 900); }
TDD(Test Driven Development) TDD != Test 장점 단순함과 모듈화 안전망 즉각적인 피드백 문서화 과정 재빨리 테스트를 하나 추가한다 . 테스트를 실행시켜 새로 추가한 녀석이 실패하는 걸 확인한다 . 코드를 약간 수정한다 . 테스트를 실행시켜 모두 성공하는지 확인한다 . 중복을 제거하기 위해 리팩터링한다 .
불과 몇 분밖에 걸리지 않는다 . 체크 인 체크 인 TDD 의 순환 과정 TEST (ShieldLevelStartsFull) { Shield shield; CHECK_EQUAL (Shield::kMaxLevel, shield.GetLevel()); } Shield::Shield() : m_level (Shield::kMaxLevel) { } 테스트 작성 코드 작성 리팩토링 테스트 실패 테스트 통과 테스트 통과
TDD 시연
Tips Mock Object Device, Socket, DB 김밥 썰기와 해체 하기 처음부터 많은 것을 테스트하려 하지말고 ,  현실적으로 가능한 것부터 하라 . 처음에는 과도할 정도로 클래스를 나눠라 . MVC(Model-view-controller)  패턴을 활용하라 . 초반에는 개발 속도가 떨어지지만 ,  익숙해지면 개발 속도가 빨라진다 .
Legacy Code 세상에 존재하는 두 종류의 코드 변화 허용 코드 레거시 코드 변화 허용 코드  :  쉽게 비즈니스나 기술의 변화에 적용하는 코드 Legacy Code :  의존성 (Dependency) 이 높고 ,  테스트로 보호되지 않은 코드
Legacy Code에 대한 접근 방법 다시 짜고 내다 버리기 (Rewrite and throw away) 리팩토링으로 굴복시키기 (Refactor into submission) 의존 관계 깨뜨리기 독립적인 코드 주변에 테스트를 추가 단위 테스트보다는 스토리 테스트 위주 작성 질식시키기 (Strangle) 포도 덩굴로 무화과 나무 질식시키기 레거시 코드 일부분이라도 건드릴 기회가 있을 때마다 질식시키는 코드를 추가
리팩토링을 습관화하라 . CODE
정리 변화 에 기민하게 대응하자 . 알고 있는 것은 중요하지 않다 .  실천하는 것이 중요하다 ! 습관적으로  설계하고 테스트하고 리팩토링해야 한다 .

More Related Content

PDF
광운대[바람] 3.vhdl test bench
PDF
읽기 좋은 코드가 좋은코드다
PDF
자바 서버 애플리케이션 아키텍처 안티 패턴
PPTX
JUnit 지원 라이브러리 소개
PPTX
TDD - Test Driven Development
PPTX
TDD or TFD
PPTX
오버라이딩을 사용한 테스트 시의 설정 처리
PDF
스프링보다 중요한 스프링 이야기
광운대[바람] 3.vhdl test bench
읽기 좋은 코드가 좋은코드다
자바 서버 애플리케이션 아키텍처 안티 패턴
JUnit 지원 라이브러리 소개
TDD - Test Driven Development
TDD or TFD
오버라이딩을 사용한 테스트 시의 설정 처리
스프링보다 중요한 스프링 이야기

What's hot (19)

PDF
Spring3 발표자료 - 김연수
PDF
Tdd live spring camp 2013
PPTX
예외처리가이드
ODP
팀장 잔소리
PDF
Effective unit testing ch3. 테스트더블
PPTX
Backend Master | 3.2.1 Test - JUnit
PDF
Effective unit testing - 좋은테스트 요약
PDF
TDD.JUnit.조금더.알기
PPT
테스트 자동화의 원칙
PPT
Unit Test With J Unit
PPTX
PPTX
X unittestpattern 1장_아꿈사
PPTX
C++ 프로젝트에 단위 테스트 도입하기
PDF
보다 나은 웹 어플리케이션 설계
PDF
TDD&Refactoring Day 03: TDD
PPT
간단하게 알아보는 좋은 코드 서영훈
PDF
Java the good parts
PDF
시작하자 단위테스트
PDF
TDD with JUnit 2
Spring3 발표자료 - 김연수
Tdd live spring camp 2013
예외처리가이드
팀장 잔소리
Effective unit testing ch3. 테스트더블
Backend Master | 3.2.1 Test - JUnit
Effective unit testing - 좋은테스트 요약
TDD.JUnit.조금더.알기
테스트 자동화의 원칙
Unit Test With J Unit
X unittestpattern 1장_아꿈사
C++ 프로젝트에 단위 테스트 도입하기
보다 나은 웹 어플리케이션 설계
TDD&Refactoring Day 03: TDD
간단하게 알아보는 좋은 코드 서영훈
Java the good parts
시작하자 단위테스트
TDD with JUnit 2
Ad

Similar to Responding to change (20)

PDF
Java 유지보수 가능한 개발 원칙
PDF
유지보수 가능한 개발 원칙
PDF
소프트웨어 개선 그룹(Sig) 개발 원칙
PDF
回国去哪买毕业证办迪肯大学毕业证Deakin毕业证书【Q微202-661-4433】 Deakin售澳洲毕业证原版新毕业证书出售各国毕业证买澳洲毕业证的价...
PDF
Oop design principle SOLID
PDF
[기본과정] 코드 테스트와 커버리지 기본 교육(개념)
PPT
Cygnus unit test
PPTX
The Cucumber for Java
PPTX
20250620_Kit-Works Team Study_jspecify.pptx
PPTX
[Dev rookie]designpattern
PDF
애자일과 애자일 테스트 소개 (테스트기본교육 3장 2절)
PDF
Devon 2011-b-5 효과적인 레거시 코드 다루기
PDF
테스터가 말하는 테스트코드 작성 팁과 사례
PDF
Legacy code refactoring video rental system
PDF
소프트웨어 설계 악취: 기술 부채 관리 방법
PDF
The Introduction to Refactoring
PDF
TDD&Refactoring Day 01: Refactoring
PDF
Effective Unit Testing
PPTX
Clean code chapter9
PPTX
The roadtocodecraft
Java 유지보수 가능한 개발 원칙
유지보수 가능한 개발 원칙
소프트웨어 개선 그룹(Sig) 개발 원칙
回国去哪买毕业证办迪肯大学毕业证Deakin毕业证书【Q微202-661-4433】 Deakin售澳洲毕业证原版新毕业证书出售各国毕业证买澳洲毕业证的价...
Oop design principle SOLID
[기본과정] 코드 테스트와 커버리지 기본 교육(개념)
Cygnus unit test
The Cucumber for Java
20250620_Kit-Works Team Study_jspecify.pptx
[Dev rookie]designpattern
애자일과 애자일 테스트 소개 (테스트기본교육 3장 2절)
Devon 2011-b-5 효과적인 레거시 코드 다루기
테스터가 말하는 테스트코드 작성 팁과 사례
Legacy code refactoring video rental system
소프트웨어 설계 악취: 기술 부채 관리 방법
The Introduction to Refactoring
TDD&Refactoring Day 01: Refactoring
Effective Unit Testing
Clean code chapter9
The roadtocodecraft
Ad

More from 기룡 남 (19)

PPTX
GAN을 이용한 캐릭터 리소스 제작 맛보기
PDF
NDC 2015 게임 스타트업 시작하기
PDF
게임 스타트업 시작하기 두달 후
PDF
게임 스타트업 시작하기
PPTX
마쉬멜로우 첼린지
PDF
레이더즈 기술 사례
PDF
PDF
Ignite Maiet 14 마이에트야구단
PDF
Ignite Maiet 12 누구나 쉽게 만드는 음악
PDF
Ignite Maiet 10 두근두근사파리 제작후기2
PDF
Ignite Maiet 07 칵테일과 함께 훈남훈녀 되기
PDF
Ignite Maiet 03 순정만화를 게임으로 재현하기
PDF
생산적인 개발을 위한 지속적인 테스트
PPTX
Rapid Development
PPT
refactoring database
PDF
Continuous Test
PDF
KGC2007 Scrum And Xp
PDF
Game AI Overview
PDF
Gunz Postmortem
GAN을 이용한 캐릭터 리소스 제작 맛보기
NDC 2015 게임 스타트업 시작하기
게임 스타트업 시작하기 두달 후
게임 스타트업 시작하기
마쉬멜로우 첼린지
레이더즈 기술 사례
Ignite Maiet 14 마이에트야구단
Ignite Maiet 12 누구나 쉽게 만드는 음악
Ignite Maiet 10 두근두근사파리 제작후기2
Ignite Maiet 07 칵테일과 함께 훈남훈녀 되기
Ignite Maiet 03 순정만화를 게임으로 재현하기
생산적인 개발을 위한 지속적인 테스트
Rapid Development
refactoring database
Continuous Test
KGC2007 Scrum And Xp
Game AI Overview
Gunz Postmortem

Responding to change

  • 1. 변화에 대처하기 (Responding to change) 남기룡 마이에트 엔터테인먼트
  • 2. 변하지 않는 것은 없다 변하지 않는 유일한 진리 = 변하지 않는 것은 없다 요구사항은 끊임없이 변한다 . 만들어봐야 재미있는지 안다 .
  • 3. 변화에 대한 대처법 많은 의사소통 유연한 설계 테스트 지속적인 통합 피드백
  • 5. 설계의 악취 경직성 (Rigidity) - 설계를 변경하기 어려움 취약성 (Fragility) - 설계가 망가지기 쉬움 부동성 (Immobility) - 설계를 재사용하기 어려움 점착성 (Viscosity) - 제대로 동작하기 어려움 불필요한 복잡성 (Needless Complexity) - 과도한 설계 불필요한 반복 (Needless Repetition) - 마우스 남용 불투명성 (Opacity) - 혼란스러운 표현
  • 6. 설계 원칙 SRP – 단일 책임 원칙 (Single Responsibility Principle) OCP - 개방 - 폐쇄 원칙 (Open-Closed Principle) LSP - 리스코프 교체 원칙 (Liskov Substitution Principle) DIP - 의존 관계 역전 원칙 (Dependency Inversion Principle) ISP - 인터페이스 격리 원칙 (Interface Segregation Principle)
  • 7. SRP(Single Responsibility Principle) 단일 책임 원칙 객체는 하나의 책임만을 맡아야 한다 . 책임 = 변화의 축 ( 산탄총 수술 )
  • 8. SRP 예시 국제적 은행의 계좌 관리 케이스
  • 10. OCP(Open Closed Principle) 개방-폐쇄 원칙 소프트웨어 개체 ( 클래스 , 모듈 , 함수 등등 ) 는 확장에는 열려 있어야 하고 , 변경에는 닫혀 있어야 한다 .
  • 11. OCP
  • 12. OCP
  • 13. OCP 상속을 통한 다형성을 이용한 호출
  • 15. LSP(Liskov Substitution Principle) 리스코프 치환 원칙 기반 클래스는 서브 클래스로 대체 가능해야 한다 . Is-A 관계
  • 17. DIP(Dependency Inversion Principle) 의존 관계 역전의 법칙 클라이언트는 구체 클래스가 아닌 인터페이스나 추상 클래스에 의존해야 한다 . Don’t call us, we’ll call you
  • 19. ISP(Interface Segregation Principle) 인터페이스 분리의 원칙 클라이언트에게 특화된 여러 개의 인터페이스가 하나의 범용 인터페이스보다 낫다.
  • 23. 테스트 유형 스토리 테스트 비즈니스 의도 (제품 설계) 사용성 테스팅 탐색적 테스팅 단위 테스트 개발자 의도 (코드 설계) 특성 테스팅 보안 테스팅 부하 테스팅 조합 테스팅 … 자동 자동 수동 도구
  • 24. Test Example (단위 테스트) TEST(TestCapsuleIntersectRay) { // test1 vec3 t = vec3(0.0f, 2000.0f, 100.0f); vec3 b = vec3(0.0f, 2000.0f, 0.0f); float fDistance = 0.0f; MCapsule tCapsule(b, t, 50.0f); vec3 vRayOrigin = vec3(0.0f, 0.0f, 0.0f); vec3 vRayDir = vec3(0.0f, -1.0f, 0.0f); bool bPick = tCapsule.IntersectRay(vRayOrigin, vRayDir, fDistance); CHECK(bPick == false); CHECK(fDistance > 0.0f); // test2 t = vec3(0.0f, 2000.0f, 100.0f); b = vec3(0.0f, 2000.0f, 0.0f); MCapsule tCapsule2(b, t, 50.0f); vRayOrigin = vec3(0.0f, 0.0f, 0.0f); vRayDir = vec3(0.0f, 1.0f, 0.0f); bPick = tCapsule2.IntersectRay(vRayOrigin, vRayDir, fDistance); CHECK(bPick == true); CHECK_CLOSE(fDistance, 1950.0f, 0.01f); // test3 t = vec3(0.0f, 2000.0f, 100.0f); b = vec3(0.0f, 2000.0f, 0.0f); MCapsule tCapsule3(b, t, 100.0f); vRayOrigin = vec3(0.0f, 0.0f, 0.0f); vRayDir = vec3(101.0f, 2000.0f, 0.0f).Normalize(); bPick = tCapsule3.IntersectRay(vRayOrigin, vRayDir, fDistance); CHECK(bPick == false); CHECK(fDistance < 1.0f); }
  • 25. Test Example(스토리 테스트) TEST(PlayerJumpTest) { const vec3 player_pos = vec3(1000,1000,0); World world; world.Create(); Player player; player.Create(world, player_pos); player.Jump(); player.Update(0.1f); CHECK(player.GetPosition().z > 0); CHECK(player.GetAni() == ANI_JUMP); } TEST(ShieldCanBeDamaged) { Player player; player.SetHealth(1000); Shield shield; shield.SetHealth(100); player.Equip(shield); player.Damage(200); CHECK(shield.GetHealth() == 0); CHECK(player.GetHealth() == 900); }
  • 26. TDD(Test Driven Development) TDD != Test 장점 단순함과 모듈화 안전망 즉각적인 피드백 문서화 과정 재빨리 테스트를 하나 추가한다 . 테스트를 실행시켜 새로 추가한 녀석이 실패하는 걸 확인한다 . 코드를 약간 수정한다 . 테스트를 실행시켜 모두 성공하는지 확인한다 . 중복을 제거하기 위해 리팩터링한다 .
  • 27. 불과 몇 분밖에 걸리지 않는다 . 체크 인 체크 인 TDD 의 순환 과정 TEST (ShieldLevelStartsFull) { Shield shield; CHECK_EQUAL (Shield::kMaxLevel, shield.GetLevel()); } Shield::Shield() : m_level (Shield::kMaxLevel) { } 테스트 작성 코드 작성 리팩토링 테스트 실패 테스트 통과 테스트 통과
  • 29. Tips Mock Object Device, Socket, DB 김밥 썰기와 해체 하기 처음부터 많은 것을 테스트하려 하지말고 , 현실적으로 가능한 것부터 하라 . 처음에는 과도할 정도로 클래스를 나눠라 . MVC(Model-view-controller) 패턴을 활용하라 . 초반에는 개발 속도가 떨어지지만 , 익숙해지면 개발 속도가 빨라진다 .
  • 30. Legacy Code 세상에 존재하는 두 종류의 코드 변화 허용 코드 레거시 코드 변화 허용 코드 : 쉽게 비즈니스나 기술의 변화에 적용하는 코드 Legacy Code : 의존성 (Dependency) 이 높고 , 테스트로 보호되지 않은 코드
  • 31. Legacy Code에 대한 접근 방법 다시 짜고 내다 버리기 (Rewrite and throw away) 리팩토링으로 굴복시키기 (Refactor into submission) 의존 관계 깨뜨리기 독립적인 코드 주변에 테스트를 추가 단위 테스트보다는 스토리 테스트 위주 작성 질식시키기 (Strangle) 포도 덩굴로 무화과 나무 질식시키기 레거시 코드 일부분이라도 건드릴 기회가 있을 때마다 질식시키는 코드를 추가
  • 33. 정리 변화 에 기민하게 대응하자 . 알고 있는 것은 중요하지 않다 . 실천하는 것이 중요하다 ! 습관적으로 설계하고 테스트하고 리팩토링해야 한다 .