40
레레레 레레 레레 레레 4 레 레레 레레 5 레 레레레 레레레 레레 레레 아아아 http://cafe.naver.com/architect1 아아아 http://blog.naver.com/sikyungelove

120908 레거시코드활용전략 4장5장

Embed Size (px)

Citation preview

Page 1: 120908 레거시코드활용전략 4장5장

레거시 코드 활용 전략

4 장 봉합 모델5 장 레거시 코드를 위한 도구

아꿈사 http://cafe.naver.com/architect1

최유림http://blog.naver.com/sikyungelove

Page 2: 120908 레거시코드활용전략 4장5장

천공 카드 프로그래밍

• 데이터를 표현하기 위해 규칙에 따라 구멍을 뚫어 사용하는 종이 카드로서 초기의 저장매체

• 천공 위치에 구멍을 뚫거나 뚫지 않음으로서 하나의 비트를 나타날 수 있음

http://ko.wikipedia.org/wiki/%EC%B2%9C%EA%B3%B5_%EC%B9%B4%EB%93%9C

Page 3: 120908 레거시코드활용전략 4장5장

봉합모델레거시 코드를 위한 도구정리가 안되지만 맞는 얘기들

Page 4: 120908 레거시코드활용전략 4장5장

봉합모델레거시 코드를 위한 도구정리가 안되지만 맞는 얘기들

Page 5: 120908 레거시코드활용전략 4장5장

봉합 (Seams)

• 프로그램 안에서 동작을 변화시킬 수 있는 위치

• 동작을 변화시키기 위해 코드를 편집할 필요는 없음

Page 6: 120908 레거시코드활용전략 4장5장

bool CAsyncSslRec::Init(){

if(m_bSslInitialized){return true;

}m_smutex.Unlock();m_nSslRefCount++;

m_bSslInitialized = true;

FreeLibrary(m_hSslDll1);m_hSslDll1 = 0;FreeLibrary(m_hSslDll2);m_hSslDll2 = 0;

if(!m_bFailureSent){m_bFailureSent = true;PostReceiveError(SOCKETCALLBACK, SSL_FAILURE);

}

CreateLibrary(m_hSslDll1, "syncesel1.dll");CreateLibrary(m_hSslDll2, "syncesel2.dll");

m_hSslDll2->Init();m_hSslDll2->Init();

return true;}

•프로그램 안에서 동작을 변화시킬 수 있는 위치•동작을 변화시키기 위해 코드를 편집할 필요는 없음

Page 7: 120908 레거시코드활용전략 4장5장

bool CAsyncSslRec::Init(){

if(m_bSslInitialized){return true;

}m_smutex.Unlock();m_nSslRefCount++;

m_bSslInitialized = true;

FreeLibrary(m_hSslDll1);m_hSslDll1 = 0;FreeLibrary(m_hSslDll2);m_hSslDll2 = 0;

if(!m_bFailureSent){m_bFailureSent = true;PostReceiveError(SOCKETCALLBACK, SSL_FAILURE);

}

CreateLibrary(m_hSslDll1, "syncesel1.dll");CreateLibrary(m_hSslDll2, "syncesel2.dll");

m_hSslDll2->Init();m_hSslDll2->Init();

return true;}

동작을 변화시키지만코드는 편집하지 않도록 함-> 코드와 테스트 분리 가능

Page 8: 120908 레거시코드활용전략 4장5장

어떻게 하면동작을 변화시키지만코드는 편집하지 않도록 할까 ?

Page 9: 120908 레거시코드활용전략 4장5장

봉합 (Seams) 의 종류

• 프로그래밍 언어에 따라 서로 다름

• 프로그램 텍스트가 시스템 코드로 변형되는 시점에 따라 다름

• 컴파일 단계 : 전처리 봉합

• 링크 단계 : 연결 봉합

• 실행 단계 : 객체 봉합

Page 10: 120908 레거시코드활용전략 4장5장

전처리 봉합

• C, C++ 은 컴파일 하기 전에 매크로 전처리가 실행됨

Page 11: 120908 레거시코드활용전략 4장5장

• 전처리란 컴파일 전에 처리하는 매크로

• # 로 시작 ex. #include <stdio.h>

• 전처리기를 통하여 동작을 변화시키지만 코드는 편집하지 않도록 정의

• 많은 봉합의 기회 제공

• 전처리기 사용시 코드의 명료성이 떨어짐

• #define 으로 정의되는 매크로는 단순히 텍스트 치환만 수행

• 불명확한 버그를 숨기기 위한 매크로를 만들기 쉬움

Page 12: 120908 레거시코드활용전략 4장5장

bool CAsyncSslRec::Init(){

if(m_bSslInitialized){return true;

}m_smutex.Unlock();m_nSslRefCount++;

m_bSslInitialized = true;

FreeLibrary(m_hSslDll1);m_hSslDll1 = 0;FreeLibrary(m_hSslDll2);m_hSslDll2 = 0;

if(!m_bFailureSent){m_bFailureSent = true;PostReceiveError(SOCKETCALLBACK, SSL_FAILURE);

}

CreateLibrary(m_hSslDll1, "syncesel1.dll");CreateLibrary(m_hSslDll2, "syncesel2.dll");

m_hSslDll2->Init();m_hSslDll2->Init();

return true;}

#include 문을 코드에 추가-> PostReceiveError 매크로 정의-> 테스트용 전처리기 사용-> 전처리 봉합

Page 13: 120908 레거시코드활용전략 4장5장

연결 봉합

• 링커는 컴파일러를 통해 만들어진 여러 Object File

들을 하나의 실행파일로 만듦

• C, C++ 은 독립된 링커 존재

• 자바는 링크 작업이 보이지 않음

Page 14: 120908 레거시코드활용전략 4장5장

• 연결 봉합을 이용하는 가장 쉬운 방법은 바꾸고자하는 클래스나 함수를 위해서 별도의 라이브러리를 만드는 것

• 테스트 해야 할 때 클래스나 함수 제작에 연결하지 않고 , 새로 생성된 클래스나 함수에 연결되도록 빌드 스크립트를 변경하면 동작을 변화시키지만 코드는 편집하지 않음

• 제 3 의 라이브러리를 호출하는 코드 베이스를 가진 경우 유용함

Page 15: 120908 레거시코드활용전략 4장5장

bool CAsyncSslRec::Init(){

if(m_bSslInitialized){return true;

}m_smutex.Unlock();m_nSslRefCount++;

m_bSslInitialized = true;

FreeLibrary(m_hSslDll1);m_hSslDll1 = 0;FreeLibrary(m_hSslDll2);m_hSslDll2 = 0;

if(!m_bFailureSent){m_bFailureSent = true;PostReceiveError(SOCKETCALLBACK, SSL_FAILURE);

}

CreateLibrary(m_hSslDll1, "syncesel1.dll");CreateLibrary(m_hSslDll2, "syncesel2.dll");

m_hSslDll2->Init();m_hSslDll2->Init();

return true;}

PostReveiveError 가 전역함수-> 라이브러리 생성-> 동작 제거를 위해 라이브러리 연결-> 테스트 할때는 테스트 라이브러리와 연결-> 실제 시스템 빌드시 , 제작 라이브러리와 연결

Page 16: 120908 레거시코드활용전략 4장5장

객체 봉합

• 객체지향 프로그램은 어떤 메소드가 실행될지 정의하지 않음

• 같은 이름을 가지는 메소드가 하나 이상 있을 수 있음

• 주변 코드 변화 없이 어떤 메소드가 호출될지 변경할 수 있는 경우가 객체 봉합

Page 17: 120908 레거시코드활용전략 4장5장

bool CAsyncSslRec::Init(){

if(m_bSslInitialized){return true;

}m_smutex.Unlock();m_nSslRefCount++;

m_bSslInitialized = true;

FreeLibrary(m_hSslDll1);m_hSslDll1 = 0;FreeLibrary(m_hSslDll2);m_hSslDll2 = 0;

if(!m_bFailureSent){m_bFailureSent = true;PostReceiveError(SOCKETCALLBACK, SSL_FAILURE);

}

CreateLibrary(m_hSslDll1, "syncesel1.dll");CreateLibrary(m_hSslDll2, "syncesel2.dll");

m_hSslDll2->Init();m_hSslDll2->Init();

return true;}

PostReveiveError 를 오버라이드 하는테스트용 하위 클래스 객체 생성-> 동작을 변화시키지만 코드는 편집하지 않도록 함

Page 18: 120908 레거시코드활용전략 4장5장

봉합모델레거시 코드를 위한 도구정리가 안되지만 맞는 얘기들

Page 19: 120908 레거시코드활용전략 4장5장

리팩토링

• 소프트웨어의 내부 구조에 가해지는 변화

• 소프트웨어에 존재하는 동작을 변경하지 않음

• 이해하기 쉽게 변경

• 직접 할 수도 있고 , 도구를 이용 할 수도 있음

Page 20: 120908 레거시코드활용전략 4장5장

자동화된 리팩토링 도구

• 언어마다 리팩토링 도구들이 존재

• 통합개발 환경으로 구성되거나 분리됨

Page 21: 120908 레거시코드활용전략 4장5장

리팩토링 검증

• 리팩토링 과정에서 버그가 생길 수 있음

• 자동화된 리팩토링 도구에 버그가 있을 수 있음

• 리팩토링 후 동작을 변경시키지 않는지 검증해야 함

Page 22: 120908 레거시코드활용전략 4장5장

리팩토링 예제public class A{ private int alpha = 0; private int getValue(){ alpha++; return 12; } public void doSome-thing(){ int v = getValue(); int total = 0; for(int n=0; n<10; n++){ total += v; } }}

v 를 제거하라 !!

public class A{ private int alpha = 0; private int getValue(){ alpha++; return 12; } public void doSomething(){ int total = 0; for(int n=0; n<10; n++){ total += getValue(); } }}

Page 23: 120908 레거시코드활용전략 4장5장

리팩토링 예제public class A{ private int alpha = 0; private int getValue(){ alpha++; // alpha 1 증가 return 12; } public void doSomething(){ int v = getValue(); int total = 0; for(int n=0; n<10; n++){ total += v; } }}

리팩토링 후동작이 변경됨

public class A{ private int alpha = 0; private int getValue(){ alpha++; // alpha 10 증가 return 12; } public void doSomething(){ int total = 0; for(int n=0; n<10; n++){ total += getValue(); } }}

테스트 루틴을 두어 리팩토링 후 수행 !!

ex) alpha 값 검증

Page 24: 120908 레거시코드활용전략 4장5장

어떻게 검증할까 ?

Page 25: 120908 레거시코드활용전략 4장5장

xUnit 단위 테스트 프레임워크

• 소프트웨어의 함수나 클래스 같은 서로 다른 구성

원소 ( 단위 ) 를 테스트 하는 프레임워크

• 같은 테스트 코드를 여러번 작성하지 않음

• Java 단위 테스트는 jUnit

C++ 단위 테스트는 CppUnit

.NET 단위 테스트는 Nunit

• 오픈소스로 사용 가능

Page 26: 120908 레거시코드활용전략 4장5장

Junit

• xUnit 의 자바버전

• TestCase 라는 클래스로 하위 클래스화함으로써 테스트 루틴을 작성

Page 27: 120908 레거시코드활용전략 4장5장

import junit.framework.*;

public class FormulaTest extends TestCase{ // testXXX() 형식의 메소드

public void testEmpty(){ // 테스트 하려는 내용 ( 빈 경우 테스트 ) // 확인코드 // 코드포함가능 ( 새로운 객체 생성 , value 메소드 이용 )assertEquals(0, new Formula("").value());

}public void testDigit(){

// 값이 일치하면 테스트 통과 , 아니면 테스트 실패assertEquals(1, new Formula("1").value());

}}

메소드 별로 서로 영향을 주지 않기 위해

각 테스트 메소드 용으로 완전히 분리된 객체 생성

Page 28: 120908 레거시코드활용전략 4장5장

public class EmployeeTest extends TestCase{private Employee employee;

// 테스트 메소드가 실행되기 전에 각 테스트 객체에서 실행됨protected void setUp(){

// 각 테스트에서 사용할 객체 생성employee = new Employee("Fred", 0, 10); TDate cardDate = new TDate(10, 10, 2000);employee.addTimeCard(new TimeCard(cardDate, 40));

}

public void testNormalPay(){ //setUp 에서 생성된 하나의 employee 가 한번만 시간카드의 봉급 계산하는지 검사assertEquals(400, employee.getPay());

}

public void testOvertime(){TDate newCardDate = new TDate(11, 10, 2000);employee.addTimeCard(new TimeCard(newCardDate,

50));//setUp 에서 생성된 하나의 employee 가

초과 근무 조건을 발생시키는지 검사assertTrue(employee.hasOvertimeFor(newCardDate));

}}

Page 29: 120908 레거시코드활용전략 4장5장

이거 합시다 ~( 이미 했지만 ~)

Page 30: 120908 레거시코드활용전략 4장5장

Fit

• 통합 테스트 프레임워크

• 입력값 , 출력값을 표로 작성

• HTML 형식으로 저장

• 작성한 표가 테스트 루틴이 됨

• 테스트를 통과하면 표의 셀을 녹색으로 표시

• 테스트를 실패하면 표의 셀을 빨간색으로 표시

Page 31: 120908 레거시코드활용전략 4장5장

Fit

• 고객 ( 기획자 ) 이 표를 작성

• 고객과 개발자 간의 의사소통이 쉬움

• 처음에는 모두 실패

• 개발 완료시 , 테스트 모두 통과

Page 32: 120908 레거시코드활용전략 4장5장

Fitnesse

• 위키에 적용된 FIT

• 빠르고 쉽고 테이블을 디자인 가능

• 웹 형태로 제공되어 누구나 쉽게 테스트케이스의 공유 및 작성 , 테스트가 가능

Page 33: 120908 레거시코드활용전략 4장5장

!define TEST_SYSTEM {slim} !define COLLAPSE_SETUP {true}!define COLLAPSE_TEARDOWN {true} !|Create Programs ||Name |Channel|DayOfWeek|TimeOfDay|DurationInMin-utes|id? ||House|4 |Monday |19:00 |60 |$ID=|

Page 34: 120908 레거시코드활용전략 4장5장

NTAF

• 테스트 흐름이 획일적인 Fitnesse 의 단점을 보완

• If, Loop, Parallel 등 키워드 추가

• 로그 확인 , 변수 연산 등 가능

Page 35: 120908 레거시코드활용전략 4장5장

봉합모델레거시 코드를 위한 도구정리가 안되지만 맞는 얘기들

Page 36: 120908 레거시코드활용전략 4장5장

정리가 안되는 맞는 얘기들

• 재사용 가능하도록 작은 조각들로 쪼개 프로그램을 작성하는 것이 좋음

• 자주 독립적으로 재사용되는 모듈화는 어려운 일

• 테스트하면 코드를 다른 각도에서 볼 수 있게 됨

• 테스트 루틴을 작성하려 할 때서야 기존의 코드가 얼마나 엉성하게 짜여져 있는지 알게 됨

Page 37: 120908 레거시코드활용전략 4장5장

비트 경제 (?) 와 공짜 테스트

나는 개발자개발 해서 돈을 벌지 ~

그런데 내가 왜 개발하면서테스트 코드를 만들어야지 ?

테스트는 QA 가 알아서 할텐데뭣하러 공짜로 ?

Page 38: 120908 레거시코드활용전략 4장5장

공짜가 아니야 ~개발 단계에서 작성하는 테스트 코드는QA 가 진행하는 테스트보다비용과 시간이 절감되지

기획과 합심하면 QA 쯤이야그 화폐를 우리 손으로 ~

Page 39: 120908 레거시코드활용전략 4장5장

QA 는 개발자가 할 수 없는 테스트를 찾아서 ..

Page 40: 120908 레거시코드활용전략 4장5장

레거시 코드 활용 전략4 장 봉합 모델5 장 레거시 코드를 위한 도구

감사합니다