SRP 에 대한 자세

Download Report

Transcript SRP 에 대한 자세

객체지향 소프트웨어
설계의 5가지 원칙
SRP (Single Responsibility Principle)
ISP (interface Segregation Princliple)
A&D 3
by bbum
Agenda








5가지 원칙
SRP & ISP
SRP 정의
SRP 설계 효과 및
목적
SRP 에 대한 자세
SRP 예시.
또 다른 예시.
다른 관점.






ISP 의 정의.
ISP 에 대한 자세.
ISP 예시.
SRP vs. ISP
SRP & ISP 비교 예시.
결론.
5가지 원칙

객체지향 Software설계의 근본 원칙.
-
Design Pattern 의 근본 원칙.
Refactoring 의 근본원칙.
기타 객체지향 소프트웨어 설계 도구들의 근본이자 목적
이 되는원칙.
-

-
‘진리’가 아닌 ‘원칙’
서로 모순이나 선택이 필요할 때가 있음.
적절한 선택을 바탕으로 적용 및 활용이 능력.(아키텍쳐
의 역할)
SRP & ISP

SRP (Single Responsibility Principle)
- THERE SHOULD NEVER BE MORE THAN ONE REASON FOR A
CLASS TO CHANGE.

ISP (Interface Segregation Principle)
- CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON
INTERFACES THAT THEY DO NOT USE .
SRP 정의

SRP (Single Responsibility Principle)
-
THERE SHOULD NEVER BE MORE THAN ONE REASON FOR A
CLASS TO CHANGE.
-
방법 : 단일 책임의 원칙. 한 개의 객체는 한 개의 ‘책임’ 만을 가지고
있어야 한다.
핵심 : 변화.
효과 : 객체의 약한 결합, 강합 응집력.(Loose Coupling, Tight
Cohesion)
목적 : 변화에의 유연성 확보.
-
-
SRP 설계 효과 및 목적

-

-

-
약한 결합(Loose Coupling)
한 개의 객체가 한 개의 책임만을 가지고 있을 때 가능.
한 개의 객체가 여러 개의 책임을 가지게 될 때 깨어짐.
강합 응집력.(Tight Cohesion)
한 개의 책임을 오직 한 개의 객체가 담당할 때 가능.
한 개의 책임이 여러 개의 객체에 분산될 경우 깨어짐.
변화에의 유연성 확보
디자인 패턴 설계원칙의 최종 목적중의 하나.
OCP 의 기본전제.
SRP 에 대한 자세

SRP 에 대한 일반적인 자세.
-
-
귀에 못이 박히도록 들었다. 이해하고 있다고 생각한다.
그러나 여러가지 이유로 잘 어기게 된다.
원인 : 익숙치 않음, 고민해야 하는 시간이 길어짐. 개발기간 길어짐,
코드의 길이 길어짐, 객체가 많아짐.
방법 : SRP를 적용하지 않아 낭패봤던 경험, 감동을 주는 예시.

담배의 경우.
-
흡연은 건강에 해롭다.
그래도 안끊는다.
원인 : 중독, 익숙함에 대한 선호.
방법 : 시커매진 흡연자의 폐를 보여줌.(절대적인 효과는 없음.)
-
-
SRP 예시

-
-
예시
상황
적용하지 않은 디자인
문제점
해결 방안
적용 예시
효과 및 결론
SRP 예시

상황
-
국제적 은행의 계좌 관리 케이스.
기본적인 계좌로서의 기능을 가지고 있어야 한다.(입금,
출금, 조회)
이자율을 적용시키는 기능을 가지고 있어야 한다.
환율계산을 하는 기능을 가지고 있어야 한다.
다양한 Application에서 활용한다.
‘변화’가 발생할 가능성이 있다.
-
-
SRP 예시

SRP 적용전 디자인
-
일반적인 디자인.
직관적이고 단순한 인터페이스
제공.
-
Account
<<uses>>
개인 재산관리 Application
-잔고
+입금()
+출금()
+조회()
+환율 계산()
<<uses>>
국제 상거래 Application
SRP 예시

예상되는 문제점

-
정체성의 혼란
활용하는 Application 마다 이용하는 기능이 다름.
이용하지 않는 기능의 변화로 인한 재컴파일 및 배포.

변화의 원인이 다양
-
이자율 및 환율 계산 알고리즘이 변할때마다 코드 수정.
환율 계산시 국가별로 분기가 일어나야 함.
수시로 이자율 및 환율을 수정해 줘야 하는 부담.
관계없는 원인에 의한 변과가 영향을 미친다 한다.
-
-
SRP 예시

해결방안
-
SRP 의 적용
한객체에 한가지의 책임을 가지게 하고 분리

SRP 적용 예시
InterestRate
+이자율 계산()
Account
-잔고
+입금()
+출금()
+조회()
+환율 계산()
Adapter Pattern
ExchangeRate
+환율계산()
ExchangeRateUS
ExchangeRateJapan
ExchangeKorea
+환율계산()
+환율계산()
+환율계산()
SRP 예시

효과

정체성 정립.
-
원하는 객체만 들고가면 된다.(이자율 계산, 환율 계산.)

사용하지 않는 기능의 변화로 인한 영향을 받지 않는다.
-
각 Application에서 사용하는 객체만 컴파일 및 교체시켜주면 된다.

계산 알고리즘의 변화시 해당객체만 변화, 교체시키면 된다.
-
Stretegy 패턴 적용 가능. 변화에 대한 비용이 적게 든다.

환율 계산시 국가별 분기가 일어나지 않는다.
확장이 용이해 진다. OCP 적용을 위한 기반.

-
이자율 및 환율의 변화는 전문 객체들이 담당한다.
추가적인 Upgrade, 패치, 교체 등이 용이해진다.
 결론
‘변화’에의 유연성 확보
또다른 예시.

-
-
예시
상황
문제점
해결방안.
새로운 문제점.
또다른 예시.

-
상황
모뎀 인터페이스 구현.
인터페이스
interface Modem
{
public void dial(String pno);
public void hangup();
public void send(char c);
public char recv();
}
 문제점
- SRP에 어긋남.
- 두가지 책임이 존재
 Connection Management.
 Data Communication.
또다른 예시.

-
해결 방안
인터페이스의 분리.
SRP의 유지.
 새로운 문제점
- Modem Implementaion의 경우 SRP에 어긋나지 않은
가?
- 두가지 이상의 책임을 가지는 객체를 인정해야 하는가?
- 근본적으로 SRP를 깨뜨리지는 않는가?
ISP 정의

ISP (Interface Segregation Principle)
- CLIENTS SHOULD NOT BE FORCED TO DEPEND
UPON INTERFACES THAT THEY DO NOT USE
-
-
방법 : 인터페이스 분리의 원칙. 하나의 일반적인 인터페이스 보다는
구체적인 여러 개의 인터페이스가 낫다.
핵심 : 변화.
효과 : 인터페이스의 통합과 분리.
목적 : 변화에의 유연성 확보.
ISP 에 대한 자세

낯설다.
-
특히 C++ 프로그래머들에게는 더욱 낯선 구조이다.
Interface에 대한 확실한 정립이 필요.
자바의 경우는 이미 존재하는 구조이나 C++의 경우는 Pure
function을 이용한 구축과 적극적 활용이 필요.
-

Refactoring에서 많이 활용하는 기법.
-
Refactoring은 Design Pattern 과 더불어 소프트웨어 설계의 원칙을
실현하기 위해 또 다른 방법이 아닐런지?

C로도 객체지향 프로그램을 짤 수 있다.
-
언어자체의 완전성보다는 개발자의 지혜와 자세가 필요.
ISP 예시

-
-
예시
상황.
적용하지 않은 디자인.
문제점.
해결 방안
적용 예시
ISP 예시

상황
-
보안용 시스템에서 이용하는 Door 객체의 구현.(잠그기, 열기)
-
일정시간 간격으로 호출해주는 ‘알람기능’을 가져야 한다.
‘알람기능’을 얻기 위해서는 TimerClient객체를 Timer에 등록해야
한다.존재해야 한다.
-
class Door
{
public:
virtual void Lock() = 0;
virtual void Unlock() = 0;
virtual bool IsDoorOpen() = 0;
};
class Timer
{
public:
void Regsiter(int timeout, TimerClient* client);
};
class TimerClient
{
public:
virtual void TimeOut() = 0;
};
ISP 예시

적용하지 않은 디자인
-
상속관계 이용.
ISP 예시

문제점

Door Class가 TimeClient와 의존관계에 있다.
-
-
모든 Door 객체가 타이머를 필요로 하는 것은 아니다.
타이머를 필요로 하지 않는 Door 객체도 Timer관련 헤더 및 컴포넌트를 추가해야 한
다.
타이머를 필오로 하지 않는 Door 객체도 Timer에 연관된 변화에 영향을 받는다.

Interface Pollution.
-
타이머를 필요로 하지 않는 Door클래스를 상속한 모든 객체들도 TimerClient의 인터
페이스를 구현해야 한다.(LSP 원칙)
타이머를 필요로 하지 않는 Door 객체도 TimerClient의 인터페이스 변화에 영향을 받
아야 한다.(추가, 수정, 삭제)
Timer Class의 인터페이스의 변화시마다 모든 Door 객체들을 재빌드 및 배포 해야
한다.
-
-
ISP 예시

-
-
해결방안
현실적으로 두가지 이상의 인터페이스를 제공 해야하는 객체의 존재
를 인정.
대신 각 기능별로 분리된 인터페이스를 제공.
ISP 예시

적용 예시
class TimedDoor : public Door, public TimerClient
{
public:
virtual void Lock();
virtual void Unlock();
virtual bool IsDoorOpen();
virtual void TimeOut(int nTimeOutID);
};
ISP 예시

효과

Door Class 와 TimeClient Class의 강한 결합을 막아준다.
-
Door Class가 TimerClient와 부적절한 의존관계를 맺지 않는다.
서로의 내부 변화에 영향을 받지 않는다.

인터페이스의 분리.
-
각 해당 기능을 필요로 하는 Client에만 인터페이스를 제공한다.
한쪽의 인터페이스의 변화가 이것을 이용하지 않는 Client들에 영향을 미치지 않는다.
-
결론
변화의 유연성의 확보와 적절한 객체들간의 관계 정립.
SRP vs. ISP
-
모순인가? 상호 보완인가?
‘그때 그때 다르다.’
-
적절한 적용과 활용이 중요.

‘역할’과 ‘인터페이스’의 구분.

-
-
‘역할’과 ‘인터페이스’는 상호 의존성을 가지나 반드시 일치하는 의
미는 아니다.
SRP와 ISP에는 서로 다른 맥락에서 접근하여하는 원칙이다.
서로가 서로를 보완하여 더 나은 설계를 만들어 낼 수 있다.
예제 다시 보기

SRP
-
각 객체는 자신의 역
할에 충실

ISP
-
각 인터페이스는 해당
기능을 필요로 하는 클
라이언트에만 적용.
결론

객체지향 소프트웨어 설계에 있어 가장 근
본적인 원칙이자 최종목표가 되어야 하는
원칙.

가장 간단하고, 가장 어려운 원칙.