12. SRP : 단일 책임 원칙
한 클래스는 하나의 역할만 맡는다
클래스가 변경되는 이유는 유일해야 한다
13.
14.
15. 무엇이 좋아졌는가?
• 코드 변경의 영향이 미치는 범위 최소화
• 코드 응집성 향상
• 단위테스트에 유리
– InterestRate, ExchangeRate 객체는 Account 의
private 변수로, 각 클래스의 메서드는 public 으로
– 캡슐화와 테스트 용의성 둘 다 만족
16. SRP != (크기가 작은 클래스)
• 클래스의 크기는 작을수록 좋지만 여러 클래
스끼리의 교통정리를 해 주는 클래스도 필요
• 관련 클래스를 묶어 데이터 연관성
• 각 part 를 연결하는 whole 의 역할
• player -> ((inventory -> item), skill)
17. SRP(Single Responsibility)
단일 책임 원칙
OCP(Open Close)
개방-폐쇄 원칙
LSP(Liskov Substitution)
리스코프 교체 원칙
ISP(Interface Segregation)
인터페이스 격리 원칙
DIP(Dependency Inversion)
의존 관계 역전 원칙
22. OCP : 개방폐쇄 원칙
확장에 대해 열려있고 수정에 대해 닫혀있다
약속, 표준안을 만드는 것
interface, protocol, standard
핸드폰 24핀 커넥터
HTTP 표준을 rendering 하는 각종 browser 들
23.
24.
25. interface(표준)의 문제점
• 변경 비용이 비싸다
– interface 가 변경되면 모든 구현 클
래스에서 컴파일 에러 발생
– concrete class 이 뭔지 알기 어렵다
– BlueRay vs HD-DVD
• 충분히 안정된 후 interface 로
– 미리 바꾸지 않는다
– 첫 번째 총알 맞기
– 게임 하나가 완성된 다음에야?
• EPIC 의 Unreal Tounament (개밥먹기)
26. SRP(Single Responsibility)
단일 책임 원칙
OCP(Open Close)
개방-폐쇄 원칙
LSP(Liskov Substitution)
리스코프 교체 원칙
ISP(Interface Segregation)
인터페이스 격리 원칙
DIP(Dependency Inversion)
의존 관계 역전 원칙
28. LSP - 리스코프 교체(치환) 원칙
• 기반 클래스(Base Class)의 포인터나 참
조값을 사용하는 코드에서는 실제로 어떤
클래스인지 몰라도 쓸 수 있어야 한다
• 하위타입(subtype)은 그것의 기반 타입
(base type)에 대해 치환 가능해야 한다
• is-a 관계를 만족하는가?
• 바바라 리스코프(Barbara Liskov). 1988
38. 좀 더 실질적인 예제
bool Party::CanJoin(Pc& p) {
// do something
if (IsParty()) {
if (GetMember() < 12) {
return true;
}
} else { // 혈맹이라면
if (GetMember() < 140) {
// do something
41. LSP(교체가능) 정리
• concrete 클래스 자체에는 논리적 결함이
없어 보이더라도, 잘못 쓸 가능성이 있다
면 문제가 있다
– 수학에서는 (정사각형 is a 직사각형), 하지만
코드에서는 (정사각형 is not a 직사각형) 이
가능하다
– 실보다 득이 많다면, LSP(교체가능)원칙이 깨
지더라도 협약(convention)으로 해결할 수도
있다
42. stack(Java 와 C++)
java.lang.Object
extended by java.util.AbstractCollection
extended by java.util.AbstractList
extended by java.util.Vector
extended by java.util.Stack
template<class _Ty, class _Container = deque<_Ty> >
class stack {
void push(const value_type& _Val) { c.push_back(_Val); }
void pop() { c.pop_back(); }
_Container c;
};
43. SRP(Single Responsibility)
단일 책임 원칙
OCP(Open Close)
개방-폐쇄 원칙
LSP(Liskov Substitution)
리스코프 교체 원칙
ISP(Interface Segregation)
인터페이스 격리 원칙
DIP(Dependency Inversion)
의존 관계 역전 원칙
50. 너무 많은 걸 알고 있는 인터페이스
class Obj { // 레퍼런스만 관리
Attack
virtual int (Obj& o) {
ASSERT(0); // Actor 에서만 호출해야 함
return 0;
}
};
class Actor : public Obj {
virtual int Attack(Obj& o) { … }
};
std::map<int, Obj*> g_ObjDB;
g_ObjDB[1]->Attack(t);
51. 필요한 것만 알고 있는 인터페이스
class Obj { // 레퍼런스만 관리
};
class Actor : public Obj {
int Attack(Actor& o) { … }
};
std::map<int, Obj*> g_ObjDB;
std::map<int, Actor*> g_ActorDB;
g_ActorDB[1]->Attack(t);
52. ISP(인터페이스분리) 정리
• 같은 로직이 반복되면 up-class 하고 싶겠
지만 욕심내지 않는다
– 코드 재사용은 상속 대신 포함(aggregation)으로
• CTimerObject 대신
ITimerObject 와 CTimerHandler 활용
– 상속은 코드 재사용보다는 OCP(개방폐쇄)나
LSP(교체가능), DIP(의존역전)를 위해 사용
53. SRP(Single Responsibility)
단일 책임 원칙
OCP(Open Close)
개방-폐쇄 원칙
LSP(Liskov Substitution)
리스코프 교체 원칙
ISP(Interface Segregation)
인터페이스 격리 원칙
DIP(Dependency Inversion)
의존 관계 역전 원칙
60. • SRP(Single Responsibility) 단일 책임
– 클래스가 변경되는 이유는 유일해야 한다
• OCP(Open Close) 개방폐쇄 원칙
– 확장에 대해 열려있고 수정에 대해 닫혀있다
• LSP(Liskov Substitution) 리스코프 교체
– Base Class의 포인터나 참조값을 사용하는 코드
에서는 실제로 어떤 클래스인지 몰라도 쓸 수 있
어야 한다
• ISP(Interface Segregation) 인터페이스 격리
– 클라이언트는 자신이 쓰지 않는 인터페이스에 의
존하지 않는다
• DIP(Dependency Inversion) 의존 관계 역전
– 상위 모듈이 하위 모듈에게 의존하면 안 된다
62. • OCP(개방폐쇄)
– 인터페이스가 같은지?
– DrawShape를 호출하는 프로그래머 입장
• LSP(교체가능)
– 기반 클래스(Base Class)의 포인터나 참조값
을 사용하는 코드에서는 실제로 어떤 클래스
인지 몰라도 쓸 수 있어야 한다(정보은닉)
– DrawShape를 구현하는 프로그래머 입장
void DrawShape(const Shape& s) {
if (typeid(s) == typeid(Square))
DrawSquare((Square&)s));
else if (typeid(s) == typeid(Circle))
DrawCircle((Circle&)s);
}
63. • SRP(단일책임)
– 여러 책임이 섞여 있는 클래스를 책임별 분리
• ISP(인터페이스분리)
– 클라이언트가 클래스의 특정 기능만 이용한다
면 그런 기능의 부분 집합을 별도 인터페이스
로 추출
64. • OCP(개방폐쇄)
– 코드 추가만으로 기능 변경 가능한가
• DIP(의존역전)
– 변경의 주체가 누구인가
65. 현실은 시궁창
// 에라 모르겠다
// 해볼 수도 있겠으나 귀찮다. 일단 여기까지
// 구현의 편의를 위해 이렇게 한다. 시간이 없거든
// 작업중입니다 T_T
// 그래 나도 이러면 안되는 지 알어... 미안해...
// 원래는 lock 걸어야 하지만 이 정도면 괜찮을 듯?
한 번이라도 죽으면 lock 걸자. 07.10.xx
// 죽었다. lock 쓰는 걸로 바꾼다. 07.12.xx
// 사실 이렇게 짜면 안 되는데 이 클래스는 너무 고
치기 무서워서 못 건드리겠음
// 다시는 이런 일이 없어야 할 것임
69. 결론
클래스를 만들때는 고객의 입장에서 생각할 것
놀래키지 않는다
구조를 잡을때는 신중하게
실제로 써 본 뒤에 구조 잡기
안정화 단계란 영원히 오지 않을지도?
안정된 코드는 오래된 코드
언제가 “적당”한가?
라이브러리보다는 비즈니스 layer 가 중요
절대적인 법칙은 없다
71. Reference
• 실전 코드로 배우는 실용주의 디자인 패턴
• 소프트웨어 개발의 지혜 - 야스미디어
• zdnet - 객체지향 SW 설계의 원칙
– http://www.zdnet.co.kr/ArticleView.asp?artice_id=000000391
34727
– http://www.zdnet.co.kr/ArticleView.asp?artice_id=000000391
35552
– http://www.zdnet.co.kr/ArticleView.asp?artice_id=000000391
39151
– http://www.zdnet.co.kr/ArticleView.asp?artice_id=000000391
37043
• http://www.objectmentor.com/resources/publishedArticles
.html
• 실용주의 디자인 패턴 0장
• 애자일 프로그래밍 - 남기룡
72. 사진
• 높은 응집도, 낮은 결합도
– http://improf.egloos.com/2309582
– 실용주의 디자인 패턴
• 이미지 출처
– http://www.lostechies.com/blogs/derickbailey/archive/2009/02/11/solid-
development-principles-in-motivational-pictures.aspx
• 개발자 좀 살려주세요
– http://resistan.com/savethedeveloper/
• 사각형 집합
– http://middle.edupia.com/SchoolBook/seb/jd_seb1_content.asp?nTerm=2&nYear
=8&nConID=669&nCatID=250&nDaeNumber=5&target=jd_seb_right
• That’s not my job
– http://life-engineering.com/2008/04/28/thats-not-my-job/
• 자동차 사고
– https://www.youngsamsung.com/pblog.do?cmd=view&seq=459&memId=4&cate
goryId=49
• 내가 짰구나
– http://www.slideshare.net/wgshim/experience-report-agile-adoption-stories-
in-lg-electronics