반응형

 

 

 

 

 

각 상태 정보를 클래스화해서 상태에 따른 행동을 만들어 놓는 것

 

=> 상태에 따라 행위를 변경해야 할때

 

일반적 관리를 위해 ABC 가 필요

 

 

 

멀티 쓰레드에서도 유리

 

 

 


 

 

각 상태를 나타내는 클래스들이 데이터 멤버를 가지지 않는다면 이들은 공유될 수 있다

 

객체 내부에 데이터 멤버가 없으면 객체는 동일한상태 ==> 서로간의 구분이 필요 없음

 

공유는 Flyweight , 또는 singleton 으로 구현 가능

(구조는 Flyweight 와 singleton 이 유사하다)

 


 

 

상태전환(객체를 누가 바꿀 것인가)

 

1. 클라이언트가  기준에 의해서 상태를 바꿔주는 것

    상태 전환 표에 따라 변환되게 할 수 있지만 , 새로운 상태가 추가 되면 상태표를 다시 고처줘야 한다

    상태객체관리가 보다 쉽다(상태 객체 추가 정도만 하면 되므로)

 

2. 각 상태 객체에서 각 상태가 끝나면 상태 객체에서 다음 상태를 반환

   이때는 각 상태간의 상태를 알아야 하는 상황이 올 수 있으므로 다른 상태 클래스를 추가할 경우 기존 것을 고처야 할 수 도 있다

   대략 mediator , observer 패턴을 연동해본느 것도 아이디어일 수 있다

 

둘다 장단점이 있음

 

 


 

상태 객체 삭제:

 

1. 상태가 공유되는 경우 공유되는 객체에 대한 레퍼런스 카운트를 두어 참조하는 객체가 없으면 소거한다

 

 

2. 필요 없는 상태객체 삭제 => A 객체에서 B 객체 즉 A 상태에서 B 상태로 갈때 A 의 포인터를 가지고 있는

 

    statepointer 를 delete statepointer ; 한 후  B 를  statepointer = new B 한다

 

    상태변환이 적은 경우 유용

 

 

 


 

 

10000명의 플레이어가 있다

캐릭터의 능력레벨이 20단계로 나뉘어진다고 가정하고 각 레벨마다 사용할 수 있는 것이 다르다고 한다, 하지만 중복되는 상태가 있을 수도 있다고 할대

20 단계 이상의 레벨을 추가 또는 삭제 할 수 있는 설계는?

 

=> 먼저 레벨들을 클래스로 만든 후, 1명 마다 각각 상태를 갖으면 낭비가 심함으로 공유되는 상태를 위해 Flywieght 패턴을 적용 할 수 있는데

    각 레벨의 특성마다 클래스가 다름으로 능력레벨에 대한 Abstract Base Class 를 두어 하나로 묶은 후 레벨 추가 삭제가 보다 간편해지게 하고

    유저는 상단 클래스의 포인터를 가지고 있으면 보다 효과 적이다

 

공유한다는 것은 각 레벨 클래스를 한번만 생성해놓고 다른 것들(다른 플레이어들)이 참조한다는 것

 

 

반응형

'디자인패턴과방법론 > 디자인패턴' 카테고리의 다른 글

Template Method 패턴  (0) 2012.11.02
strategy 패턴  (0) 2012.11.02
Observer 패턴  (0) 2012.11.02
memento 패턴  (0) 2012.11.02
iterator 패턴, 스택제거시 삭제되는 포인터(like 스마트포인터)  (0) 2012.11.02
반응형

 

 

 
 
 
 

 

mediator 와 observer 의 차이는

 

observer 는 중심이 되는것이 밖에 있는 것들 즉 중계자가 중심이 되는 것이 아니고

 

중계자가 아닌 밖의 옵저버들이 대한 변경 사항을 subject(중계자) 에게 알리면 변경사항을 나머지 옵저버들에게 알려주는 것이

 

Observer pattern


 

 

A 의 오브젝트 변경사항을 나머지에도 적용 시키는 패턴

 

중간에 Subject 가 이를 반영한다

 

 

 

원래 처음 주어진 환경이 이런 환경

 

 

A(observer object) 에서 변경된 부분을  Subject  에게 전달해주고

 

Subject 는 A 가 업데이트 됐다면 Subject 가 A 에서 읽어와 나머지 오브젝트들(observer objects)에게 변경사항을 알려주는 것

 

 

switch 를 피하기 위해 동일한 인터페이스 사용

 

 

 

 

 

subject 클래스는 내부적으로 observer objects 를 리스트로 관리할뿐 구체적으로 어떤 observer object 들인지는 관여하지 않는다

=> 즉 동일한 인터페이스를 갖는다

 

 

서로 업데이트 하려고 하는 경우 같은 정보로 변경할 경우 subject 에서 정볼르 받아 쌓아놨다가 이전에 바꿨던것과 동일한가를 비교

 

이렇게 알려주려면 알려주기 위한 클래스를 생성 해야 한다

 

 

subject 가다른 observer objects 와 동일한 데이터 일경우 싱글톤으로 만들 수도 있다

 

 

subject 가 여러개가 있고 observer 가 여러개 있을 수 있다

 

 

 

업데이트시 this  를 넘겨줌

 

 


 

 

subject 가 소멸되는 경우 각 observer objects 들은 소멸 하거나 어떤 처리를 해야 함

 

 

 

setstate() 함수 호출의 순서를 조절할 수 있는 것이 themplate method 패턴을 참고

=> subject 에서 값변환 먼저 실행후 notify 실행, 각 옵저버 객체에서도 동일하게 추가 되야 함

 

 

 

-특정 값이 바뀌었을때는 subject 에 클래스를 미리 등록 시켜 놓고 관심 있는 옵저버 클래스에게만 알려 효율 올림

 

 

 

-


 

 

 

오브젝트 N 개 서브젝트 M 개 일때

 

중간에 change manager 를 두고 이 사이를 관리할 수도 있음

 

change manager 를 상속 받는 manager 의 종류를 또 분류하여, 변경사항을 다 통보해주는 매니저로 갈지

 

변경사항이 연관있는 옵저버오브젝트들에게만 알릴지를 정할 수도 있다( 전자의 경우 mediator 와 유사)

 


 

 

한 노드가  subject 와 observer 역할을 둘다 할 수도 있다

 

옵저버가 다른 옵저버와 연결 되는 경우

 

1. 다중상속

2. 다중상속이 힘든 환경이면 subject ,observer 클래스를 따로 구현 하지 않고 하나로 두어 구현

 

 

 

 


 

 

 

 

스트크래프트 미니 맵에서 적은 안보이고 우리만 보이는 상황

 

전체 오브젝트에 대해서 서브젝트가 가지고 있는데

 

Subject 에서 A편, B 편, 관람자들의 리스트를 따로 가지고 있어서

 

연관된 사람들에게만 오브젝트 위치를 보여준다

 

 

반응형

'디자인패턴과방법론 > 디자인패턴' 카테고리의 다른 글

strategy 패턴  (0) 2012.11.02
state 패턴  (0) 2012.11.02
memento 패턴  (0) 2012.11.02
iterator 패턴, 스택제거시 삭제되는 포인터(like 스마트포인터)  (0) 2012.11.02
interpreter 패턴  (0) 2012.11.02
반응형

 

 

 

 

 

 

 

 

상태정보 저장이 목적

 


 

 

undo, redo 같은 기능을 실행 하기 위해선 변경된 정보 , 심할 경우 변경된 상태의 전체 정보를

 

따로 저장 관리하는 클래스를 두는 것을 memento 패턴이라 한다

 

 

일반적으로 필요한 정보만 따로 모아 관리 하는 것을 말한다

 

 

 

 

행동:

저장할 필요 정보를 memento 에 저장했다가 다시 돌리고 싶을때 memento 에서 다시 불러온다

 

또한 해당 객체 상태를 직접 접근하는 것이 어려운 경우 상태 정보를 memento 로 빼놓아

 

클라이언트가 객체의 은닉성을 깨트리지 않고 상태 정보를 알기 위해 memento 로 저근하는 상황에서도 사용 될 수 있다

 

 

이처럼 직접 접근하지 못하게 경계 역할도 할 수 있다

 

 

하지만 원래 memento 에 상태를 저장하는 객체는 memento 객체를 마음대로 다루길 원함으로

 

friend 로 선언해 주는 것도 좋다

 

하지만 다른 것이 접근할때는 private 로 선언하는게 좋다

 

 


 

모든 값을 다 저장해서 가지고 있으면 비효율적이므로 변경된 부분만 관리 한다( 이부분 설계가 관건)

 

 

지나치게 memento 에 다른 클라이언트가 접근해 모두 막 상태를 바꾸는 구조는 좋지 않다

 

 

redo/undo 같은 경우  메모리가 많이 커질 수 있음으로 횟수의 제한을 두는 것이 좋다

 

 

command 패턴과 memento 패턴을 같이 사용하여 명령을 memento 에 저장해 놓으면 효과적이다

 

 

 

 

 

 


 

 

 

 

memento 할(저장할) 단위 설정이 중요

 

단위가너무 작으면 저장된는 것이 많아 질 수 있다

 

 

반응형

'디자인패턴과방법론 > 디자인패턴' 카테고리의 다른 글

state 패턴  (0) 2012.11.02
Observer 패턴  (0) 2012.11.02
iterator 패턴, 스택제거시 삭제되는 포인터(like 스마트포인터)  (0) 2012.11.02
interpreter 패턴  (0) 2012.11.02
command 패턴  (0) 2012.11.02
반응형

 

 

 

 

 

 

 

예를들어 list 의 경우

 

list 내부에 포인터를 두면 멀티플(멀티 쓰레드)로 list 에 접근할때 오류가 생길 수 있는데

 

이것을 객체로 두면 멀티플로 접근이 가능해진다

 

즉 접근 포인터를 객체로 둔것이 iterator 패턴이다

 

 

굳이 필요한 상황 아니면 type<T>::iterator it; 쓰는게 났다

 

 


 

 

 

리스트자체에서 리스트에 대한 이터레이터를 만들때의 구현

( iterator 가 없어질때 List 를 동적 또는 정적 할당 하지 않았음으로 삭제 과정은 필요 없고 new 한 Listiterator 만 삭제 하면 된다

pListiter 으로 함수 안에서 생성된 list 를 다룰 수 있다

 

ListIterator* pListiter = list.createiterator();

 

했을때..

 

       iterater* createiterator(){

            return new ListIterator(this);   // this 는 리스트의 주소

       }

 

 

 

class ListIterator: public Iterator {
  public :
    ListIterator(LinkedList* pList){  this->pList = pList;  }

 

  private :
    LinkedList* pList_;
};

 

반응형

'디자인패턴과방법론 > 디자인패턴' 카테고리의 다른 글

Observer 패턴  (0) 2012.11.02
memento 패턴  (0) 2012.11.02
interpreter 패턴  (0) 2012.11.02
command 패턴  (0) 2012.11.02
chain of responsibility 패턴  (0) 2012.11.02
반응형

 

 

 
 

 

 

 

문법에 대한 패턴, 간단한 연산 등 간단한 스크립트 같은거나 간단한 정규식 그리고 비교적 작은 형태일때

 

속도가 안중요할때 쓰임

 

처리 영역을 나누지 않고 한번에 처리할때

 

 

복잡한 경우에는 다루기 힘들다

 

 

interpreter 패턴은 파싱을 하지 않고 바로 객구조를 만들어 사용

 

interpreter 패턴에 멤버  함수를 정의하는 것이 번거로운 경우 vistor 패턴을 각 연산마다 적용하여

 

추상노드를 순회하도록함으로써 interpreter 패턴의 수행역할을 동일하게 할 수 있다

 

 

 

장점 : 문법에서 클래스 구조를 만들어 내고 만들어진 클래스 구조를 보고 다시 문법을 봐 성립하면 이것이 맞는 구조라 할 수 있음

 

 

 

 XML DTD 문법이 맞는지 체크하라

 

즉 간단한 문법이 있는데 이것을 프로그램으로 읽어 들였을때 맞는 것인지 확인

 

<!Element purchaseOrder (shipTo,BilTo,Item) >

<!Element shipTo (Name,Street,city,state,country,zip) >

<!Element BilTo (Name,Street,city,state,country,zip) >

<!Element Item (ProductNo,quentity, price, ItemName,orderDate) >

<!Element Name (#PCdate) >

 

 

위는 아래와 같다

 

purchaseOrder := shipTo & BilTo & Item +

shipTo := Name & Street .. 이런식

 

 

+ 는 한번이상 나타난다

* 는 0번 이상 나타난다

 

 

purchaseOrder,shipTo  왼쪽에 나타나는개 클래스 

 

 

XML 이 문법을 만드는 것인데 이 문법이 맞는것인지 아닌지를 확인 할때 interpreter 패턴을 사용 할 수 있다

 

 

 


 

클래스 구조적 포인트는

 

연산자이든, 문자열이든 동일한 부모 추상클래스를 두어서 실행시키는 함수를 virtual 로 정의해놓고 이 함수를

 

수행하는 것

 

 

즉 연산자와, 문자를 파싱할때 동일한 부모이니 연산자이든 문자이든 동일한 타입의 부모로 캐스팅 됨을 이용하여

 

보다 간결한 구조로 조사와 순회 할 수 있다는 것

 

반응형
반응형

 

 

 

 

 

command 패턴이란?

 

요청과 이 요청을 처리할 객체를 중계하기 위한 클래스 상속구조를 말한다

 

 

여라가지의 처리할 명령을 'A' 에서 요청할 경우 'A'쪽의 명령들을

 

Abstract Base class 기반으로 구성하여 각 명령에 대해 처리할 관련있는 클래스들끼리 참조 또는 할당하여 하나의 객체로 구성하여

 

map 등으로 명령과 클래스를 같이 갖고 있는 형태로 만들어 놓은후

 

B 쪽에서 이것을 처리할때

 

A 에서 만든 상속구조처럼 묶어 처리하는 패턴

 

오고 가는 것은 map 의 value 가 오고 가지만 이 value 에 대한 명령 처리를

 

B쪽에서는 해당 처리해야 할 서브 클래스에 대한 해당 명렬을 처리할 클래스를 추출해 낼 수 있음으로

 

이 둘의 연결 구조를 보다 각각의 지역적으로 분할된 형태로 처리 할 수 있다

 

 

 

 

2. callback 버튼 실행 명령 함수에 이를 대입할 수 있다

  C 함수는 괜찮은데 , 멤버 함수를 callback 으로 부를 경우 문제가 될 수 있는데 이때 사용 할 수 있다

 

3. redo, undo 에 적용 하기 쉽다

 

  각 명령에 대해서 동일한 인터페이스로 처리 가능

  즉 동일한 데이터 타입으로 명령을 처리 할 수 있고 필요 한 클래스들만 있으면 된다

  => 동일한 데이터만 핸들링 하면 된다

 

 undo/redo 의 순서는 memento 패턴으로 해결 하면 된다

 

 

 

또한 undo/redo 의 객체 상태 저장은 prototype패턴 or 바뀐부분을 저장하는 방법 memento 패턴을 활용(상태 값을 저장해 놓는 형태)

 

 

*undo/redo 는 연산을 했던걸 다시 역으로 하는 것보단, 상태값으로 그때의 상태를 제연하는 것이 좋다

 

 

4. protocal 과 같은 명령에 대한 처리에도 유용하다

 

5. makefunctor( (functor1*), ai, show );   <= 표기 정확하지 않음 대략적으로 표기

같은 것 또한 전역 함수나, 멤버함수를 동일한 형태로써 두개를 수행 할 수 있는 것과 같은 것도 command 패턴의 유형과 개념상 비슷하다고 볼 수 있다


 

 

명령종류의 자체가 많아 지면 command 들의 상위인 command 클래스가 필요한데 이렇게 명령의 종류가 많아지면

 

composite 패턴과 연동하여 한번에 처리 할 수 있게 한다

 

동일한 레벨을 묶고 있는게 composite 이니깐 동일하게 묶고 있는것에 대해 전체를  돌면서 다 실행하는 virtual 함수 실행

 


 

 

 

명령의 종류에 대해 나뉘어지는 형태이므로

 

다른 유사 명령과 교체하여 실행을 다르게 설정 할 수 도 있다


 

또한 복합적인 명령을 수행해야 하는 경우

 

서브 command 클래스를 만들 필요 없이

 

중간에 macrocommand 클래스를 만들어 두어 이 클래스에서 명령을 조합해 실행하는 클래스를 두는 것이 효과적이다

 

 

 


 

 

 

macrocommand 클래스를 활용할 경우 스크립트의 작업형태도 처리 가능하다

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

execute( ) 의 수행함수에서 인자를 줄려면 다 주던지 안주려면 다 안주던지 해야 한다

함수에 인자가 들어가면 인자타입이 다 틀려지고 부르는 쪽도 맞춰 틀려져야 하기 때문에 처리가 복잡해 진다

 

각 명령에 대해 한 클래스들이 명령을 처리할 클래스들을 생성자의 초기 값으로 넘겨주게 된다

이때의 생성자 초기 값은 상관 없음으로 명령을 수행할 execute() 함수만 불러주면 되기 때문

 

 

반응형
반응형

 

 

 
 

 

 

 

 여러 오브젝트가 있을때 현재 자신이 처리할 수 있으면 처리를 하고 끝내지만 현재 자신이 처리하지 못하면

 

다음 오브젝트로 일을 보내 처리하도록 한다

 

흐름적 이점 : switch  구문을 제거 할 수 있다

 

한 프로젝트의 도움말에 대한 사항을 분기문이 아닌 chain of responsibility  패턴으로 처리할 사항을 다음 클래스로 넘기며 처리 할 수 있는데

 

 

A, B ,C ,D, E, .... N 의 클래스가 있을때

 

 A 에서 처리할 수 있는 도움말이면 A 에서 처리 하지만 A 에서 처리 할 수 다음 포인터 주소를 통해 다음 클래스로

 

처리를 넘긴다

 

A                  

success() --------------->B

                                         success()--------------->C

                                                                                 success()---------------->

 

 

DNS 처리 또한 유사하게 처리 될 수 있다

 

단 처리 됐는지 처리 되지 않았는지 처리를 넘긴 다음에는 알지 못한다

즉 정확히 어떤 객체가 처리하는지 모른다

 

 

 


 

 

도움말, 프린트, 응용프로그램 등등에 대한 각 가지 다양한 종류에 대한 처리 사항을 클라이언트가 요청 할 수 있는데

 

그때는 요청의 종류 req->GetRequestofKind() 와 같은 종류를 구분 할 수도 있지만 좀 더 나은 방법은

 

Dynamic_cast 로 현재 넘어온 클래스가 어느 부류에 속하는 클래스인지 다운캐스팅 테스트를 해보아

 

 

Dynamic_cast  가 0 을 리턴하면 현재 상속구조의 클래스가 아님으로 다음 분기문에서 다시 다른 종류에 대한 클래스의 다운 캐스팅을

 

시도해보아 맞을때까지 분기문을 놓는 식으로 처리 한다

 

 


 

 

 

 

패턴을 오히려 너무 많이 남발하면 좋지 않다

 

적시 적소에 쓸 수 있어야 한다 chain of responsibility 패턴 과 쓰일 수 있는데

 

다음 노드로 넘어가야 하느냐 말아야 하느냐가 각 노드마다 공통인 부분이기 때문에 이 부분에 대해서 Template Method 패턴이 쓰일 수 있다

 

다음 으로 넘어가지 않는다고 하면 Template Method 를 지나쳐 다음을 수행 하면 되기 때문..

 

 

 

 

 


 

 

 

Template method 패턴이

 

 

 

반응형
반응형

 

 

 

 

기본 변하지 않는 클래스의 계층 구조에서 변하는 부분의 클래스의 추가, 정의 등이 필요할때

 

기존 구조를 거의 무너트리지 않고 변하는 부분을 만들 수 있는데 그것을 스트레티지 패턴이라 한다

 

 

point 는 포함 관계로 변화되는 클래스를 변하지 안흔 클래스의 부모에 포함 시켜서

 

클래슬르 만들때 원하는 행동의 클래스를 업케스팅해주면 된다

 

 

또한 기존에 돌아 가고 있던 행동을 쉽게 교체 하기 위해서도 많이 쓰인다

 

 


 

 

 

http://tongins.blog.me/80096279721

 

[패턴] Strategy Pattern  


복사http://tongins.blog.me/80096279721
 

 


 




스트레티지 패턴은 런타임 시점에서 알고리즘을 선택할 수 있는 독특한 디자인 패턴입니다.
이 패턴은 객체 지향 언어의 특성인 다형성을 사용한 패턴입니다.
스트레티지 패턴은 어플리케이션이 동작하는 상황에서 해당 기능에 대한 알고리즘을 교체하고자 할때 유용합니다.
이 패턴의 이름이 Strategy라고 불리우는 이유는 전쟁중에 이기기위해 싸우는 수단을 다양하게 바꾸는 상황과 프로그램이 동작하는 중에 알고리즘을 동적으로 교체하는 상황이 비슷하기 때문일 것입니다. 

 

 

스트레티지 패턴은 복잡하거나 어려운 패턴은 아닙니다.

프로그래밍을 하다 보면 if문을 제거하고 싶어질 때가 있습니다.

이때 자연스럽게 스트레티지 패턴을 만들어서 사용하게 될 때가 있습니다.

 

 

 

 

 

 

위 다이어 그램에 대한 C# 소스는 아래와 같습니다.

  1. using System;
  2.  
  3. namespace Pattern.Strategy
  4. {
  5.     class MainApp
  6.     {
  7.         static void Main()
  8.         {
  9.             Context context;
  10.  
  11.             // Three contexts following different strategies
  12.             context = new Context(new ConcreteStrategyA());
  13.             context.ContextInterface();
  14.  
  15.             context = new Context(new ConcreteStrategyB());
  16.             context.ContextInterface();
  17.  
  18.             context = new Context(new ConcreteStrategyC());
  19.             context.ContextInterface();
  20.  
  21.             // Wait for user
  22.             Console.ReadKey();
  23.         }
  24.     }
  25.  
  26.     /// <summary>
  27.     /// The 'Strategy' abstract class
  28.     /// </summary>
  29.     abstract class Strategy
  30.     {
  31.         public abstract void AlgorithmInterface();
  32.     }
  33.  
  34.     /// <summary>
  35.     /// A 'ConcreteStrategy' class
  36.     /// </summary>
  37.     class ConcreteStrategyA : Strategy
  38.     {
  39.         public override void AlgorithmInterface()
  40.         {
  41.             Console.WriteLine(
  42.                 "Called ConcreteStrategyA.AlgorithmInterface()");
  43.         }
  44.     }
  45.  
  46.     /// <summary>
  47.     /// A 'ConcreteStrategy' class
  48.     /// </summary>
  49.     class ConcreteStrategyB : Strategy
  50.     {
  51.         public override void AlgorithmInterface()
  52.         {
  53.             Console.WriteLine(
  54.                 "Called ConcreteStrategyB.AlgorithmInterface()");
  55.         }
  56.     }
  57.  
  58.     /// <summary>
  59.     /// A 'ConcreteStrategy' class
  60.     /// </summary>
  61.     class ConcreteStrategyC : Strategy
  62.     {
  63.         public override void AlgorithmInterface()
  64.         {
  65.             Console.WriteLine(
  66.                 "Called ConcreteStrategyC.AlgorithmInterface()");
  67.         }
  68.     }
  69.  
  70.     /// <summary>
  71.     /// The 'Context' class
  72.     /// </summary>
  73.     class Context
  74.     {
  75.         private Strategy _strategy;
  76.  
  77.         // Constructor
  78.         public Context(Strategy strategy)
  79.         {
  80.             this._strategy = strategy;
  81.         }
  82.  
  83.         public void ContextInterface()
  84.         {
  85.             _strategy.AlgorithmInterface();
  86.         }
  87.     }
  88. }

관련 URL:

http://www.cumps.be/design-patterns-strategy-pattern/

http://en.wikipedia.org/wiki/Strategy_pattern

 

 

반응형
반응형

 

 

 
 

 

A ,B , C,D ... N 개의 객체들간의 통신을 하려고 할때

 

그리고 이것들이 상속구조를 이루고 있다면 통신하기 위해 직접 연결 한다면 상당히 지저분한 상태에 이르고 만다

 

 

그래서 클래스 중계자(mediator) 하나를 둬서 변경 된 사항을 mediator 에게 던지고 적용시킬지니는 mediator 가 수행하는 패턴을

 

mediator 패턴 이라고 한다

 

 

observer 는 옵저버가 중점이고 mediator 는 mediator 가 중점이다

 


 

 

 

그래서 mediator 의 내부는 좀 복잡해 질 수 있고 통신할 것들에 대해 다 알고 있어야 한다

 

 

또한 mediator 와 연결될 다른 객체들도 mediator 를 연결해야 한다

다른 객채들과의 통신을 mediator 와 통신한다

 

 

장점 : 재사용이 쉬워진다 => A 객체만 재사용 하고 싶으면 A 하나 때내고 mediator 부분에서 A 에 대한 부분만 수정해 주면 됨으로

 

분산된 것을 한곳으로 모여줌 N:M 관계를 1:M 관계로 변경

 

차이:

Facade 와 차이점은 Facade는 일반적으로 단방향이지만 Mediator 는 양방향이다

 

차이:

Observer 는 중앙이 아닌 밖의 것이 중점이 된다

 

A 에서 값이 바뀌면 중계 해주는 곳에 A 가 알려주고  중계 해주는 곳이 나머지들에게  A 값이 바뀌었다고 알려주는 형태

 

구성형태는 Oberser 와 Mediator 와 같긴하다

 

 

 

변화 상태는 this 를 멤버함수 인자로 넘겨서 알리는 방법이 있다

 

 

 

활용

 

메신저 대화명 바꿀때

 

if A ,B 가 서로 친구 일때

 

중간 mediator 가 서로 연결된 친구라면 A 에서 대화명을 바꿨을때 바꾼 대화명을  B 에게 알려준다

 

 

또는 B 는 바뀌는게 싫다고 mediator 에게 요청하면 변경사항을 받지 않는 처리도 할 수 있다

 

 

 

기계가 여러대 있을때 기계 서로의 속도 제어등 전체 조정

 

하지만 각각의 기계가 각자 동작하진 않고 중앙관리 형태로 구성이 되야 한다는 것이 Mediator 패턴의 컨셉

 
 

 

반응형
반응형


블로그 이미지

3DMP engines


 가상 소멸자가 없을때 컴파일 오류 : error C2683: 'dynamic_cast' : 'A'은(는) 다형 형식이 아닙니다.

 


 

class A{
public :
 A(){}
 virtual ~A(){}
};

class C : public A{
public :
 C(){}
 ~C(){}
};


class B : public A{
public :
 int num;
 B(int dd) : num(dd) { }
 B() {}
 ~B(){}


};

 


int _tmain(int argc, _TCHAR* argv[])
{

 A* ci=new A;
 B* bi= dynamic_cast<B*>( ci );
 cout<<dynamic_cast<B*>( ci )<<endl;      // 000000000

 

 return 0;
}

 

 


[직렬상속구조]

 

A <- B <- C  상속 구조에서 자식이 어느 자식인지 확인하는 방법

 

#include <iostream>
#include <list>
#include <iterator>
#include <map>
using namespace std;

class Graphic {
public :
 Graphic(){}
 virtual void Draw(){
  cout<<"Graphic\n";
 }
};


class ComposedGraphic : public Graphic {
public :
 ComposedGraphic(){}


 void Add(Graphic *pObj) {
  cout << "ComposedGraphic" << endl;
 }
};

class SpecificComposedGraphic : public ComposedGraphic {
public :
 SpecificComposedGraphic(){}
 void Draw() {
  cout<<"SpecificComposedGraphic\n";
 }

 void Add(Graphic *pObj) {
  cout << "Specific-ComposedGraphic" << endl;
 }
};

void main()
{
 Graphic *pObj = new ComposedGraphic;
 
 cout<<dynamic_cast<ComposedGraphic*>(pObj)<<endl;                   // 주소값 존재
 cout<<dynamic_cast<SpecificComposedGraphic*>(pObj)<<endl;       // 000000000

 

                 // if 문으로 확인할 경우 제일 하단의 클래스부터 dynamic_cast 을 거처서 어느 자식의 클래스인지 확인해야함


 delete pObj;


 pObj = new SpecificComposedGraphic;

 cout<<dynamic_cast<ComposedGraphic*>(pObj)<<endl;                   //주소값 존재
 cout<<dynamic_cast<SpecificComposedGraphic*>(pObj)<<endl;       //주소값 존재


 delete pObj;
}

 

 





아래부터는 퍼온자료.....


[병렬상속구조]

 

Graphic<---- 클래스A

Graphic<-----클래스B

인 병렬 상속구조일때 해당 클래스가 어느쪽 자식 클래스인지 확인하는 방법

 

 

#include <iostream>
#include <list>
#include <iterator>
#include <map>
using namespace std;

class Graphic {
public :
 Graphic(){}
 virtual void Draw(){
  cout<<"Graphic\n";
 }
};


class A : public Graphic {
public :
 A(){}
 virtual void Draw(){
  cout<<"A\n";
 }
};


class ComposedGraphic : public Graphic {
public :
 ComposedGraphic(){}


 void Add(Graphic *pObj) {
  cout << "ComposedGraphic" << endl;
 }
};

class SpecificComposedGraphic : public ComposedGraphic {
public :
 SpecificComposedGraphic(){}
 void Draw() {
  cout<<"SpecificComposedGraphic\n";
 }

 void Add(Graphic *pObj) {
  cout << "Specific-ComposedGraphic" << endl;
 }
};

void main()
{
 Graphic *pObj = new A;
 
 cout<<dynamic_cast<ComposedGraphic*>(pObj)<<endl;                    // 00000000
 cout<<dynamic_cast<SpecificComposedGraphic*>(pObj)<<endl;         // 00000000
 cout<<dynamic_cast<A*>(pObj)<<endl;                                            // 주소값

 delete pObj;
}

 

 

 

 

 

 

 

 

 

 

 

 

 


반응형

'디자인패턴과방법론 > 패턴정리와스킬' 카테고리의 다른 글

GOF 디자인패턴 정리  (0) 2012.11.01
반응형



블로그 이미지

3DMP engines


[설계 과정]

 

1. 문제의 목적?

 

2. 어떤 패턴?

 

3. 세부적인 해결 방법

 


 

 

 

아키텍쳐 설계   : 큰 레벨에서 분류 하는 것

ex) 클라이언트 서버가 어떻게 돌아가느냐, 디비가 어떻게 있느냐

 

문제를 나누는 것

 

전체 문제를 쪼개는것 => 목적을 쪼개 나가는 것

 

 

이를 전체적으로 쪼개면 프로세스정도로 구분이 되고 이 프로세스를 설계할때

 

클래스 설계에서부터 패턴으로 올라가면서 설계한다

 

 

ex)

웹브라우저 -----> 웹서버 --------> WAS(웹 어플리케이션) [ 디비핸드링, 비즈니스 로직 ]

 

웹브라우저 ,웹서버 , WAS 까지 나누는 레벨이 아키텍쳐설계

 

웹브라우저를 짜겠다, 웹서버를 짜겠다  WAS 를 짜겠다는 것은(디비핸들링, 디브니스 로직 으로 들어가면)

클래스 디자인으로 들어감

 


 

 

 

 

클래스 정의는? : 클래스 정의는 알아서 한다( 클래스는 알아서 끌어낸다) 분석단계 등에서..

 

 

분석단계에서 데이터 모델링한다

(데이터 모델링 : 현실세계에 있는 것을 개체로 이끌어 내면서 구체화해 가는 과정 )

클래스는 명사를 찾아라

 

이런걸 이용해서 클래스를 끌어내야 한다, 클래스를 정의 해야 한다

 

이제 여기에서 클래스들을 어떻게 최적화 시킬것인가에 대한 패턴을 대보는것 => 디자인 패턴

그래서 디자인패턴은 상세설계에서 사용하게 된다

 

* 패턴도 패턴안에서 섞일 수도 있다 즉 => 목적두개가 겹친다

 

 

 디자인패턴은 클래스 구조( 화살표) 를 먼저 보는 것이 아닌 목적을 먼저본다음 클래스 구조를 봐야 한다

 

 

 


 

 

 

-product family 를 만들기 위한 패턴 = Abstract Factory

 

-부분 부분을 생성해서 전체를 생성하는것 = builder

 

-객체 생성을 대행해주는 함수 = Factory Method

 

-복제해서 객체를 생성하고 싶으면 = ProtoType

 

-Maximum  N 개까지만 객체를 생성하고 싶으면 = SingleTon

 

-기존 객체를 사용하고 싶은데 인터페이스가 틀리다 = adapter 

[구조] adapter 패턴 (잘 구현된 클래스에 구현할 기능이 있는 경우 클래스를 private 으로 상속 하는 패턴)

 

-처음 클래스를 설계하면서 interface 와 information 을 나누어서 설계하고 싶다 = bridge

[구조] bridge 패턴 (구현부와 인터페이스를 나누어버리는 패턴 ,여러 환경에서 조사된 가장 적합한 기능에 대해 연결해주는 패턴 대신 실행하는 패턴)

ex) 1.가장 적절한 클래스를 생성해 리턴(unix,window , etc... 등등...)

      2.여러 클래스가 해당 플렛폼에 대해 동일한 클래스(정보) 를 자동으로 플렛폼에 맞게 얻고자 할때

 

-tree 형태로 객체부수를 관리하고 싶다 = composite

 

-동적으로 객체의 기능을 확장시켜 나가고 싶다 = decorator

[구조] decorator 패턴 ( on,off 없이 윈도우에 추가되는 스크롤 같은것 연달아 추가 )

(객체 추가되면서 추가된것 다 실행됨 : 객체가 다음실행할 객체를 (중간)Decorator 클래스 포인터로 가지고 있음)

 

-서브시스템을 대표하는 인터페이스를 갖고 싶다 = Facade

 

-객체를 공유하고 싶다 = Flyweight

 

-중간 매개 개체를 이용해 원객체에 대해 접근제어라든지 추가적인 작업을 하고 싶다 proxy

 

-동적으로 수행할 역할을 이행 시키기, 위임시키기 위해 연결해 놓은 것을 처리 하고 싶다 = chain of responsibility

[행동] chain of responsibility (동적으로 처리할 역할을 연결해 놓은 것, 책임(조건)에 따라 처리 사항을 다음으로 넘기는 것, 처리를 분담)

// 현재 클래스에서 처리하지 못하면 부모클래스에서는 다음 객체포인터를 가지고 있어서 그 객체 포인터로 책임전가

  (객체 추가는 없고 고정된 상태)

 

-수행할 작업을 일반화 시켜서 핸들링 하고 싶을때 = command

  (하나의 함수 명령으로 수행)

 

-어떤 문법에 따라서 파싱하고 원하는 작업까지 동시에 하고 싶다 = interpreter

 

-어그리게이트의 구성요소를 차례로 접근하고 싶다 = iterator

 

-M:N 관계를 1:N 관계로 바꾸고 싶다 = mediator

 (중계자)

 

-객체의 상태정보를 별도의 객체에 저장하고 싶다 = memento

 (저장만 하는 것만!!)

 

-객체 상태정보를 저장하기도 하고 상태에 따라서 행위까지 핸들링 하고 싶으면  = state

 [행동] state 패턴 ( 각 상태에 대해 객체로 만들어 분리 처리하는 것 , 게임능력레벨에 해당하는 행동을 클래스로 분류해서 처리  )

 ex) 각 레벨에 따른 행동 또는 상태 정보가 각 레벨 클래스마다 있고 이 클래스들은 공통적인 것이므로 singleton 처럼 객체가 공유된다

 

-1:N  의 관계를 유지하면서 객체간의 행위를 분산하고 싶을때 = observer

subject 에게 observer 가 변경상태를 통지하면 subject 가 나머지 observer 들에게 변경 내용을 알려주어 변경 내용(상태)에 따라

나머지 observer 들이 그 내용에 맞게 수행하는 패턴

 

-동일 목적의 여러 알고리즘 들을 동적으로 변경시키고 싶다 = strategy

  [행동]Strategy 패턴 같은 목적을 수행하는 알고리즘을 동적으로 바꾸고 싶을때

 

-알고리즘의 기본 골격을 만들어 놓고 난다음 세부 알고리즘은 하위 클래스에서 알아서 바뀌도록 하고 싶다 = Template method

 [행동] Template Method 패턴 (공통된 알고리즘 부분이 고정적일때 사용, 기본 알고리즘 골격을 상위 클래스에서 갖도록 한다 ) 

 하위 클래스에서 구체적으로 처리하기 

  : instance 는 자식으로 생성해놓고 부모에만 정의된 함수를 호출하여 이 함수 안에 virtual 로 선언된 공통함수를 호출하여

    instance 를 만든 자식의 virtual 함수가 불리도록 하는 흐름

 

 

-작업 대상과 작업 종류 작업 항목을 분류해서 작업종류를 임의로 추가하는 것을 유연하게 하고 싶다 = visitor

 [행동] visitor 패턴 (고정부분과 동적인 부분을 클래스에서 분리)

 : 데이터 구조와 처리를 분리 하는 패턴.
   > 필요할 때 : 처리를 데이터 구조에서 분리해야 할 때. => 결합도를 낮춘다

  'strategy 패턴과 응용해서 사용


 

디자인패턴을 실제 어떻게 적용할 것인가?

 

 

한번만에 최적이 나오긴 힘들다, 한번 이터레이션 해보고 Localizatio of change(변경을 국지화) 를 할 수 있는가?

 

를 따져보고 된다면 판단하고 적용

 

 

변경 안되는 부분, 변경되는 부분을 고려햐여 고려

 

일단 패턴을 알면 보통이상의 퀄리티를 보장해 줄 수 있다

 

중요한 점은 어떤 목적으로 접근할 것인가 하는 것이다

많은 고민에 의해서 적용해야지 대강 생각해서 적용해버리면 일정 수준이상에서 퀄리티가 올라가지 않을 수 있다

생각을 많이 해보자

 

 

 

무엇을 할것인가? => 뭘 할껀데?   => 목적이 무엇인가

 

어떻게 할것인가 => 최적화적인것을 판단

 

 








이하 자료는 퍼온 자료들..



 

디자인패턴들의 상관관계

 

 

 

 

 

[관계도 설명]

 

 

-builder 패턴은 composite 객체를 생성하기 위해 사용 될 수 있다

 

-iterator 패턴은 Composite 객체를 구성하는 하위 객체들을 순회하기 위해 사용 될 수 있다

 

-Command 패턴은 MacroComand 클래스 등의 정의시 Composite 패턴을 활용 가능하다

 

-chain of responsibility 패턴은 객체들간의 연결 사슬을 composite 패턴을 이용하여 정의 할 수 있다

 

-composite 객체를 구성하는 각 하위 객체들에게 새로운 연산을 추가하 위해 visitor 패턴이 사용 될 수 있다

(트리 구조에서 각 노드마다 새로운 연산을 위해 함수들을 visitor 로 만들 수 있다)

 

-interpreter 패턴은 문법을 정의하는 과정에서  Abstract Syntax Tree 를 Composite 패턴으로 표현할 수 있다

  (트리가 composite로 표현)

 

-Composite 객체를 구성하는 하위 객체들은 Decorator 패턴을 이용하여 추가적인 역할을 수행하도록 설계 될 수 있다

 

- Flyweight 패턴은 Strategy, State, interpreter 패턴에서 알고리즘이나 상태정보, Terminal Symbol 들을 각각 공유하기 우해 사용 될 수 있다

 

- Decorator 패턴은 이미 존재하는 객체에 새로운 기능을 덧입히는 역할을 하는데 반해

Strategy 패턴은 객체 내부의 구체적인 동작이나 알고리즘을 외부 객체에게 위임시키는 형태이다

그래서, Decorator 패턴은 객체의 겉을 변경시켜주는 역할이고, Strategy 패턴은 객체의 속을 변경시켜주는

역할을 한다고 할 수 있다

 

- Memento 패턴은 Iterator 패턴이 반복 상태를 저장하기 위해 이용 할 수 있으며

  Command 패턴이 명령 수행 이전 상태로 되돌아가기 위해 사용 할 수 있다

 

- Observer 패턴은 객체들 간의 의존 관계를 분산 시켜 관리하는 데 반해 Mediator 패턴은

중앙 집중적으로 관리하기 때문에 복잡한 의존 관계를 한 곳에서 관리하고자 할 경우에는

Mediator 패턴이 효과적이다

 

- Template Method 패턴은 내부의 알고리즘 단계를 정의할 때(변하지 않는 부분) Strategy 패턴을 사용 할 수 있으며

, 대개 Factory Method 패턴을 사용하여 필요한 객체를 생성한다

 

- Abstract Factory 패턴은 종종 Factory Method 패턴이나 Prototype 패턴을 이용하여 구현되며,

  Singleton 패턴을 이용하여 하나의 공유되는 객체를 관리할 수 있다

 

- Singleton 패턴은 Facade 패턴에서도 하나의 객체를 공유하기 위한 목적으로 사용 될 수 있다

 


 

아래 있는건 다른곳에서 퍼온 것 


http://mrnoname.blog.me/130112026691

 

 

JAVA 언어로 배우는 디자인 패턴 입문

작가
유키 히로시
출판
영진닷컴
발매
2008.05.01

리뷰보기


 상반기 개인 학습 목표로 디자인 패턴을 선택한 관계로, 한 동안 'Java 언어로 배우는 디자인 패턴 입문' 이라는 책으로 디자인 패턴에 대해서 알아보았습니다.

 이미 책을 보기 전부터, 코딩을 하며 Singleton이라던지 Factory Method 패턴들을 접해보았고, 직접 적용도 조금 해봤기 때문에, 대략적으로 디자인 패턴이 무엇인지는 어렴풋이 알고 있었습니다. 그래서 이번에 디자인 패턴 학습에서는 '어떤 디자인 패턴들이 있고, 어떨 때 사용해야 될 까?'에 대해서 알아보는 것에 중점을 두었습니다.

 디자인 패턴 관련 서적 중에 가장 유명한 책은 'Head First 디자인 패턴'이었는데, 개인적으로 Head First 시리즈는 그냥 그냥 보기에는 좋지만, 나중에 머리에 남는 것이 별로 없는 것 같아서, 조금 딱딱해 보여도 실질적인 예제 코드들로 설명이 잘 되어있다는 'Java 언어로 배우는 디자인 패턴 입문'을 고르게 되었습니다.

 처음에는 처음부터 순서대로 읽어가면서 정리를 해보자는 생각으로 책을 읽기 시작했는데, 점점 정리를 하다 보니 '아, 이러면 안되겠구나…'라는 생각이 들었습니다. 예전에 개발을 하고 싶지만 전혀 못하던 시절, C++ 책만 이 책, 저 책 사서 보기만 하고 어려워서 포기하고 쉽다는 다른 책 사보고 했던 게 생각이 났습니다. '百聞이 不如一打'라고 개발 공부에는 백 번 보는 것 보다, 한번 쳐보는 게 훨씬 빨리 이해할 수 있을 텐데, 이렇게 책만 붙잡고 있는다고 해서 디자인 패턴에 대해서 얼마나 알 수 있겠나 싶었습니다. 그리고 이 책에 나오는 디자인 패턴을 모조리 다 외운다고 해서 실제 개발에 얼마나 써먹을 수 있을지에 대해서도 의문이 들었습니다. 그래서 그 때 부터는, 디자인 패턴에 대해서 간략하게만 설명해두고, 어떨 때 사용할 수 있는지, 어떨 때 적용하면 좋은지에 대해서만 정리 했습니다. 그러면 나중에 특정 디자인 패턴이 필요한 상황에서 적절한 디자인 패턴을 찾아서 적용시키기 좋을 것이고, 한번씩 정리하면서 어떤 디자인 패턴들이 있는지에 대해서도 숙지할 수 있을 것 같았습니다.

 그렇게 책을 한번 읽고, 정리하면서 어떤 디자인 패턴들이 있는지, 어떤 상황에서 사용해야 하는지, 어떤 방식으로 문제를 해결하는지에 대해서 알 수 있었습니다. 그리고 이번에 학습을 하면서 'Effective Java' 역시 함께 참고하였는데, 이 책에도 디자인 패턴에 관련된 내용들이 많이 나와서 좀 더 고급스러운 패턴 사용법들을 볼 수 있었습니다. 특히 실제로 자주 사용되는 디자인 패턴 중 하나인 Singleton 패턴을 구현 할 때, 자바 1.5 이상의 경우 Enum 타입으로 구현을 하면, 복잡한 직렬화나 리플렉션 상황에서도 직렬화가 자동으로 지원되며, 인스턴스가 여러 개 생기지 않도록 확실히 보장해 주기 때문에 가장 권장 하는 구현 방법이라는 것을 보고, 실제로 과제용 프로그램을 작성할 때 적용시켜 보기도 했습니다. (아래 정리에 예제 코드 포함)

 이번 디자인 패턴을 학습하면서, 여태까지 무심코 사용하고 있었던 코딩 기법들이 알고 보니 디자인 패턴들이었던 것 도 알 수 있었고,(기존 코딩 기법에 패턴이란 이름을 붙인 걸 수도 있겠네요) 디자인 패턴이란 것이 그렇게 특별한 것이 아닌 것 같다는 생각을 했습니다.
 디자인 패턴은 객체 지향 개념과 아주 밀접한 관계를 가지고 있는 것 같습니다. 저는 디자인 패턴이란 '객체 지향 개념(상속,재사용성,캡슐화,추상화 등등)을 어떻게 하면 더 깔끔하고 효율적으로 적용할 수 있을까? 에 중점을 두고 개발을 하기 위한 기법들을 정리한 것'이라고 생각합니다.

 아직은 개발 경력이 얼마 되지 않아서, 이런 디자인 패턴들을 언제 어떻게 적용해야 하는지, 또 적용 할 수 있을 지는 잘 모르겠지만, 이번에 디자인 패턴에 대해 알아 보면서, 객체 지향 개념에 대해서 좀 더 자세히 알 수 있게 된 것 같습니다.

 다음은 책 보면서 간단히 정리한 내용들인데, 각 패턴에 대해서 간략히 훑어보기에는 좋은 것 같습니다. 마지막에 디자인 패턴 Q&A 파트 중, 다음 내용을 처음부터 알았다면, 책을 처음부터 찬찬히 읽는 수고는 덜었을지도 모르겠네요…ㅠ

디자인 패턴은 모두 외울 필요가 없다
- 기계적으로 디자인 패턴을 외우는 것은 의미가 없다. 디자인 패턴이 문제를 어떻게 해결하고 있는지 이해하는 것이 중요하다.

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

시작하기전에
- 디자인 패턴은 클래스 라이브러리가 아니다
○ 클래스 라이브러리 안에서 디자인 패턴이 사용되고 있다
- 프로그램을 완성품으로 보지 않는다
○ 디자인 패턴의 목표는 재사용성
○ 어떤 기능이 확장될 가능성이 있는가?
○ 확장기능을 수행할 때 수정이 필요한 클래스는 무엇인가?
○ 수정이 불필요한 클래스는 무엇인가?
- 다이어그램은 보는 것이 아니라 읽는 것이다
Iterator 패턴 - 순서대로 지정해서 처리하기
Iterator(반복자) 패턴 : 무엇인가 많이 모여있는 것들을 순서대로 지정하면서 전체를 검색하는 처리를 실행하기 위한 것.
hasNext와 next를 이용해서 요소들을 탐색한다.
Iterator를 사용하는 이유 : 구현과 분리해서 하나씩 셀 수 있다.
Next는 틀리기 쉽다 : next의 정확한 의미는 returnCurrentElementAndAdvanceToNextPosition
hasNext도 틀리기 쉽다 : 최후의 요소를 얻은 뒤에false를 반환한다. 즉 "다음next를 불러도 괜찮은지 조사하는" 메소드.
Adapter 패턴 - 바꿔서 재이용하기
Adapter 패턴 : 이미 제공되어 있는 것과 필요한 것의 차이를 없에주는 디자인 패턴. (Wrapper 패턴)
a. 상속을 사용한 Adapter 패턴 : 인터페이스 + 클래스의 다중 상속
b. 위임을 사용한 Adapter 패턴 : 클래스 + 클래스의 경우 ->위임(Composition을 사용)
Adapter를 사용하는 이유 : 항상 처음부터 프로그래밍을 하는 것이 아니기 때문에, 구현하려는 기능이 이미 존재하고 검증 받았다면, 그것을 이용하는 편이 좋고, 그러기 위해서 Adapter 패턴을 이용하는 것이다.

Template Method - 하위 클래스에서 구체적으로 처리하기
Template Method 패턴 : 상위 클래스에서 추상메소드를 통해 뼈대를 결정하고, 하위 클래스에서 그 구체적인 내용을 결정하는 패턴. Java에서 Interface를 상속받아 구현하는 것과 같다.
Factory Method 패턴 - 하위 클래스에서 인스턴스 작성하기
Factory Method 패턴 : 인스턴스를 만드는 방법을 상위 클래스에서 결정하지만, 구체적인 클래스 이름 까지는 결정하지 않는 것. 인스턴스의 골격과 생성을 분리할 수 있다. Template Method 의 전형적인 응용.
Static Factory Method 패턴 : 생성자 대신 고유의 이름을 가지는 static method를 이용해 인스턴스를 생성하면, 생성자를 사용 할 때보다 다양한 이득이 있다.
Singleton - 인스턴스를 한 개만 만들기
Singleton 패턴 : 클래스의 인스턴스가 단 하나만 필요할 때, 인스턴스가 한 개 밖에 존재하지 않는 것을 보증하는 패턴.
Singleton 패턴의 구현 방법
a. INSTANCE를 public final 필드로 선언한다.
b. static factory method를 이용해서 Instance를 참조하도록 한다.(전형적인 getInstance() 메소드를 이용한 구현)
c. Enum 싱글톤 : 하나의 요소만 가지는 열거형(Enum)으로 선언.
public enum Elvis {
INSTANCE;
public void leaveTheBuilding(){…}
}

Prototype - 복사해서 인스턴스 만들기
Prototype 패턴 : 인스턴스를 new로 생성하지 않고 복사해서 새로운 인스턴스를 만드는 패턴. clone 메소드를 이용하여 새로운 인스턴스들을 생성한다. Clonable이 구현 된 클래스에만 적용가능.
Prototype 패턴을 사용하는 경우
a. 종류가 너무 많아서 정리할 수 없는 경우
b. 클래스로부터 인스턴스 생성이 어려운 경우
c. framework와 생성하는 인스턴스를 분리하고 싶은 경우
Builder - 복잡한 인스턴스 조립하기
Builder 패턴 : 전체를 구성하고 있는 각 부분을 만들고 단계를 밟아 만들어 나가는 패턴. 메소드 하나 하나가 메소드 전체를 완성시킨다.
Abstract Factory - 관련 부품을 조합해서 제품 만들기
Abstract Factory 패턴 : Factory Method 패턴과 비슷하지만 Abstract Factory 패턴은 객체 생성과정을 Interface화 시키고, Factory Method 패턴은 객체 생성 자체를 다른 메소드에 넘긴다.
Bridge - 기능 계층과 구현 계층 분리하기
Bridge 패턴 : 기능의 클래스 계층과 구현의 클래스 계층 사이에 다리를 놓는 것.
기능의 클래스 계층 : 새로운 기능을 추가하고 싶을 경우, 클래스 계층 안에서 자신의 목적과 가까운 클래스를 찾아내 그 하위 클래스를 만들어, 목적한 기능을 추가한 새로운 클래스를 만든다는 것.
구현의 클래스 계층 : 새로운 구현을 위해 추상 클래스의 하위 클래스를 만들어 추상 메소드를 구현하는 것.
사용하는 이유 : 구현과 기능의 클래스 계층을 분리하여 각각 계층을 독립적으로 확장할 수 있고, 새로 기능을 추가하더라도 모든 구현에서 사용할 수 있게 된다.
Strategy - 알고리즘을 모두 바꾸기
Strategy 패턴 : 알고리즘을 독립적으로 구현시켜 필요한 알고리즘을 필요할 때 삽입하는 패턴. 위임이라는 느슨한 연결을 사용하여 알고리즘을 손쉽게 교체할 수 있다.
필요할 때 :  알고리즘 교체를 쉽게 하고 싶을 때. (특히 동적으로)
Composite - 그릇과 내용물을 동일시하기
Composite 패턴 : 그릇과 내용물을 동일시해서 재귀적인 구조를 만들기 위한 디자인 패턴.
필요할 때 : 재귀적인 구조가 필요할 때. 트리 구조로 된 데이터 구조는 Composite 패턴에 해당한다. 
Decorator - 장식과 내용물을 동일시하기
Decorator 패턴 : 오브젝트에 기능을 추가해 나가는 디자인 패턴.
필요할 때
○ 내용물을 변경하지 않고 기능을 추가하고 싶을 때.
○ 동적인 기능을 추가하고 싶을 때.
Visitor - 데이터 구조를 돌아다니면서 처리하기
Visitor 패턴 : 데이터 구조와 처리를 분리 하는 패턴.
필요할 때 : 처리를 데이터 구조에서 분리해야 할 때.
Chain of Responsibility - 책임 떠넘기기
Chain of Responsibility 패턴 : 복수의 오브젝트를 사슬처럼 연결해 두면, 그 오브젝트의 사실을 차례로 돌아다니면서 목적한 오브젝트를 결정하는 패턴. 요구를 
필요할 때 : Client와 ConcreteHandler 을 유연하게 연결하는 것.
Facade - 단순한 창구
Facade 패턴 : 단순한 창구 역할을 하는 패턴. 클래스를 개별적으로 제어하지 않아도, 창구에 요구만 하면 역할이 끝난다.
필요할 때 : 내부에서 실행되고 있는 많은 클래스의 관계나 사용법이 복잡한 것들을 단순하게 보여줘야 할 때. 인터페이스(API)를 적게 하는 것이 핵심이다. 클래스나 메소드가 많으면 무엇을 사용해야 할 지 고르기가 어렵고, 틀리기도 쉽다. 이런 인터페이스들을 적게 해 주는 것이 Facade패턴.
Mediator - 중개인을 통해서 처리하기
Mediator 패턴 : 조정자, 중개자라는 의미로, 다수의 오브젝트 사이를 조정해야 할 경우 사용한다. 각각의 오브젝트들이 상호간에 통신을 하는 것이 아니라, 중개인을 통해서만 통신을 하는 패턴.
필요할 때 : 각 클래스에서 분산 시킬 것은 부산 시키고, 집중시킬 것은 집중시켜야 할 때, 중개자 패턴을 통해서 집중시킨다.
Observer - 상태의 변화를 알려주기
Observer 패턴 : 오브젝트의 활동을 관찰자가 기록하는 패턴. Observer는 Subject를 관찰하게 된다. MVC Model-View 관계는 Subject-Observer 관계에 대응한다.
실제로는 Observer가 관찰 한다기 보다는, Subject가 상태를 전달하는 것을 기다리고 있는 구조.
필요할 때 : 상태 변화에 따른 처리를 기술 할 때. 
Memento - 상태를 저장하기
Memento 패턴 : 어떤 시점의 인스턴스의 상태를 확실하게 기록해서 저장해 두고, 나중에 인스턴스를 그 시점의 상태로 되돌릴 수 있는 패턴. undo, redo, history, snapshot 등의 기능을 실행할 수 있다.
필요할 때 : 변해버린 인스턴스의 상태를 원래대로 돌려야 할 때, 캡슐화의 파괴에 빠지지 않고 저장과 복원을 실행해야 할 때.
State - 상태를 클래스로 표현하기
State 패턴 : 사물이나 모양이나 형편(상태)을 클래스로 표현하는 패턴.
필요할 때 : 사물의 상태의 변화를 표현하고 추가해야 될 때.
Flyweight - 동일한 것을 공유해서 낭비 없에기
Flyweight 패턴 : 인스턴스를 가능한 대로 공유시켜서, 쓸데없이 new 하지 않도록 하는 패턴. 인스턴스를 필요할 때마다 new 하는 것이 아니라, 이미 만들어져 있는 인스턴스를 사용할 수 있으면 그것을 공유해서 사용한다.
필요할 때 : 객체를 가볍게 해야 할 때. (메모리 사용량을 줄여야 할 때.)
Proxy - 필요해지면 만들기
Proxy 패턴 : 대리인이라는 의미로, 대리역할을 하는 클래스가 실제 클래스의 역할을 대신 하다가, 실제 클래스의 기능이 필요할 때가 되면 그때 실제 클래스의 인스턴스를 생성하는 패턴.
필요할 때 : 시간이 오래 걸리는 작업을 해야할 때. 초기화에 시간이 걸리는 기능이 많이 존재한 대규모 시스템의 경우, 기동 시점에 이용하지 않는 기능까지 모두 초기화 하면 느려지므로, Proxy 패턴을 이용하여 사용할 때 초기화 하도록 한다.
Command - 명령을 클래스로하기
Command 패턴 : 명령을 클래스로 표현하는 패턴. 명령을 나타내는 클래스의 인스턴스를 하나의 '물건'처럼 표현할 수 있다. 명령의 집합을 저장해 두면 같은 명령을 재실행 하거나, 복수의 명령을 모아서 새로운 명령으로 재이용할 수도 있다.
Interpreter - 문법규칙을 클래스로 표현하기
Interpreter 패턴 : 프로그램이 해결하려는 문제를 간단한 '미니 언어'로 표현하는 패턴. 구체적인 문제를 미니 언어로 기술된 '미니 프로그램'으로 표현한다. 그리고 그 미니 프로그램을 통역하는 프로그램을 만들고, 미니 프로그램을 실행할 수 있도록 한다.
디자인 패턴 Q&A
디자인 패턴이란?
○ 소프트웨어 설계시에 반복해서 발생하는 문제에 대한 해법.
적절한 디자인 패턴의 선택
○ 자신이 설계하고 있는 소프트웨어가 어떤 '문제'를 포함하고 있는지 알아야 한다.
디자인 패턴은 모두 외울 필요가 없
○ 기계적으로 디자인 패턴을 외우는 것은 의미가 없다. 디자인 패턴이 문제를 어떻게 해결하고 있는지 이해하는 것이 중요하다.
디자인 패턴과 알고리즘
○ 디자인 패턴과 알고리즘은 다르지만 밀접한 관계가 있다. 알고리즘을 문제해결의 수법으로 기술해서 패턴으로 표현할 수 있지만, 알고리즘=디자인 패턴은 아니다. 디자인 패턴은 알고리즘 이외에도 이디엄(코딩 시 자주 사용되는 관용구)과도 관계가 있다. 디자인 패턴은 구체적인 구현이라기 보다는, 구체적인 구현을 실현하기 위한 사고방식, 해법이라고 할 수 있다.

 

반응형
반응형

http://xper.org/LineReaderTdd/






LineReader TDD 동영상


LineReader를 테스트 주도 개발(TDD)로 만들어 나가는 과정으로, 김창준과 강규영이 직접 제작했습니다. 전체 상영 시간은 약 1시간 20분 가량 됩니다. 시청을 하실 때에는 윈도우즈 미디어 플레이어를 사용하시고, 되도록이면 전체화면 모드로 보세요. 

-- 김창준, 강규영 (2003년 7월)


동영상의 저작권은 김창준과 강규영에게 있으며, 허락없이는 재배포할 수 없습니다.

반응형
반응형





http://www.javajigi.net/display/OSS/TDD



TDD

Toggle Space Navigation Tree
Space Map

TDD와 JUnit을 이용한 테스팅 방법을 알아보고 효율적인 테스팅 방법에 대해 토의해봅시다.

오픈 소스 스터디

Table of Contents

Introduction

  • 개발자의 테스트 활동이 중요한 이유
    • 초기 단계에서 발견된 결함은 수정이 용이하다.
    • 개발 후기 단계에서 발견된 결함들을 수정하기에는 비용과 시간이 많이 소비되고,
      프로젝트가 실패될 확률이 높아진다.
    • 개발 단계에서의 효율적인 테스팅은 전체 프로젝트 시간을 감소시킨다.
  • 테스트의 종류
    • 단위테스트 : JUnit
      단위테스트는 단위 코드에서 문제 발생 소지가 있는 모든 부분을 테스트 하는 작업이다. 
      보통 클래스의 public method 를 테스트 한다. 
      좋은 단위 테스트란 모든 메서드를 테스트 하는 것이 아니라, 
      상식 수준의 확인을 통해 단위 코드가 의도한 대로 동작하는지 여부를 판단하는 단계이다. 
      이상적으로는 코딩전에 테스트 케이스를 작성하여 구현시 보조자료로 활용하는 것이 좋다. ( TDD의 기법 ) 
      단위테스트 후에 개발팀은 테스트를 프로젝트 테스트 스위트에 추가하여 매일 여러번 수행하고 모든 테스트를 항상 통과하게 해야 한다. 
      기회가 된다면 Code Coverage 를 하는 것이 좋은데 오픈소스로는 JCoverage 등이 있다.
    • 통합/컨테이너 내부 테스트 : Cactus
      좋은 단위 테스트는 시스템내의 복잡한 부분에 관계없이 클래스 내의 함수들을 검사하는 것이다. 
      단위 테스트는 가능한 의존성 없이 독립적으로 처리되어야 한다. 
      Mock Object 로 테스트를 하는 경우도 있지만, 
      Cactus 는 J2EE 컨테이너에 접근하는 방법을 제공한다. 
      컨테이너 안에서 코드 테스트가 가능하도록 하기 위해서 Cactus 는 상세하거나 또는 까다로운 
      실제와 같은 모형을(mock-ups) 개발자에게 제공한다. 
      이 방법은 실행되는 코드가 제품이 출시되는 환경에서 실행되기 때문에 또 다른 피드백 기준을 제공한다. 
      컨테이너 서비스와 상호 작용하는 단일 오브젝트 경우에 컨테이너 내부 테스트를 사용하여 간편한 단위 테스트를 할 수 있다.
    • 수락/기능 테스트 : HttpUnit
      기능 테스트는 전체 시스템이 의도한 바대로 동작하는 지를 검사하는 과정이다. 
      이 방법은 완성된 시스템을 고객으로부터 검사받는 방법이므로 수락 테스트라고도 한다. 
      기능 테스트는 구조적 기능에 대하여 어떤 프로그램의 기능에 대한 시험이며 진척 상태를 확인하고 
      이전의 테스트나 누락된 결점을 잡아내거나 미완성 또는 불완전한 부분에서 발생된 문제를 찾아내는 것이 중요하다. 
      수락 테스트는 고객에 의해 작성된다. 
      기능 테스트는 항상 100% 구현될 필요는 없으나 제품 출시 전에는 100% 수행 되어야 할것이다. 
      기능 테스는 종종 매우 구체적인 내용들을 테스트 하기도 한다. 
      아직은 통괄적인 수락 테스팅 툴은 나오지 않았고 Junit은 어떤 자바클래스에서도 수행될 수 있으나 
      수락 테스팅 도구는 특정 애플리케이션 요구에 따라 작성되어야 한다. 
      HttpUnit을 이용하면 테스팅 API를 이용하여 웹 리소스에 대한 호출과 응답 값 조회를 프로그래밍 할 수 있도록 한다.

TDD

자동화된 테스트로 개발을 이끌어 가는 개발 방식을 테스트 주도 개발이라 부른다. 
TDD는 분석 기술이며, 설계 기술이며, 개발의 모든 활동을 구조화하는 기술이다. 
작동하는 깔끔한 코드(clean code that works). 
이 핵심을 찌르는 한마디가 바로 테스트 주도 개발의 궁극적인 목표다.

테스트 주도 개발에서는 두 가지 단순한 규칙만을 따른다.

  • 오직 자동화된 테스트가 실패할 경우에만 새로운 코드를 작성한다.
  • 중복을 제거한다.

또한 위의 두 가지 규칙에 의해 프로그래밍 순서가 다음과 같이 결정 된다.

  • 빨강- 실패하는 작은 테스트를 작성한다. 처음에는 컴파일조차 되지 않을 수 있다.
  • 초록- 빨리 테스트가 통과하게끔 만든다. 이를 위해 어떤 죄악을 저질러도 좋다.
    (죄악이란 기존 코드 복사해서 붙이기-copy and paste, 테스트만 간신히 통과할 수 있게끔 
    함수가 무조건 특정상수를 반환하도록 구현하기 등을 의미한다.)
  • 리팩토링- 일단 테스트를 통과하게만 하는 와중에 생겨난 모든 중복들을 제거한다

TDD 따라해보기

  • MyProject 라는 프로젝트를 만들었다. 메뉴> New> Project
  • TestCase를 생성한다. 이클립스에서는 TestCase와 TestSuite의 기본 템플릿을 제공하고 있다.
    메뉴> New> Other을 누르면 다음과 같은 창이 뜬다.

  • 생성할 TestCase 파일 이름 및 테스트 대상 클래스를 입력한다. (①)
    만약 setup() 메소드나 teardown() 메소드를 사용할 때는 해당 체크박스를 선택한다. (②)

  • 다음이 생성되었다.

  • 할일 목록을 작성해보자. 작업을 끝낸 항목에는 표시를 하고,
    또 다른 테스트가 생각나면 할일 목록에 새로운 항목을 추가할 것이다.

  • 자, 그럼 구현을 하기 위해 어떤 객체가 있어야 할까?
    방금 이건 속임수다. 객체를 만들면서 시작하는 게 아니라 테스트를 먼저 만들어야 한다. 
    앞에서 언급한 TDD의 주기중 현재 단계는 빨강이다.
  • 그렇다면 어떤 테스트가 필요할까? 할일 목록을 보니 첫번째 테스트는 좀 복잡해보인다.
    작은 것부터 시작하든지, 아니면 손을 대지 않는 게 좋겠다. 이번엔 다음 항목인 곱하기를 보자. 
    대단히 어렵진 않겠지? 이걸 먼저 하는게 좋겠다.
  • testMultiplication이라는 테스트를 추가해보자.

  • 다음 코드를 돌리면 당연히 에러가 난다. 메뉴> Run As> JUnit Test

  • 할일 목록에 3가지를 추가한다.

  • 빨간 막대기를 가능하면 빨리 초록 막대기로 바꾸고 싶다.
    실행은 안 되더라도 컴파일만은 되게 만들고 싶은데, 가장 쉬운 방법이 뭘까? 
    이번 단계는 TDD주기에서 빨강에서 초록으로 넘어가는 과정이다.
  • 현재 네 개의 컴파일 에러가 있다.
    • Dollar 클래스가 없음
    • 생성자가 없음
    • times(int) 메서드가 없음
    • amount 필드가 없음
  • 네개의 컴파일 에러를 없앨 수 있는 가장 빠른 방법은 다음을 테스트 코드 아래 추가하는 것이다.


  • 당장의 목표는 완벽한 해법을 구하는 것이 아니라 테스트를 통과하는 것일 뿐이므로 최소한의 작업을 수행한다.

  • 테스트를 다시 실행해보자.

  • 드디어 초록색 막대가 나타났다. 하지만 아직 주기가 완성되지 않았으니까 서둘지 않는게 좋겠다.
    우리는 TDD의 주기중 빨강/초록을 넘었다.
  • 다음 단계는 리팩토링이다.코드를 다음과 같이 바꿔준다.

  • 테스트는 통과하고 테스트 막대 역시 초록색이다. 우리는 여전히 행복하다.

  • 이 단계가 너무 작게 느껴지는가? 하지만 기억하기 바란다. TDD의 핵심은 이런 작은 단계를
    밟아야 한다는 것이 아니라, 이런 작은 단계를 밟을 수 있는 능력을 갖추어야 한다는 것이다.
  • 5를 어디서 얻을 수 있을까? 이건 생성자에서 넘어오는 값이니 이걸 다음과 같이 amount 변수에 저장하면,

  • 그걸 time()에서 사용할 수 있다.
    인자 multiplier의 값이 2이므로, 상수를 이 인자로 대체할 수 있다.

  • 마지막으로 우리가 자바 문법을 완벽하게 알고 있다는 것을 보여주기 위해 *=연산자를 써주자.( 물론 중복을 제거하기 위해서다. )

  • 이제 첫 번째 테스트에 완료표시를 할 수 있게 되었다.

  • 마무리 - 우리는 다음과 같은 작업들을 해냈다.
    • 우리가 알고 있는 작업해야 할 테스트 목록을 만들었다.
    • 오퍼레이션이 외부에서 어떻게 보이길 원하는지 말해주는 이야기를 코드로 표현했다.
    • JUnit에 대한 상세 사항들은 잠시 무시하기로 했다.
    • 스텁 구현을 통해 테스트를 컴파일했다.
    • 끔찍한 죄악을 범하여 테스트를 통과시켰다.
    • 돌아가는 코드에서 상수를 변수로 변경하여 점진적으로 일반화했다.
    • 새로운 할 일들을 한번에 처리하는 대신 할일 목록에 추가하고 넘어갔다.

TDD의 특징

  • 격리된 테스트
  • 테스트 목록
  • 테스트 우선
  • 단언 우선
  • 명백한 데이터

TDD와 관련된 의문

  • 단계가 얼마나 커야 하나?
  • 테스트 할 필요가 없는 것은 무엇인가?
  • 좋은 테스트를 갖췄는지의 여부를 어떻게 알 수 있는가?
  • TDD로 프레임워크를 만들려면 어떻게 해야하나?
  • 피드백이 얼마나 필요한가?
  • 테스트를 지워야 할 때는 언제인가?
  • 프로그래밍 언어나 환경이 TDD에 어떤 영향을 주는가?
  • 거대한 시스템을 개발할 때도 TDD를 할 수 있는가?
  • 애플리케이션 수준의 테스트로도 개발을 주도할 수 있는가?
  • 프로젝트 중반에 TDD를 도입하려면 어떻게 해야 할까?
  • TDD는 누구를 위한 것인가?
  • TDD는 초기 조건에 민감한가?
  • TDD와 패턴의 관계는?
  • 어째서 TDD가 잘 동작하는가?
  • TDD와 익스트림 프로그래밍의 실천법 사이에는 어떤 관련이 있는가?

JUnit

▪ 다운로드 : http://www.junit.org/

JUnit 기본 클래스

1. TestCase 클래스 : 가장 간단하게 Junit을 사용하는 방법은 TestCase 클래스를 상속받은 클래스를 작성하는 것이다. 이 클래스에는 test로 시작하는 메소드만 나열하면 된다.

2. TestSuite 클래스 : testCase 클래스를 상속받은 클래스만을 사용하다 보면, 일부의 test 메소드는 간혹 실행하지 않고 싶거나 특정한 test 메소드만 실행하고 싶을 때가 생긴다. (①) 또는 Test 클래스를 한데 묶어서 한꺼번에 실행하고 싶은 경우(②)도 발생한다. 이때 사용하는 것이 바로 TestSuite이다.

3. Assersions

4. Fixture : 초기 값 설정 및 해제 - setUp(), teardown()


JUnit4.0에서의 변경사항

  • Test Annotation
    이전 버전에서 사용했던 TestCase를 대신에 org.junit.Test를 임포트하여 다음과 같은 형식으로 사용한다.
    • @Test public void functionName() { }
  • Expected Exception
    @Test Annotation은 "expected" 라는 파라메터를 option 으로 가지고 있는데
    이것은 Throwable의 서브 클래스들을 값으로 취한다.
    • @Test(expected= IndexOutOfBoundsException.class) public void empty() {
      new ArrayList<Object>().get(0); 
      }
  • Timeout
    @Test Annotation은 long형 파라메터를 통해 timeout을 설정할 수 있다.
    • @Test(timeout=100) public void infinity()
      Unknown macro: { for ( ; ; ); }
  • Fixture
    • setup - Before Annotation
      • import org.junit.Before;
        @Before public void functionName()
    • tearDown - After Annotation
      • import org.junit.After
        @After public void functionName()
  • Ignore Annotation
    때때로 일시적으로 테스트를 작동시키지 않을 때가 있는데 Ignore이라는 Annotation을 사용할 수 있다. 
    Ignore하는 이유를 옵션 파라메터를 통해 기록할 수 있다.
    • @Ignore("not ready yet") @Test public void something()

단위 테스트 지침 요약

일반 원칙

  • 망가질 가능성이 있는 모든 것을 테스트한다.
  • 망가지는 모든 것을 테스트한다.
  • 새 코드는 무죄가 증명되기 전까지는 유죄.
  • 적어도 제품 코드만큼 테스트 코드를 작성한다.
  • 컴파일 할 때마다 지역 테스트를 실행한다.
  • 저장소에 체크인하기 전에 모든 테스트를 실행해 본다.

자문해 봐야 할 사항

  • 이 코드가 옳게 동작한다면 어떻게 그것을 알 수 있는가?
  • 이것을 어떻게 테스트할 것인가?
  • ''''' 어떤 것이 잘못될 수가 있는가?
  • 이와 똑같은 종류의 문제가 다른 곳에서도 일어날 수 있을까?

좋은 테스트란?

좋은 테스트는 'A- TRIP' 해야 한다.

  • 자동적('A'utomatic)
    • 테스트가 혼자 실행되고 자신을 검증할 수 있어야 한다.
  • 철저함('T'horough)
  • 반복 가능('R'epeatable)
    • 모든 테스트가 어떤 순서로든 여러 번 실행될 수 있어야 하고, 그때마다 늘 같은 결과를 내야 한다.
  • 독립적('I'ndependent)
    • 확실히 한 대상에 집중한 상태여야 한다.
    • 환경과 다른 개발자들에게서 독립적인 상태를 유지해야 한다.
    • 어느 테스트도 다른 테스트에 의존하지 않는다.
  • 전문적('P'rofessional)
    • 좋은 설계를 위한 모든 일반적인 규칙, 캡슐화 유지, DRY 원칙 지키기, 결합도 낮추기 등은 제품 코드에서 그랬듯이 테스트 코드에서도 반드시 지켜져야 한다,

무엇을 테스트 할 것인가?

Right-BICEP (오른쪽 이두박근이라는 뜻)

  • Right - 결과가 옳은가?
    예) 
  • B - 모든 경계('B'oundary) 조건이 correct 한가?
    <경계 조건에서 확인해봐야 할 사항들 - 'CORRECT'>
    • 형식 일치('C'onformance) - 값이 기대한 형식과 일치 하는가?
      예) 최상위 도메인 이름이 없는 이메일 주소 fred@foobar 이 넘어온다면?)
    • 순서('O'rdering) - 적절히 순서대로 되어 있거나 그렇지 않은 값인가?
      예)
    • 범위('R'ange) - 적당한 최소값과 최대값 사이에 있는 값인가?
      예) 
    • 참조('R'eference) - 코드가 자기가 직접 제어하지 않는 외부 코드를 참조하는가?
      예) 
    • 존재성('E'xistance) - 값이 존재 하는가?
      예) null이 아님, 0이 아님, 집합 안에 존재함)
    • 개체 수('C'ardinality) - 확실히 충분한 값이 존재하는가? 개수를 정확히 필요한 만큼 갖고 있다던가, 정확히 필요한 만큼 만들었다는 것을 확인해야 한다.
      예) 울타리 기둥 에러, 하나 차이에 의한 오류
    • 시간 ('T'ime) (절대적으로 그리고 상대적으로) - 모든 것이 순서대로 일어나는가? 제시간에? 때 맞추어?
      예) 로그인하기 전에 문서를 출력하려고 시도하는 것
  • I - 역('I'nverse) 관계를 확인할 수 있는가?
    예) 
  • C - 다른 수단을 사용해서 결과를 교차 확인('c'ross-check) 할 수 있는가?
    예) 
  • E - 에러조건('e'rror condition)을 강제로 만들어 낼 수 있는가?
    현실 세계에서는 에러가 발생한다. 여러분은 강제로 에러를 일으켜 코드가 현실 세계의 문제를 제대로 처리한다는 것을 테스트 할 수 있어야 한다. 
    네트워크 에러 등을 시뮬레이션 하는 경우 모의객체(mock object)를 사용할 수 있다.
  • P - 성능('P'erformance) 특성이 한계 내에 있는가?
    예) 

프로젝트에서 테스트하기

1. 테스트 코드를 어디에 둘 것인가?

  • 같은 디렉터리
    • 장점: TestAccont가 Account의 보호된 멤버 변수와 메서드에 접근할 수 있다.
    • 단점: 테스트 코드가 제품 코드 디렉터리의 공간을 잡아먹으면서 어질러져 있다.
  • 하위 디렉터리
    • 장점: 태스트 코드를 적어도 제품 코드와 똑 같은 디렉토리에 있지 않게 떨어뜨려 놓을 수 있다.
    • 단점: 테스트 코드가 다른 패키지에 있으므로 필요한 멤버들을 노출시키는 제품 코드의 하위 클래스를 사용하지 않는다면 테스트 코드는 보호된 멤버에 접근할 수 없다.
  • 병렬 트리
    • 장점: 테스트 코드와 제품 코드가 정말로 분리되었다. 테스트 코드가 같은 패키지에 있기 때문에 선택적으로 접근할 수 있다.
    • 단점: 편하게 쓰기에는 너무 멀리 떨어져버린 건지도 모른다.

2. 테스트 예절

  • 혼자하는 테스트와 다른 사람과 함께하는 테스트의 가장 큰 차이점은? 테스트 코드의 동기화
  • 팀 환경에서 코드를 체크인 할 때는, 그 코드가 단위 테스트를 완료하였고,모든 단위 테스트가 통과했다는 것을 확인해야한다.
    사실상, 전체 시스템의 코든 테스트가 새로운 코드에 대해 계속 통과해야 한다.
  • 잠재적 위반사항 목록을 만들자
    • 불완전한 코드(예: 클래스 파일 하나만 체크인 하고 그것이 의존할 수 있는 다른 파일은 체크인 하는 것을 잊어버린 경우)
    • 컴파일 되지 않는 코드
    • 컴파일 되기는 하지만, 다른 코드를 망가뜨려서 컴파일 되지 않게 만드는 코드
    • 대응하는 단위 테스트가 없는 경우
    • 단위테스트가 실패하는 코드
    • 자신의 테스트는 통과하지만, 시스템의 다른 테스트를 실패하게 만드는 코드

3. 테스트 빈도

  • 새 메서드를 작성할 때마다 지역 단위 테스트들을 컴파일하고 실행한다.
  • 버그를 고칠 때마다 버그를 드러내는 테스트를 시행한다.
  • 성공적으로 컴파일 할 때마다 지역 단위 테스트들을 실행한다.
  • 버전 관리 시스템에 체크인할 때마다 모든 모듈 또는 시스템의 단위 테스트들을 실행한다.
  • 따로 배정된 특정 컴퓨터가 자동으로 하루 종일(주기적으로, 또는 버전 관리 시스템에 체크인 할 때마다),
    처음부터 전체 빌드와 테스트를 수행하고 있어야 한다.

4. 테스트와 레거시 코드

  • 이미 있던 코드의 경우 : 가장 망가진 부분을 위한 테스트를 가장 먼저 추가하는 편이 좋다.
    이런 환경에서 실시하는 단위 테스트는 뒷걸음 질을 막는다. 
    즉, 유지 보수하기 위해 수정하고 개선하다가 이미 있는 부분들에 버그를 만들어 내는 죽음의 나선을 피할 수 있다.
  • 연속적 빌드-테스트 프로그램을 사용하여 코드가 저장소에 전송될 때마다
    자동으로 단위테스트가 실행되게 만든다면 불량코드가 전체 회사에 돌아다니는 일을 방지할 수 있다.

5. 테스트와 검토

  • 코드 검토를 수행할 때, 그 검토과정의 필수 구성요소로 테스트 코드를 끼워넣어라
  • 코딩과 검토를 다음 순서로 하면 좋다
  • 테스트 케이스나 테스트 코드, 둘 다를 작성한다.
    1. 테스트 케이스나 테스트 코드, 또는 둘 다를 검토한다.
    2. 테스트 테이스나 테스트 코드, 또는 둘 다를 검토할 때마다 수정한다.
    3. 테스트를 통과하는 제품 코드를 작성한다.
    4. 제품코드와 테스트 코드를 검토한다.
    5. 검토할 때마다 테스트 코드와 제품코드를 수정한다.
    6. 모든 팀원을 이 과정에 참여시킴으로써 팀의 의사소통을 증진시킬 수 있다.
      다른 이들이 어떻게 테스트 하는지, 팀의 규칙이 무엇인지 알게된다.

설계와 관련된 문제들

1. 테스트의 용이성을 높이는 설계

2. 테스트를 위한 리팩토링

3. 클래스의 불변성(invariant)을 테스트 하기

  • 구조적
    • 주문 정보 입력 시스템은 다음과 같은 불변성을 가질 수 있다.
      • 모든 개별 항목은 어떤 주문에 속해야 한다.
      • 모든 주문은 개별 항목 하나 이상을 가져야 한다.
    • 데이터 배열을 다룰 때 인덱스 노릇을 하는 멤버 변수는 다음과 같은 불변성을 가질 수 있다.
      • 인덱스는 >=0이어야 한다.
      • 인덱스는 < 배열 길이여야 한다.
  • 수학적
    • 은행 계좌의 입금 부분과 출금 부분을 계산하면 잔고와 맞아 떨어져야 한다.
    • 다른 단위로 측정된 양은 변환 후에 맞아떨어져야 한다.
  • 데이터의 정합성(consistency)
    • 쇼핑 카트에 들은 항목 목록, 전체 판매액, 그 쇼핑 카트에 들은 전체 항목 개수는 밀접한 관련이 있다.
      항목 목록의 구체적인 내용을 알면, 다른 두 수치를 이끌어 낼 수 있다. 이 수치들이 조화를 이루어 맞아 
      떨어진다는 사실은 불변성이 되어야 한다.

참고문헌

  • 이클립스 기반 프로젝트 필수 유틸리티 CVS,Ant,JUnit (민진우 & 이인선 공저, 한빛미디어)
  • 테스트 주도 개발 (켄트 벡 저, 김창준 & 강규영 역,인사이트)
  • 실용주의 프로그래머를 위한 단위 테스트 with JUnit (데이비스 토머스 & 앤드류헌트 공저, 이용원 & 김정민 역, 인싸이트)
  • 참고 싸이트 - TDD를 공부하고 싶다면?
    http://wiki.tdd.or.kr/wiki.py
    http://c2.com/cgi/wiki?TestDrivenDevelopment
    http://xper.org/wiki/xp/

문서에 대하여

최초작성자 : 오혜진
최초작성일 : 2006년 2월 19일
버전 : 1.0 ? ㅎㅎ 
문서이력 :

  • 2005년 2월 19일 오혜진 문서 최초 생성
  • 2005년 2월 20일 JUnit4.0에서의 변경사항 추가
  • 2005년 2월 21일 오픈소스스터디 1기 장회수님 자료 참고하여 보완, 테스트의 종류 추가
  • 2005년 2월 24일 프로젝트에서 테스트하기 항목 추가 및 문서 구조 수정

반응형
반응형

크리에이티브 커먼즈 라이선스
Creative Commons License
  Doxygen은 주어진 소스 코드를 분석하고 소스 코드에 있는 특정한 형식의 주석을 이용해서 소스 코드를 자동으로 문서화해주는 프로그램이다. 결과는 일련의 HTML 페이지들이구, LATEX나 PDF 문서들을 만들어낼 수도 있다.
 일단 Doxygen을 설치 하기 전에 아래와 같이 해당 문서에그래프 다이어그램도 만들기 위해서는 Graphviz의 Graph Visualization Software를 설치할 필요가 있다. 


이 사이트에 접을 하면 위와 같이 첫 화면에서 current stable release 부분에서 다운을 받을 수 있다.
 graphviz-2.26.3.msi 이라는 파일 이름으로 다운이 받아졌을 것이다. 다운 받고 아무 폴더에 깔아 주기만 하면 된다.

 Doxygen 설치 
이제 본격적으로 Doxygen을 설치해보자. 


위에서 보이듯이 Download 메뉴를 클릭하고 중간쯤에 다운 받을 수 있는 화면이 나온다 윈도우에서는 Doxygen Wizard로 문서화를 간편하게 할 수 있다. Wizard가 나오기 전에는 조금 사용하기 불편했던 모양이지만, 요즘에는 편의성이 많이 제공되고 있다. 
다운을 받았으면 원하는 폴더에 설치를 해주자. 본인은 \Tools\Doxygen 1.7.1 이라는 폴더에 설치를 했다. 

 Doxygen Wizard 
 설치를 끝마쳤다면, bin 폴더에 doxywizard.exe 파일을 실행 시켜 보자. 

아래는 실행 시킨 모습이다. 실행을 시켰으니 옵션들에 대해서 알아 보자. 우선 Wizard - Project 부분이다.
 - 1번 : 프로젝트 이름을 설정한다. 
 - 2번 : 소스 파일이 있는 디렉토리를 설정한다. 
 - 3번 : 문서화한 결과 html들을 넣을 Destination Directory를 설정한다. 

- 1번 : Include cross-refeenced source code in the output 옵션은 각 함수마다 사용한 함수 코드로 바로 Jump할 수 있는 링크를 생성해 준다. 즉, html 문서에서 링크를 타고 넘나 드는 것과 같은 효과를 나타낸다.
 - 2번 : Doxygen에서는 각 코드만의 고유 주석 스타일을 가지고 있는데, 이런 주석 스타일에 맞춰서 해당 언어에 맞는 것에 체크를 해주면 된다. 

 - 이곳은 자신이 출력하고자 하는 형식을 고르는 곳이다. 

 - Wizard의 마지막 부분인 Diagrams 부분은 다이어그램을 사용할 것인지 안할 것인지 설정하는 부분이다. GraphViz를 설치 했다면 이 다이어그램을 사용할 수 있다.

 - 이런 설정을 다 마쳤다면 Run Doxygen을 통해 문서화하고 결과물들을 뽑아 낼 수 있다.

 Doxygen 에서 한글은? 
 간혹 가다가 문서화 했을 시, 주석에 한글사용을 했다면 깨지는 경우가 있다. 아까 expert부분을 넘어 갔는데, 이 부분은 세세한 설정부분이 있어 까다롭지만, 다른 것은 몰라도 이 한글이 안깨지게 하는 법만 알면 된다. 아래 빨간색 네모친 부분만 바꿔주자.

 Doxygen, chm 파일 만들기 
 PDF와 같이 manual이나 그런곳에 자주 보이는 chm 형식으로 파일을 만들 수 있다. Wizard - Output 부분에 chm 부분을 체크 하면 된다. 허나 이 설정을 체크만 한다고 해서 다 끝나는 것은 아니다. MS HTML Help가 필요하기 때문이다. 만약 깔려 있다면 상관없지만, 안깔려 있다면 꼭 설치를 해주고 설정을 해줘야 한다. 

위의 다운로드 링크를 클릭해 다운받고, 어디에다가 설치 했는지 알아 두자 Doxygen Wizard의 설정도 바꿔줘야 하기 때문이다.

Expert - HTML 부분에서 중간쯤에 GENERATE_HTMLHELP 부분을 체크 한 후, HHC_LOCATION 부분에서 아까 설치한 HTML Help의 프로그램 경로를 지정해 준다.



http://www.stack.nl/~dimitri/doxygen/index.html


Doxygenlatest release v1.8.2 - last page update Sat Aug 11 2012
Doxygen Manual

Generate documentation from source code

Doxygen is a documentation system for C++, C, Java, Objective-C, Python, IDL (Corba and Microsoft flavors), Fortran, VHDL, PHP, C#, and to some extent D.

It can help you in three ways:

  1. It can generate an on-line documentation browser (in HTML) and/or an off-line reference manual (in $\mbox{\LaTeX}$) from a set of documented source files. There is also support for generating output in RTF (MS-Word), PostScript, hyperlinked PDF, compressed HTML, and Unix man pages. The documentation is extracted directly from the sources, which makes it much easier to keep the documentation consistent with the source code.
  2. You can configure doxygen to extract the code structure from undocumented source files. This is very useful to quickly find your way in large source distributions. You can also visualize the relations between the various elements by means of include dependency graphs, inheritance diagrams, and collaboration diagrams, which are all generated automatically.
  3. You can also use doxygen for creating normal documentation (as I did for this manual).

Doxygen is developed under Linux and Mac OS X, but is set-up to be highly portable. As a result, it runs on most other Unix flavors as well. Furthermore, executables for Windows are available.


Doxygen license

Copyright © 1997-2012 by Dimitri van Heesch.

Permission to use, copy, modify, and distribute this software and its documentation under the terms of the GNU General Public License is hereby granted. No representations are made about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. See the GNU General Public License for more details.

Documents produced by doxygen are derivative works derived from the input used in their production; they are not affected by this license.

User examples

Doxygen supports a number of output formats where HTML is the most popular one. I've gathered some nice examples of real-life projects using doxygen.

These are part of a larger list of projects that use doxygen. If you know other projects, let me know and I'll add them.

Commercial Support

I'm currently investigating the possibilities of providing commercial support for doxygen. The forms of support I'm thinking of are:

  • implementing features,
  • fixing bugs,
  • providing priority help in answering questions.

To get a better understanding of the feasibility, please let me know if you have a need for this type (or another type) of doxygen related commercial support.

Future work

Although doxygen is successfully used by large number of companies and open source projects already, there is always room for improvement.

You can submit enhancement requests in the bug tracker. Make sure the severity of the bug report is set to "enhancement".

Acknowledgements

Thanks go to:

  •  Malte Zöckler and Roland Wunderling, authors of DOC++. The first version of doxygen borrowed some code of an old version of DOC++. Although I have rewritten practically all code since then, DOC++ has still given me a good start in writing doxygen.
  • All people at Qt Software, for creating a beautiful GUI Toolkit (which is very useful as a Windows/Unix platform abstraction layer :-)
  • My brother Frank for rendering the logos.
  • Harm van der Heijden for adding HTML help support.
  • Wouter Slegers of Your Creative Solutions for registering the www.doxygen.org domain.
  • Parker Waechter for adding the RTF output generator.
  • Joerg Baumann, for adding conditional documentation blocks, PDF links, and the configuration generator.
  • Tim Mensch for adding the todo command.
  • Christian Hammond for redesigning the web-site.
  • Ken Wong for providing the HTML tree view code.
  • Talin for adding support for C# style comments with XML markup.
  • Petr Prikryl for coordinating the internationalization support. All language maintainers for providing translations into many languages.
  • The band Porcupine Tree for providing hours of great music to listen to while coding.
  • Andrea Schulte for translating part of the web page to German.
  • Jan Milz for mirroring the tar ball.
  • Techfacts.de for their long time contribution and support.
  • many, many others for suggestions, patches and bug reports.
Follow doxygen on Twitter Doxygen on freshmeat Doxygen on SourceForge 

This page was last modified on 11 August 2012. 
(c) 1997-2012 Dimitri van Heesch, first release 27 oct 1997.




독시전 사용법


초기 사용법


JAVADOC_AUTOBRIEF 옵션을 YES

Doxgen 에 대한 개인적인 생각, 굳이 안써도 된다는 의견

과거버전이긴 하지만 Doxgen syntax 에 관한 얘기가 있다.


doxgen 에 대한 여러가지 설명들

소스인사이트에 doxgen 주석 comment 추가

doxgen 주석에 관한 format template




출처 : http://acidlikk.tistory.com/entry/Doxygen에서-GraphVizdot로-Diagram-그리기



Doxygen에서 GraphViz(dot)로 Diagram 그리기

Posted 2007/11/28 14:59 by acidlikk
1. GraphViz(dot)을 설치한다. http://www.graphviz.org 에서 무료로 받을 수 있다.

2. Doxygen Wizard의 Diagrams 탭에서 Use dot tool from the GraphViz package to generate 선택. 그 밑의 체크박스는 취향에 따라...

3. Expert의 Dot 탭에서 설정을 해 준다.

먼저, DOT_PATH에 GraphViz의 dot이 깔린 bin 폴더의 절대 경로를 써준다. 예를 들어,

DOT_PATH: C:\Program Files\Graphviz2.16\bin

그리고 HAVE_DOT을 체크해준다. 나머지 체크박스도 취향에 따라...





반응형

'디자인패턴과방법론 > 개발방법론' 카테고리의 다른 글

LineReader TDD 동영상  (0) 2012.11.01
TDD 개발방법론  (0) 2012.11.01
단위테스트  (0) 2012.10.31
반응형





단위테스트란 무엇인가?

단위 테스트는 테스트 대상이 되는 코드 기능의 아죽은 특정 영역을 실행해 보는, 개발자가 작성한 코드 조각이다. 대개 단위 테스트는 특정 상황에서 특정 메서드를 시험해본다. 예를 들어, 어떤 정렬된 리스트에 큰 값을 넣고 이 값이 리스트 끝에 들어 있는지 확인해 볼 수 있다. 또 어떤 문자열에서 문자 패턴을 하나 지우고 그것이 없어졌는지 확인할 수도 있다.
 단위 테스트는 어떤 코드 조각이 개발자가 생각한 대로 동작하는지 증명하기 위해 수행하는 것이다.
 그 동작이 고객이나 최종 사용자가 바라는 것인지 아닌지는 해결되지 않은 채로 남는다. 이 부분은 인수 테스트의 목표다. 우리는 아직은 공식적인 유효성 검증과 확인이나 정확성에 크게 신경 쓰지 않는다. 이 시점에서는 성능 테스트에 조차 관심을 두지 않는다. 우리가 할 일은 단지 코드가 의도대로 동작하는지 확인하는 것이고, 따라서 코드의 기능 중에 아주 작고 고립된 부분만 테스트하기를 원한다. 개개의 부분들이 생각한 대로 동작한다는 확신을 쌓아 나감으로써, 비로소 그것들을 조립하여 전체 동작 시스템을 테스트하는 단계로 나아갈 수 있다.
 어쨌든, 만약 코드가 생각대로 동작한다고 확신할 수 없다면 어떤 형태의 테스트라 해도 그저 시간 낭비일 뿐이다. 여전히 다른 형태의 테스트도 필요할 테고, 환경에 따라서는 훨씬 많은 공식 테스트도 필요할 것이다. 하지만 자선과 마찬가지로 테스트는 기본에서 시작한다.


왜 귀찮게 단위 테스트를 해야 하는가?

무엇보다 시간은 금이다라는 말과 같이 단위테스트는 프로그래머의 삶은 편하게 해준다. 디버깅에 낭비하던 시간을 극적으로 줄여 준다.
 누군가 코드를 짤때 코드가 제데로 동작한다고 가정하고 개발을 하면, 그 이후에 코드가 제데로 동작하는지 확인 못한채 짜는 코드들은 문제는 늘어만 가게 된다. 어떤 코드 또한 돌아가지 않게 될 수도 있다. 처음에 짠 낮은 레벨의 코드가 문제가 생기면 그부분만 고친다고 해서 문제가 해결되는 것은 아니다. 이런 문제가 잇을 경우엔, 코드에 대한 확신을 얻어야 한다. 코드에게 무슨일을 하고 잇는지 물어봐야 하고 그 결과가 기대한 바와 같은지 확인해야 할 것이다. 이 간단한 개념이, 좀 더 나은 코딩을 위한, 가장 확실하고 가장 효과적인 기법인 단위 테스트의 핵심이다.

반응형

+ Recent posts