현재 진행하고 프로젝트의 신규 기능에 대해 설계를 진행하면서 다시 브릿지 패턴에 대해 찾아보다가 예전에는 모르고 지나갔던 부분이 걸려 인터넷을 찾아보았다.

브릿지 패턴을 자세히 보니 패턴의 기본인 Strategy 패턴과 동일한게 아닌가? 라는 의문이 들었다. 실제 UML의 모양도 비슷했다.

실제 두 차이점에 대해 찾아본 결과 차이점은 있었다.

(Stackoverflow 참조 : http://stackoverflow.com/questions/464524/what-is-the-difference-between-the-bridge-pattern-and-the-strategy-pattern)

The UML class diagram for the Strategy pattern is the same as the diagram for the Bridge pattern. However, these two design patterns aren't the same in their intent. While the Strategy pattern is meant for behavior, the Bridge pattern is meant for structure.

The coupling between the context and the strategies is tighter than the coupling between the abstraction and the implementation in the Bridge pattern.

From wikipedia 


즉 브릿지와 스트래지 패턴의 차이점은 스트래지는 행동을 브릿지는 구조의 decoupling를 의미했다.

이 말은 언뜻보기에는 명확하지만 도대체 행동과 구조의 차이점은 무엇일까라는 의문이 들었다. 답변 중의 내용을 좀더 살펴보았다.

  • Strategy: you have more ways for doing an operation; with strategy you can choice the algorithm at run-time and you can modify a single Strategy without a lot of side-effects at compile-time;
  • Bridge: you can split the hierarchy of interface and class join him with an abstract reference (seeexplication)


행동이라는 것은 하나의 동작을 진행할 때 런타임 시점에서 사용자가 알맞는 알고리즘등을 선택하여 진행하는 것이며 구조는 인터페이스의 구조를 나누고 추상적인 참조를 통해 합치는 의미를 가지고 있다. 

즉 스트래지 패턴은 사용자가 사용하고 싶은 정렬 알고리즘을 실행 중에 선택하여 진행할 수 있고 브릿지 패턴은 데이터베이스들의 api를 wrapper 클래스를 추상화 하여 클라이언트가 동일한 api로 같은 동작할 수 있도록 한다는 것이다.

정리.

스트레지 패턴 : 같은 결과이지만 다른 처리방식(알고리즘)을 수행
브릿지 패턴 : 하나의 동작을 추상화하여 서로 다른 구조(데이터베이스, 네트워크 등) 수행




 

'UML,OOP,Pattern, TDD' 카테고리의 다른 글

TDD - 계약에 의한 설계(DbC, Design by Contract)  (0) 2011.04.19
TDD Tip  (0) 2011.04.19
객체지향 개발 관련 팁  (0) 2011.04.19
객체지향 개발 원칙  (0) 2011.04.19
UML Tip  (0) 2011.04.19
출처 : 테스트주도개발 TDD 실천법과 도구

계약이란 개념은 로직의 선/후행 조건 같은 단순한 개념부터, 개발에 필요한 업무규칙, 고객의 요구사항에 이르기까지의 다양한 경우를 지칭한다. (null 크, 최소값 체크, 음수 체크)

방어 프로그래밍 - 발생 가능한 문제 상황에 대비해 점검하는 부분을 의심
계약에 의한 설계 - 신뢰에 의한 프로그램

즉 선언적인 형태로 프로그램의 상태를 구분하고, 이를 통해 작성된 로직의 간결성을 유지하면서도 작성자의 의도를 명확히 전달한다

방어 프로그래밍 테스트 케이스 예

public void testAccount(){
try {
wrongAccount = new Account(-10000);  // Account 클래스는 음수가 들어갈 경우 IlleagalArgumentException 발생)
assertTrue("계좌는 반드시 양수 이여야함", false);
} catch(IlleagalArgumentException e) {
assertTrue(true);
}
}
 
 위 경우  Account가 음수가 들어 갈 경우 예외 상황이 발생되어 catch가 되어 조건이 참이 되게 된다. (해당 예외가 발생이 안되면 false를 발생하게 됨) 즉 Account 객체의 음수가 아닌 음수에 따른 결과를 테스트하게 되는 것임.

계약에 의한 설계에 의한 테스트 케이스는 따로 테스트 케이스를 작성하기 보다는 실제로 값이 입력되는 부분에 assert라는 키워드를 통해 특정 상황(양수 값)의 상태를 확증하는데 사용된다.


'UML,OOP,Pattern, TDD' 카테고리의 다른 글

Strategy pattern VS Brigde Pattern  (0) 2011.10.09
TDD Tip  (0) 2011.04.19
객체지향 개발 관련 팁  (0) 2011.04.19
객체지향 개발 원칙  (0) 2011.04.19
UML Tip  (0) 2011.04.19
출처 : 테스트주도개발 TDD 실천법과 도구

TDD유의사항

테스트케이스는 이름이 중요하다.
더 이상 제대로 동작하지 않은 테스트 케이스는 제거한다.
TDD는 자동화된 테스트를 만드는 것이 최종 목표가 아니다.
모든 상황에 대한 테스트 케이스를 만들 필요는 없다
여러 개의 실패하는 테스트 케이스를 한 번에 만들지 않는다.
하나의 테스트 케이스는 하나만 테스트하도록 작성한다.
전통적인 테스트 기법을 배워둔다.
테스트 케이스는 최대한 고립시킨다.

TIP

1. 기능 테스트, 단위 테스트 구분

기능 테스트 - 사용자 관점의 테스트
단위 테스트 - 애플리케이션 관점의 테스트

기능 테스트는 외부 동작 위주로 진행되기 때문에 블랙박스 테스트로 볼수 있다. 하지만 일부 단위가 수정 되었을 때 오류가 발생되게 되면 해당 오류 단위를 추적하기 힘든 상황이 있다. 이럴 경우 단위 테스트가 잘 구성되어있다면 쉽게 오류난 부분을 찾는데 도움이 될 것이다.

2. 미리 예상할 수 없는 경우 TDD진행

임의의 값을 만들어 실패를 만들고 실패 때 나온 값을 결과값으로 현재 상태가 올바름을 알 수밖에 없다.  TDD는 사실 개발자가 특정 메소드를 호출했을 때 어떤 값이 리턴될지 알고 있다는 것을 사전조건으로 가정되어 있다.

3. 테스트 케이스 코드를 작성하기 어려울 때

코드가 불필요한 클래스와 의존관계가 있는지 확인한다. 의존성을 피할수 없는 경우 Mock객체를 사용하는 방법이 있지만 최솨한만 사용한다. 억지로 테스트를 작성하는 것은 잘못된 접근이다.

4. 테스트 케이스를 작성할 때 외부 모듈이 익숙지 않을 경우

위 경우 테스트 케이스 작성은 두가지로 나눌수 있다.

가. 라이브러리 학습을 위한 테스트 케이스 - 신뢰도 측정의 개념으로 테스트 케이스를 작성한다.
나. 업무 코드 작성을 위한 테스트 케이스 - 외부 모듈의 API를 배제하고 업무시나리오에 맞게 테스트 케이스를 작성한다. API는 재료로 사용하는 것이라는 생각으로 시나리오 베이스 테스트 케이스를 작성하면 수월하다

5. 수동 테스트 VS 자동화된 테스트

자동화는 지향해야하는 목표이다. 하지만 자동화하는데 많은 노력이 들어간다. 따라서 프로젝트 적당한 시기에 도입한다. 수동 테스트의 단점은 회귀 테스트가 부담이 될 것이다. 기능이 추가/변경 될 때마다 기능 테스트를 수행해야하는데 누락되거나 지나치게 단순화된 형태로 테스트를 진행하게 될 가능성이 커진다.

6. void 메소드를 테스트 할 경우

메소드를 아래와 같이 나눌 수 있다

리턴값이 있는 메소드 : 기능
void 메소드 : 절차

메소드의 리턴값이 없다는 의미는 로직의 절차를 기술했거나, 로직 트리의 맨 끝에 해당하는 기능 위임 작업을 목표로 하는 것을 의미한다. 이 경우 행위 기반 테스트를 해야한다. 가장 간단한 방법은 상태를 확인 할수 있는 다른 메소드로 결과를 테스트 하는 것이다. (isClicked, isReady 등)

'UML,OOP,Pattern, TDD' 카테고리의 다른 글

Strategy pattern VS Brigde Pattern  (0) 2011.10.09
TDD - 계약에 의한 설계(DbC, Design by Contract)  (0) 2011.04.19
객체지향 개발 관련 팁  (0) 2011.04.19
객체지향 개발 원칙  (0) 2011.04.19
UML Tip  (0) 2011.04.19

1. 요구사항에 대해 일반적으로 보이는 명사나 비슷한 대상을 가지고 대충 관계를 맺지 말아야한다.
-> 이런 행동은 허깨비 클래스, 상상뿐인 추상화, 하나님 클래스 등을 생성할 여지가 있고 실제 코드로 작성이 엉망으로 바뀔 가능성이 많다.

허깨비 클래스 : 실제 단순한 기능을 하는 부분을 어뎁터 생성하게 되어 기능을 사용할 때 필요 없는 클래스
상상뿐인 추상화 : 개념에 의해서 추상 클래스를 생성 한 후 다른 클래스에서 전혀 사용하지 않은 클래스
하나님 클래스 : 여러 객체로 기능을 분리하였지만 실제 중요한 동작은 한 클래스에 몰려있게 되는 클래스

2. 문제를 생각해야 한다.
-> 실제 요구사항들이 진행되는 과정을 이해하고 클래스로 구현해야 하는 문제가 무엇인지 파악해야 한다. 하지만 이때에도 주의해야 할 사항이 있다.

선을 넘어간 연결 : 각 과정을 나누고 난뒤 물리적인 순서로 연관을 맷을 경우 문제가 발생한다. 즉 논리적인 관점에서 과정의 연관을 생각해야한다.

3. 사용자 인터페이스를 생각한다.
-> 실제 사용자(호출하는 대상) 관점에서 객체와 상호작용할 수단을 만든다. 인터페이스 내에서 위 단계에서 도출된 클래스와 어떻게 연결될지 논리적인 관점에서 생각한다. 이런 연결을 협력 다이어그램으로 표현 한 후 추상 모델 클래스 다이어그램으로 정의할 수 있다.

4. 추상 모델을 실제 구현한다.
-> 생성 된 모델을 현재 환경에 의존하지 말도록 구체적으로 고민해야 한다. 즉 DIP를 사용하여 의존관계에 대해 생각해본다. 그리고 의존관계를 인터페이스로 분리하여 세부 사항 정의 할 때 고차원적인 정책과 한정 된 유도 클래스 내 행동(메소드)을 분리해야 한다.

'UML,OOP,Pattern, TDD' 카테고리의 다른 글

Strategy pattern VS Brigde Pattern  (0) 2011.10.09
TDD - 계약에 의한 설계(DbC, Design by Contract)  (0) 2011.04.19
TDD Tip  (0) 2011.04.19
객체지향 개발 원칙  (0) 2011.04.19
UML Tip  (0) 2011.04.19

의존 관계 정리
1. 인터페이스를 만들어 의존 관계를 끊거나 의존의 방향을 바꿀수 있다.
2. 다형성을 사용하면 어떤 함수를 포함한 모듈에 의존하지 않고 그 함수를 호출할 수 있다.

SRP : 단 하나의 책임 원칙

1. 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다. 한 클래스가 너무 많을 것을 안다면(다양한 기능의 메소드) 부서지기 쉬운 클래스가 된다. 즉 설계 결합도가 너무 높다. UML을 통해 확인하기 쉽다. 둘 이상의 주제 영역에 의존 관계인 클래스를 찾아보면 된다. 가장 쉽게 찾을 수 있는 것은 특정 속성을 부여하는 인터페이스를 하나 또는 그 이상으로 구현하는 클래스를 확인한다. 

2. 기존에 존재하는 서로 다른 속성의 인터페이스와 클래스가 하나의 단위로 묶여야 한다면 인터페이스를 바로 적용하기 보다는 클래스를 상속한 자식 클래스에서 인터페이스를 적용하여 인터페이스와 부모 클래스의 연관관계를 최소화시킨다.

어떤 클래스를 변경해야 할 이유는 오직 하나 뿐이어야 한다

OCP : 개방 - 폐쇄 원칙

1. 소프트웨어 엔티티(클래스, 모듈, 함수)는 확장에 대해서는 개방되어야 하지만, 변경에 대해서는 폐쇄되어야 한다. 즉 모듈 자체를 변경하지 않고도 둘러싼 환경을 바꿀 수 있어야 한다. A->B->C 3개의 클래스가 의존된 상태에서 C클래스가 변경되면 A클래스 까지도 영향을 미친다. 이때 A와 B 사이에 인터페이스를 두어 환경 변경에 대해 폐쇄해야한다.

2. GUI를 사용한 MVC모델에서는 View와 Controller의 결합이 너무 강한 경우가 많다. 이때 OCP규칙을 적용하려면 FLIP-FLOP패턴을 적용하여 View와 Controller사이의 결합도를 낮춘다. FLIP-FLOP패턴은 뷰와 컨트롤러 각각 인터페이스를 생성하여 상대방의 인터페이스를 참조하게한 후 컨트롤러모델에서 뷰의 동작을 제어하는 형태를 가지는 방식이다. 이렇게 구현하는 경우 뷰와 컨트롤러 각각 테스트 케이스 작성시 SELF SHUNT패턴을 사용하여 의존성이 있는 객체를 대체할 수 있게 된다. 즉 TDD방식으로 구현하게 된다면 위와 같은 구조로 개발하기 수월해진다.

클래스를 변경하지 않고도 그 클래스의 환경을 바꿀 수 있어야 한다.

LSP : 리스코프 교체 원칙

1. 서브타입은 언제나 자신의 기반 타입으로 교체할 수 있어야 한다. 즉 instanceof(클래스지정) 이나 다운캐스트를 할 필요가 없어야한다. 사용자는 파생클래스에 대해 알 필요가 없어야 한다. 이런 경우는 동일 의미를 가진 클래스이지만 실행 방식이 다른 클래스를 하나의 기반 타입으로 묶으려고 할 때 발생하게 된다. 다른 실행 방식으로 인해 예외 상황을 명시하기 위해 다운캐스트나 instanceof를 사용하게 된다. 이때 동일 의미이지만 다른 기반 성격의 클래스로 분류해야한다.

유도된 크래스으 메서드를 퇴화시키거나 불법으로 만드는 일을 피하라. 기반 클래스의 사용자는 기반 클래스에서 유도된 클래스에 대해 알 필요가 없다.

DIP : 의존 관계 역전 원칙

1. 고차원 모듈은 저차원 모듈에 의존하면 안된다. 이 두모듈 모두 다른 추상화된 것에 의존해야 한다.
2. 추상화된 것은 구체적인 것에 의존하면 안된다. 구체적인 것이 추상화 된것에 의존해야 한다.
즉 자주 변경되는 컨크리트 클래스에 의존하면 안된다. 어떤 클래스에서 상속받아야 한다면, 기반 클래스를 추상 클래스로 만들어야 한다.
어떤 클래스의 참조를 가져야 한다면, 참조 대상이 되는 클래스를 추상 클래스로 만들어야한다. 만약 어떤 함수를 호출해야 한다면 함수를 추상 함수롤 만들어라. 여기서 말하는 클래스는 자주 변경되는 컨크리트 클래스 이다. 즉 개발 중인 클래스이거나 변할 가능성이 높은 비즈니스 규칙을 담은 클래스이다. UML을 사요아면 이 원칙을 쉽게 검사할 수 있다. 다이어그램의 화살표마다 인터페이스나 추상 클래스를 가리키는지 확인하면 된다.

자주 변경하는 컨크리트 클래스 대신 인터페이스나 추상 클래스에 의존하라

ISP : 인터페이스 격리 원칙
비대한 클래스 메서드를 다 사용하는 일은 매우 적다. 즉 필요치 않은 메서드에 의한 변화도 영향을 받게 된다. 이런 의존 관계는 필요한 인터페이스만 제고하여 필요하지 않은 메서드를 보호하면 된다.

어떤 객체의 사용자에게 필요한 메서드만 있는 인터페이스를 제공하라

'UML,OOP,Pattern, TDD' 카테고리의 다른 글

Strategy pattern VS Brigde Pattern  (0) 2011.10.09
TDD - 계약에 의한 설계(DbC, Design by Contract)  (0) 2011.04.19
TDD Tip  (0) 2011.04.19
객체지향 개발 관련 팁  (0) 2011.04.19
UML Tip  (0) 2011.04.19
출처 : UML 실전에서는 이것만 쓴다

로드맵

- UML은 대규모 소프트웨워 구조의 로드맵을 만들 때 유용하다. 이런 로드맨은 어떤 클래스가 다른 클래스에 의존하는지 개발짜가 빨리 파악할 수 있게 해주고 시스템의 구조에 대한 참조 도표로도 사용된다. 굳이 문서로 저장 안해도 된다

반복을 통해 다듬기
- 행위를 제일 먼저 시작하는 것이 좋다. 간단한 시퀀스 다이어그램으로 문제를 풀어나간다. 이후 협력 다이어그램을 작성한 후 구조를 점검하여 클래스 다이그램을 다듬어 나간다. 이때 클래스 간에 의존관계를 최소화하기 위해 적절한 패턴을 사용하는 것이 좋다.

미니멀리즘
- UML은 의사소통을 위해 존재하는 것이지 예쁘게 꾸미기 위해 존재하는 것이 아니다. 다이어그램 한 장에 많은 세부사항을 그려 넣지 말아야 한다. UML다이어그램은 메서드나 변수, 관계를 선언하는 장소로 취급해서는 안된다.


클래스다이어그램

연관
클래스 사이의 연관은 다른 객체의 참조를 가지는 인스턴스 변수를 의미한다. 프로그램 안에서 실제로 일어나는 일을 정확히 설명하는 "~와 연결된다" 와 같은 용어이다

집합
부분/전체 관계를 내포하는 특별한 형태. 집합에 대해 여러 정의가 내려져 있기때문에 혼란을 가져다 준다. 가급적 피하는 것이 좋다. 집합의 규칙은 전체는 자신이 될수 없고(자기참조), 어떤 객체가 자신의 부분이 될수 없고, 두 객체가 서로 상대 객체의 부분이 될수 없다. 그리고 세 객체가 전체/부분 관계의 고리를 만들 수 없다.

합성
집합과 동일한 규칙을 가지고 있으면서 몇가지 규칙이 추가된다.
피보호자의 한 인스턴스를 두 주인이 소유하지 못한다. 하지만 객체 다이어그램과 대응하는 클래스 다이어그램은 문제 없다.
주인은 피보호자의 수명 전체에 책임을 진다. 주인이 소멸되면, 피보호자도 함께 소멸되어야 한다. 즉 주인 객체에서 내에 생성된 피보호 객체는 주인 객체가 메모리에서 해제될때 같이 해제되어야한다.


시퀀스다이어그램

- 시퀀스 다이어그램은 모든 시나리오에서 공통으로 나오는 것을 찾아 초점을 맞춰야한다. 공통된 주제와 공통된 실천 방법을 보이기 위해 다이어그램을 사용해야한다. 사소한 차이점까지 모두 문서로 만들기 위해 다이어그램을 사용하지 마라. 메시지 흐름을 설명하기 위해 시퀀스 다이어그램을 꼭 그려야 한다면 간결하고 절재해서 그려야한다.

첫째. 시퀀스 다이어그램이 정말 필요한지 확인하라. 코드가 의사전달하기 더 쉽고 경제적인 경우가 많다.
둘째. 시퀀스 다이어그램이 필요하다면 여러 시나리오로 쪼갤 수 있는지 확인하라. 거대한 시퀀스 다이어그램은 읽기 쉬운 작은 시퀀스 다이어그램 여러개로 나눌수 있다.
세째. 무엇을 그려야하는지 생각해봐야한다.저차원 연산에 대한 세부사항과 고차원의 개괄인지 생각하여야 한다. 대부분의 경우 고차원 다이어그램이 더 쓸모있다.













'UML,OOP,Pattern, TDD' 카테고리의 다른 글

Strategy pattern VS Brigde Pattern  (0) 2011.10.09
TDD - 계약에 의한 설계(DbC, Design by Contract)  (0) 2011.04.19
TDD Tip  (0) 2011.04.19
객체지향 개발 관련 팁  (0) 2011.04.19
객체지향 개발 원칙  (0) 2011.04.19

+ Recent posts