변화에 대처하기 (Responding to change) 남기룡 마이에트 엔터테인먼트
변하지 않는 것은 없다 <ul><li>변하지 않는 유일한 진리  =  변하지 않는 것은 없다 </li></ul><ul><ul><li>요구사항은 끊임없이 변한다 . </li></ul></ul><ul><ul><li>만들어봐...
변화에 대한 대처법 <ul><li>많은 의사소통 </li></ul><ul><li>유연한 설계 </li></ul><ul><li>테스트 </li></ul><ul><li>지속적인 통합 </li></ul><ul><li>피드백 ...
설계
설계의 악취 <ul><li>경직성 (Rigidity) -  설계를 변경하기 어려움 </li></ul><ul><li>취약성 (Fragility) -  설계가 망가지기 쉬움 </li></ul><ul><li>부동성 (Immo...
설계 원칙 <ul><li>SRP  –  단일 책임 원칙 (Single Responsibility Principle) </li></ul><ul><li>OCP  -  개방 - 폐쇄 원칙 (Open-Closed Princip...
SRP(Single Responsibility Principle) <ul><li>단일 책임 원칙 </li></ul><ul><li>객체는 하나의 책임만을 맡아야 한다 . </li></ul><ul><li>책임  =  변화의...
SRP 예시 <ul><li>국제적 은행의 계좌 관리 케이스 </li></ul>
SRP 예시
OCP(Open Closed Principle) <ul><li>개방-폐쇄 원칙 </li></ul><ul><li>소프트웨어 개체 ( 클래스 ,  모듈 ,  함수 등등 ) 는 확장에는 열려 있어야 하고 ,  변경에는 닫혀 ...
OCP
OCP
OCP <ul><li>상속을 통한 다형성을 이용한 호출 </li></ul>
Command Pattern
LSP(Liskov Substitution Principle) <ul><li>리스코프 치환 원칙 </li></ul><ul><li>기반 클래스는 서브 클래스로 대체 가능해야 한다 . </li></ul><ul><li>Is-...
잘못된 상속 관계
DIP(Dependency Inversion Principle) <ul><li>의존 관계 역전의 법칙 </li></ul><ul><li>클라이언트는 구체 클래스가 아닌 인터페이스나 추상 클래스에 의존해야 한다 . </li...
Template Method Pattern
ISP(Interface Segregation Principle) <ul><li>인터페이스 분리의 원칙 </li></ul><ul><li>클라이언트에게 특화된 여러 개의 인터페이스가 하나의 범용 인터페이스보다 낫다. </...
ISP 적용 전
ISP 적용 후
테스트
테스트 유형 스토리 테스트 비즈니스 의도 (제품 설계) 사용성 테스팅 탐색적 테스팅 단위 테스트 개발자 의도 (코드 설계) 특성 테스팅 보안 테스팅 부하 테스팅 조합 테스팅 … 자동 자동 수동 도구
Test Example (단위 테스트) TEST(TestCapsuleIntersectRay) { // test1 vec3 t = vec3(0.0f, 2000.0f, 100.0f); vec3 b = vec3(0.0f, 2...
Test Example(스토리 테스트) TEST(PlayerJumpTest) {  const vec3 player_pos = vec3(1000,1000,0); World world; world.Create(); Play...
TDD(Test Driven Development) <ul><li>TDD != Test </li></ul><ul><li>장점 </li></ul><ul><ul><li>단순함과 모듈화 </li></ul></ul><ul><u...
불과 몇 분밖에 걸리지 않는다 . 체크 인 체크 인 TDD 의 순환 과정 TEST (ShieldLevelStartsFull) { Shield shield; CHECK_EQUAL (Shield::kMaxLevel, shi...
TDD 시연
Tips <ul><li>Mock Object </li></ul><ul><ul><li>Device, Socket, DB </li></ul></ul><ul><li>김밥 썰기와 해체 하기 </li></ul><ul><li>처음...
Legacy Code <ul><li>세상에 존재하는 두 종류의 코드 </li></ul><ul><ul><li>변화 허용 코드 </li></ul></ul><ul><ul><li>레거시 코드 </li></ul></ul><ul>...
Legacy Code에 대한 접근 방법 <ul><li>다시 짜고 내다 버리기 (Rewrite and throw away) </li></ul><ul><li>리팩토링으로 굴복시키기 (Refactor into submissi...
리팩토링을 습관화하라 . CODE
정리 <ul><li>변화 에 기민하게 대응하자 . </li></ul><ul><li>알고 있는 것은 중요하지 않다 .  실천하는 것이 중요하다 ! </li></ul><ul><li>습관적으로  설계하고 테스트하고 리팩토링해...
Upcoming SlideShare
Loading in …5
×

Responding to change

2,033 views

Published on

변화에 대처하기

  • Be the first to comment

  • Be the first to like this

Responding to change

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

×