o d for agile software developmentcfs2.tistory.com/upload_control/download.blog?fhandle=... ·...
TRANSCRIPT
1
OObjectbject--OOrientedriented DDesignesign
for for AgileAgile Software DevelopmentSoftware Development
소 속 : ㈜ 미래로시스템
작 성 자 : 고형호
메 일 : [email protected]
홈 페 이 지 : http://www.innosigma.com
http
://w
ww
.inn
osig
ma.
com
2
Goal
Object-Oriented Design
http
://w
ww
.inn
osig
ma.
com
3
Contents
3. Modeling
1. Object-Oriented
2. What is an Object
Part 1. ObjectPart 1. Object--Oriented ModelingOriented Modeling
1. Usecase Diagram
2. Class Diagram
3. Sequence Diagram
Part 2. UML Part 2. UML 기초기초
1. The Fragile-Base-Class Problem
2. Customer Requirement
3. Object-Oriented Design
5. Summary
4. Design Pattern in Practice
Part 3. UML Part 3. UML 실전실전
4
Part 1. Object-Oriented Modeling
5
1. Object-Oriented
http
://w
ww
.inn
osig
ma.
com
6
??
신제품 실패 원인(IBM, 1996)
출처 : "DMAIC" 발표자료 인용(2005.04.06 삼성경제연구소 6시그마실 김종만)
Object-Oriented
http
://w
ww
.inn
osig
ma.
com
7
Object-Oriented의 장점
1. 데이터 지향적이다.
2. 인터페이스 지향적이다.
1 : N
3. Real World 지향적이다.
Read World : Mapping ≒ 1 : 1
DATA FUNCTION(변경 횟수)
Creation : Use =(객체 사용 횟수)
Object-Oriented
http
://w
ww
.inn
osig
ma.
com
8
Object-Oriented의 특징
1. 캡슐화(Encapsulation)
2. 상속(Inheritance)
3. 다형성(Polymorphism)
코드 재사용 다형성 은닉
캡슐화(Encapsulation)
은닉(Hiding)
구현(Implement) 상속
인터페이스(Interface) 상속
∆∆O O
Object-Oriented
구현 상속을 통한 재사용-. 구현 상속을 통한 재사용은 불필요한 결합도를 증가시킨다. 재사용을 위해서는 Composition을 사용하자.-. 구현 상속은 여러 클래스가 공통의 연산 집합을 공유하고 있을 때 정규화를 위해 사용하자.
구현 상속을 통한 다형성-. 깨지기 쉬운 기반 클래스 문제가 있기 때문에 다형성 획득 측면서 인터페이스 상속보다 안전하지 못 하다.
: 데이터와 연산을 한데 묶는 것
: 내부 데이터, 내부 연산을 외부에서 접근하지 못하도록 격리 시키는 것
기반 클래스의 행동을 상속한 클래스에서 재정의하는 것
출처 : 실전 코드로 배우는 실용주의 디자인 패턴(사이텍미디어, 송치형)
9
2. What is an Object
http
://w
ww
.inn
osig
ma.
com
10
Class
Object
VS.
= User Defined Data Type
= Service Provider
What is an Object
http
://w
ww
.inn
osig
ma.
com
11
Object (Service Provider)
‘무엇을 하는가(WHAT)’ 하는 연산으로 정의되어야 한다(변화하지 않는 것).
‘어떻게(HOW)’ 연산을 수행하는가는 철저히 은닉되어야 한다(변화하는 것).
What is an Object
12
3. Modeling
http
://w
ww
.inn
osig
ma.
com
13
Analysis/Design Programming
??
Model은 어떤 것이 실제로도 잘 동작하는지 알아보려고 만드는 것이다.
Modeling
Modeling은 Model을 만들어 테스트 해보는 과정을 이야기 한다.
목적 : 실제 물건을 만드는 것보다 훨씬 적은 비용으로 설계가 제대로 되었는지 판단할 수 있다.
Modeling
Read World System
Test
Test
Model
http
://w
ww
.inn
osig
ma.
com
14
Modeling
Software Development 입장에서 Model은 ?
결론
UML은 Modeling의 필수 도구 이다.
Model은 개발된 소프트웨어 프로젝트의 하나 또는 그 이상의 측면들을 표현하는
UML 다이어그램의 집합이다.
15
Part 2. UML 기초
16
1. Usecase Diagram
http
://w
ww
.inn
osig
ma.
com
17
Usecase Diagram
사용자사용자(Actor)(Actor)가 보낸 자극자극 하나에 대한 반응으로 시스템시스템이 진행하는(정보 요청/제공등 상호작용)
눈에눈에 보이는보이는 이벤트이벤트들의 흐름흐름을 표현한다.
사용자(Actor)은 시스템 외부에 존재하며 시스템과 상호작용하는 것.
유스케이스(Usecase)은 사용자(Actor)의 관점에서 작성된 시스템의 동작 하나를 기술 한 것.
목적
Usecase Name
Actor Name
Relationship System
System Name
사용자사용자의 시각시각에서 시스템시스템의 범위범위와 기능기능을 파악할 수 있다.
http
://w
ww
.inn
osig
ma.
com
18
Usecase Diagram
Notiation Actor and Usecase Actor and Actor Usecase and Usecase
Association(Communication)
Generalization(Inheritance)
Include(Shared Service)
Extend
(Extension Point)
<<include>>
<<extend>>
Extension Point
항공편 검색
창구 담당자
Airline Reservation
항공편 예약
적용 가능한할인 검색
<<include>>
<<include>>
Ex.
19
2. Class Diagram
http
://w
ww
.inn
osig
ma.
com
20
시스템에서 사용되는 객체객체 타입타입((클래스클래스))를 정의정의하고,
그들 간에 존재하는 정적인정적인 관계관계를 다양한 방식으로 표현표현한다.
Class Diagram
목적
높은높은 응집도응집도(High Cohesion)(High Cohesion), 낮은낮은 결합도결합도(Low Coupling)(Low Coupling) 설계설계를 하도록 강요강요한다.
응집도은 하나의 클래스가 하나의 기능(책임)을 온전히 순도 높게 담당하고 있는 정도
결합도는 클래스 간의 서로 다른 책임들이 얽혀 있는 상호 의존도의 정도
시스템 고유의 유지유지 보수성보수성과 적응성적응성을 측정측정하는 기준기준
http
://w
ww
.inn
osig
ma.
com
21
class Widget{};
class Widget{public:
int m_nValue;protected:
long m_lValue;private:
double m_dwValue;};
class Widget{public:
int m_nValue;
public:void Do();
protected:int Do(int nValue);
private:long Do(int nValue, long lValue);
};
Widget
Class Name
Widget
: doublem_dwValue-
: longm_lValue#
: intm_nValue+
Attritue
Visibility Variance type
Class Diagram
+
: intm_nValue+
: longDo(nValue : int, lValue : long)-
: intDo(nValue : int)#
Do( )
Widget
Parameters Return type
Operation
Class Diagram
http
://w
ww
.inn
osig
ma.
com
22
Class Diagram
class Widget{public:
virtual void Draw() = 0; int GetSize();
};
class Widget{public:
virtual void Draw() = 0; virtual int GetSize() = 0;
};
Widget
+ Draw()
+ GetSize() : int
추상 메소드(이탤릭체)
추상 클래스(이탤릭체)
<<interface>>Widget
+ Draw()
+ GetSize() : int
Stereotype
class interface(기존 UML 요소) (새로 만든 UML 요소)
Class Diagram
http
://w
ww
.inn
osig
ma.
com
23
class Widget{public:
virtual void Draw(); };
class Button : public Widget{public:
virtual void Draw();};
Widget
+ Draw()
Button
+ Draw()
Implement Inheritance = Generalization(OOP) (UML)
class Widget{public:
virtual void Draw() = 0; };
class Button : public Widget{public:
virtual void Draw();};
Class Diagram
<<interface>>Widget
+ Draw()
Button
+ Draw()
Interface Inheritance = Realization(OOP) (UML)
Class Diagram
http
://w
ww
.inn
osig
ma.
com
24
class Widget{public:
list<Tool*> m_pTool; };
class Tool{};
Multiplicity
Unidirectional Association
Widget Tool
+m_pTool
0..*
Select Widget
Role name
class Widget{public:
vector<Tool*> m_pTool; };
class Tool{};
Association name
OOP에서 직접적으로 지원하는 개념이 아니다.
Class Diagram
Class Diagram
http
://w
ww
.inn
osig
ma.
com
25
class Computer{public:
Printer* m_pPrinter;};
class Printer{
};
Aggregation
Computer Printer+m_pPrinter
Computer Computer Computer
Printer Printer
Ex. Aggregation
( O ) ( O ) ( O ) ( O )
class Computer{public:
Printer* m_pPrinter;public:
Computer(){
m_pPrinter = new Printer;}~Computer(){
delete m_pPrinter; }
};
Composition
Computer Printer+m_pPrinter
Ex. Compositon
Computer
keyboard
mouse
Computer
keyboard
mouse
( O ) ( X ) ( X )
Class Diagram
Class Diagram
http
://w
ww
.inn
osig
ma.
com
26
class Widget{public:
void Draw(Graphics* pGraphics);};
class Graphics{
};
Dependency
Graphics
Widget
+ Draw(pGraphics : Graphics*)
Class Diagram
Class Diagram
27
3. Sequence Diagram
http
://w
ww
.inn
osig
ma.
com
28
Sequence Diagram
목적
객체객체간의 동적인동적인 상호관계상호관계를 시간시간 순서순서에 따라 표현표현한다.
시스템의 문제문제 해결해결을 위한 전체전체 흐름흐름을 쉽게 파악할 수 있다.
http
://w
ww
.inn
osig
ma.
com
29
class ShapeFactory
{
public:
void MakeShape();
};Sequence D
iagram
: ShapeFactory
MakeShape
Time
Object Name Class Name
Life Line Activation
Method
Message
Sequence Diagram
http
://w
ww
.inn
osig
ma.
com
30
class ShapeFactory{public:
Shape* MakeShape(){
return new Rectangle;}
};
class Rectangle : public Shape{};
Sequence Diagram
: ShapeFactory
shape := MakeShape
shape : Rectange
Return Message
Return
Sequence Diagram
http
://w
ww
.inn
osig
ma.
com
31
class ShapeFactory{private:
Shape* m_pShape;
public:void DeleteShape(){
delete m_pShape;}
};
Sequence Diagram
End of Object Life
Sequence Diagram
: ShapeFactory
DeleteShape
shape : Rectange
http
://w
ww
.inn
osig
ma.
com
32
class ShapeFactory{private:
static void MakeShape();};
Sequence Diagram
ShapeFactory
MakeShape
Sequence Diagram
http
://w
ww
.inn
osig
ma.
com
33
class Log{public:
Log(){
_beginthreadex( …, ThreadFunc, …);}
unsigned int WINAPI ThreadFunc(…){
while(IsRunning){
// 로그 데이터 처리
}}
void Write(string strLog){
// 로그 데이터 추가만 수행
// 로그 데이터 처리는 ThreadFunc에서
}};
Sequence Diagram
: Log
Write
Asynchronous Message
Sequence Diagram
34
Part 3. UML 실전
35
1. The Fragile-Base-Class Problem
http
://w
ww
.inn
osig
ma.
com
36
깨지기 쉬운 기반 클래스 문제(The Fragile-Base-Class Problem)
class ArrayList{public:
void Add(int nIndex, String strData){
…}String Remove(int nIndex){
…}void Clear(){
// 모든 데이터 삭제…
}…
};
class Stack : public ArrayList{ private:
int m_nTopOfStack;
public:void Push(String strData){
Add(m_nTopOfStack++, strData);}String Pop(){
return Remove(--m_nTopOfStack);}
}
Stack stack = new Stack();stack.Push("1");stack.Push("2");stack.Clear();stack.Push(“3”); // m_nTopOfStack가 올바른 위치를 지정할 수 없다
clear 메소드 호출로 인하여 스택 인텍스(m_nTopOfStack)가 올바른 위치를 지정할 수 없게 된다.즉, 원하지 않는 메소드(clear)까지 모두 상속 받기 때문이다.
http
://w
ww
.inn
osig
ma.
com
37
1. Stack 내부의 상태를 변경하는 모든 메소드(clear, …)를 상속 받는다.
2. clear 메소드가 예외를 던지도록 상속 받는다.
기반 클래스에 clear와 같은 메소드를 추가하는 경우에는 속수무책이다.
깨지기 쉬운 기반 클래스 문제(The Fragile-Base-Class Problem)
기반 클래스의 규약은 파생 클래스가 기반 클래스의 몇몇 메소드가 작동하길 원하지 않을 때예외를 던진다고 말해 주지 않는다.
예외로 인하여 클라이언트는 다형성을 이용한 코딩을 하지 못하게 된다(LSP 위반).
컴파일 타임 에러(해당 메소드를 찾을 수 없음)를 런타임으로 옮기게 된다.
단순 해결책
http
://w
ww
.inn
osig
ma.
com
38
깨지기 쉬운 기반 클래스 문제(The Fragile-Base-Class Problem)
Implement Inheritance 보다는 Composition을 선호하자
class ArrayList{public:
void Clear(){
// 모든 데이터 삭제…
}…
};
class Stack : public ArrayList{ private:
int m_nTopOfStack;
public:Stack() : m_nTopOfStack(0){}void Push(String strData){
Add(m_nTopOfStack++, strData);}String Pop(){
return Remove(--m_nTopOfStack);}
}
Implement Inheritance
class Stack{ private:
int m_nTopOfStack = 0;ArrayList m_data;
public:Stack() : m_nTopOfStack(0) {}public void Push(String strData){
m_data.Add(m_nTopOfStack++, strData);}public String Pop(){
return m_data.Remove(--m_nTopOfStack);}
}
Composition
Favor Object Composition(with Interface Inheritance) over Class Implementation.
(Implement Inheritance)
http
://w
ww
.inn
osig
ma.
com
39
class Stack{ private:
int m_nTopOfStack = 0;ArrayList m_data;
public:Stack() : m_nTopOfStack(0) {}public void Push(String strData){
m_data.Add(m_nTopOfStack++, strData);}public String Pop(){
return m_data.Remove(--m_nTopOfStack);}
}
Stack stack = new Stack();stack.Push("1");stack.Push("2");stack.Clear();
clear 메소드 호출로 인하여 컴파일러 에러가 발생된다.즉, 구현상속으로 인한 문제점(런타임시 발생될 에러 가능성)을 제거할 수 있다.
깨지기 쉬운 기반 클래스 문제(The Fragile-Base-Class Problem)
40
2. Customer Requirement
http
://w
ww
.inn
osig
ma.
com
41
Log
+Write(const void*, UINT)void Log::Write(const void* lpBuf, int nLen){
// File 출력}
요구사항 구현
요구사항
: Log 데이터를 File과 DB에 출력한다.
1. 변수 추가 2. 함수 추가 3. 구현 상속
Customer Requirement
http
://w
ww
.inn
osig
ma.
com
42
void Log::Write(const void* lpBuf, int nLen){
if(출력판단){
// File 출력}else{
// DB 출력}
}
1. 변수변수 추가
추가 요구사항
: Log 데이터를 Window에 출력한다.
1. 변수 추가 : 조건문 수정 필요
추가 요구 사항 구현은 ?
Customer Requirement
2. 함수 추가 : 조건문 수정 필요, 함수 추가 필요(WriteWindow)
3. 구현 상속 : 깨지기 쉬운 베이스 클래스 및 불안정한 다형성 획득의 잠재적 문제 소유
int _tmain(int argc, _TCHAR* argv[]){
...if(출력판단)
pLog->WriteFile( … );else
pLog->WriteDB( … );...
}
2. 함수함수 추가
class Log{
virtual void Write(const void*, UINT){
//do something...}
};
class LogFile : public Log{
virtual void Write(const void*, UINT){
// File 출력}
};
class LogDB : public Log{
virtual void Write(const void*, UINT){
// DB 출력}
};
3. 구현구현 상속
43
3. Object-Oriented Design
http
://w
ww
.inn
osig
ma.
com
44
Object-Oriented Design Principles
1. SRP(Single Responsibility Principle) : 단일 책임 원칙
2. DIP(Dependency Inversion Principle) : 의존 관계 역전의 원칙
3. ISP(Interface Segregation Principle) : 인터페이스 분리의 원칙
4. LSP(Liskov Substitution Principle) : 리스코프 대체 원칙
5. OCP(Open-Closed Principle) : 개방 폐쇄 원칙
Object-Oriented Design
http
://w
ww
.inn
osig
ma.
com
45
Customer RequirementCustomer Requirement
Log 데이터를 File에 출력한다.
Log 데이터를 Window에 출력한다.
File과 Window Stream을 생성한다.
생성이 제한된 Log를 생성한다(전역적 접근).
동기화 처리된 Buffered Memory를 이용하여 File에 출력한다(속도 향상).
File System
Log::Write
Log::Write
Log::Write
접근 횟수 : 3
적용 후적용 전
접근 횟수 : 1
Buffered Memory File System
Log::Write
Log::Write
Log::Write
Write
동기화 처리
동기화 처리하여 Window에 출력한다(멀티스레드 지원).
Object-Oriented Design
http
://w
ww
.inn
osig
ma.
com
46
Code ReuseCode Reuse
Log 데이터를 Window에 출력한다.
동기화 처리된 Buffered Memory를 이용하여 File에 출력한다(속도 향상).
동기화 처리하여 Window에 출력한다(멀티스레드 지원).
Log 데이터를 File에 출력한다.
File과 Window을 생성한다.
Customer RequirementCustomer Requirement
생성이 제한된 Log를 생성한다(전역적 접근).
Object식별
Sub-HOW : 동기화 처리, Buffered Memory
HOW : File, Window HOW : File, Window HOW : 생성이 제한된 Log
WHAT : 출력 WHAT : 생성 WHAT : 생성
Object-Oriented Design
http
://w
ww
.inn
osig
ma.
com
47
WinOutputStreamFactoryFileOutputStreamFactory
HOW
OCP(LSP)
<<interface>>IOutputStreamDIP
WHAT, SRP
+Write(const void*, UINT)
Sub-HOW
SyncOutputStream
OCP(LSP)
BufferedOutputStream
WinOutputStreamFileOutputStream DecoratorOutputStream
OCP(LSP)
HOW
DIP
WHAT, SRP
+Create() : IOutputStream*
<<interface>>IOutputStreamFactory
Log
WHAT/HOW, SRP 위반
#Log+Create() : Log*+SetLog(IOutputStream*)+Write(const void*, UINT)
<<create>>
<<create>>
Code ReuseCode Reuse
DIP
Sub-
HOW
HOW
WHAT
WHAT
HOW
: 출력
: File, Window
Sub-HOW : 동기화 처리, Buffered Memory
WHAT
HOW
: 생성
: File, Window
WHAT
HOW
: 생성
: 생성이 제한된 Log
DIP
Client
PhysicalLogical
Client
http
://w
ww
.inn
osig
ma.
com
48
IOutputStream* WinOutputStreamFactory::Create(){
IOutputStream *pWin, *pSync;
pWin = new WinOutputStream;pSync = new SyncOutputStream(pWin);return pSync;
}
IOutputStream* FileOutputStreamFactory::Create(){
IOutputStream *pFile, *pBuffered, *pSync;
pFile = new FileOutputStream;pBuffered = new BufferedOutputStream(pFile);pSync = new SyncOutputStream(pBuffered);return pSync;
}
File 출력
확장
에대
해열
려있
고,
수정
에는
대해
닫혀
있다
void Client::Init(){
Log::Create()->SetOutputStream(m_pFactory->Create());}
void Client::Log( … ){
…Log::Create()->Write(lpBuf, nLen);
}
Window 출력
재사용 가능한 설계
OpenOpen--Closed PrincipleClosed Principle
Object-Oriented Design
Code ReuseCode Reuse
http
://w
ww
.inn
osig
ma.
com
49
Log
WHAT/HOW, SRP 위반
<<interface>>IOutputStreamDIP
WHAT, SRPWHAT, SRP
WinOutputStreamFactoryFileOutputStreamFactory
HOW
OCP(LSP)
WinOutputStreamFileOutputStream DecoratorOutputStream
OCP(LSP)
HOW
Sub-HOW
Write(const void*, UINT)
DIP
SyncOutputStream
OCP(LSP)
BufferedOutputStream
DIP<<interface>>
IOutputStreamFactory
<<create>>
<<create>>
Singleton Strategy
Decorator
Pattern Summary
Abstract Factory
Object-Oriented Design
#Log+Create() : Log*+SetLog(IOutputStream*)+Write(const void*, UINT)
+Create() : IOutputStream*
DIP
Client
50
4. Design Pattern in Practice
http
://w
ww
.inn
osig
ma.
com
51
Customer RequirementCustomer Requirement
Log 데이터를 DB에 출력(저장)한다.
HOW(세부 구현, 변화는 것)
DBOutputStream
WHAT(외부와의 계약, 변화지 않는 것)
HOW(세부 구현, 변화는 것)
DBOutputStreamFactory
WHAT(외부와의 계약, 변화지 않는 것)
DBOutputStream를 생성한다.
WHATHOW
동기화 처리된 Buffered Memory를 이용하여 DB에 출력(저장)한다.
Buffered MemorySub-HOW
동기화 처리Sub-HOW
DBHOW
delegationdelegation
출력(저장)WHAT
Sub-HOW
delegation
Sub-HOW
delegation
Design Pattern in Practice
http
://w
ww
.inn
osig
ma.
com
52
Object-Oriented Design
HOW : DBOutputStream HOW : DBOutputStreamFactoryWHAT : 출력 WHAT : 생성
<<create>>
WinOutputStreamFactoryFileOutputStreamFactory
<<interface>>IOutputStream
+Write(const void*, UINT)
SyncOutputStream BufferedOutputStream
WinOutputStreamFileOutputStream DecoratorOutputStream
+Create() : IOutputStream*
<<interface>>IOutputStreamFactory
Log
#Log+Create() : Log*+SetLog(IOutputStream*)+Write(const void*, UINT)
<<create>>
Client
Design Pattern in Practice
Sub-HOW : 동기화 처리, Buffered Memory
DBOutputStreamFactory
HOW
DBOutputStream
HOW
WHATWHAT
Sub-HOW
http
://w
ww
.inn
osig
ma.
com
53
IOutputStream* DBOutputStreamFactory::Create(){
IOutputStream *pDB, *pBuffered, *pSync;
pDB = new DBOutputStream;pBuffered = new BufferedOutputStream(pFile);pSync = new SyncOutputStream(pBuffered);return pSync;
}
IOutputStream* FileOutputStreamFactory::Create(){
IOutputStream *pFile, *pBuffered, *pSync;
pFile = new FileOutputStream;pBuffered = new BufferedOutputStream(pFile);pSync = new SyncOutputStream(pBuffered);return pSync;
}
File 출력
확장
에대
해열
려있
고,
수정
에는
대해
닫혀
있다
void Client::Init(){
Log::Create()->SetOutputStream(m_pFactory->Create());}
void Client::Log( … ){
…Log::Create()->Write(lpBuf, nLen);
}
DB 출력
재사용 가능한 설계
OpenOpen--Closed PrincipleClosed Principle
Design Pattern in Practice
Code ReuseCode Reuse
54
5. Summary
http
://w
ww
.inn
osig
ma.
com
55
Object =Object = Service ProviderService Provider
Summary