SlideShare a Scribd company logo
OOP 설계 원칙S.O.L.I.D.v.2.5NCsoft박일http://parkpd.egloos.com
OOP 설계 원칙S.O.L.I.D.이러다가 v.10.0 까지 나올 기세v.2.5NCsoft박일http://parkpd.egloos.com
강사 소개KGC 07 게임에 적용해 보는 TDDKGC 08, NCDC 09 Lineage2 Production SystemKGC 09, NDC 10 사례로 살펴보는 디버깅KGC 10 낡은 코드에 테스트 코드 넣기
잠깐만 UML 을 배웁시다
잠깐만 UML 을 배웁시다
잠깐만 UML 을 배웁시다
잠깐만 UML 을 배웁시다
대원칙 - 높은 응집도, 낮은 결합도응집도 : 하나의 클래스가 하나의 기능(책임)을 온전히 순도 높게 담당하는 정도결합도 : 클래스간의 서로 다른 책임들이 얽혀 있어서 상호의존도가 높은 정도
SRP(Single Responsibility)단일 책임 원칙OCP(Open Close)개방-폐쇄 원칙LSP(Liskov Substitution)리스코프 교체 원칙ISP(Interface Segregation)인터페이스 격리 원칙DIP(Dependency Inversion)의존 관계 역전 원칙
SRP(Single Responsibility)단일 책임 원칙OCP(Open Close)개방-폐쇄 원칙LSP(Liskov Substitution)리스코프 교체 원칙ISP(Interface Segregation)인터페이스 격리 원칙DIP(Dependency Inversion)의존 관계 역전 원칙
SRP (Single Responsibility)단일 책임 원칙
SRP : 단일 책임 원칙한 클래스는 하나의 역할만 맡는다클래스가 변경되는 이유는 유일해야 한다
OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.
무엇이 좋아졌는가?코드 변경의 영향이 미치는 범위최소화코드 응집성 향상단위테스트에 유리InterestRate, ExchangeRate객체는 Account 의 private 변수로, 각클래스의 메서드는public 으로캡슐화와 테스트 용의성 둘 다 만족
SRP != (크기가 작은 클래스)클래스의 크기는 작을수록 좋지만 여러 클래스끼리의 교통정리를 해 주는 클래스도 필요관련 클래스를 묶어 데이터 연관성각 part 를 연결하는 whole 의 역할player -> ((inventory -> item), skill)
SRP(Single Responsibility)단일 책임 원칙OCP(Open Close)개방-폐쇄 원칙LSP(Liskov Substitution)리스코프 교체 원칙ISP(Interface Segregation)인터페이스 격리 원칙DIP(Dependency Inversion)의존 관계 역전 원칙
OCP(Open Close)개방폐쇄 원칙
표준이 없는 세상
표준이 없는 세상
표준이 없는 세상
OCP : 개방폐쇄 원칙확장에 대해 열려있고수정에 대해 닫혀있다약속, 표준안을 만드는 것interface, protocol, standard핸드폰 24핀 커넥터HTTP 표준을 rendering 하는 각종 browser 들
OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.
interface(표준)의 문제점변경 비용이 비싸다interface 가 변경되면 모든 구현 클래스에서 컴파일 에러 발생concrete class 이 뭔지 알기 어렵다BlueRayvs HD-DVD충분히 안정된 후 interface 로미리 바꾸지 않는다첫 번째 총알 맞기게임 하나가 완성된 다음에야?EPIC 의 Unreal Tounament (개밥먹기)
SRP(Single Responsibility)단일 책임 원칙OCP(Open Close)개방-폐쇄 원칙LSP(Liskov Substitution)리스코프 교체 원칙ISP(Interface Segregation)인터페이스 격리 원칙DIP(Dependency Inversion)의존 관계 역전 원칙
LSP(Liskov Substitution)리스코프 교체(치환) 원칙
LSP - 리스코프 교체(치환) 원칙기반 클래스(Base Class)의 포인터나 참조값을 사용하는 코드에서는 실제로 어떤 클래스인지 몰라도 쓸 수 있어야 한다하위타입(subtype)은 그것의 기반 타입(base type)에 대해 치환 가능해야 한다is-a 관계를 만족하는가?바바라리스코프(Barbara Liskov). 1988
‘하위 호환성’ - DirectXdll이 바뀌어도 문제가 없다
LSP 위반 사례void DrawShape(const Shape& s) {	if (typeid(s) == typeid(Square))DrawSquare((Square&)s));	else if (typeid(s) == typeid(Circle))DrawCircle((Circle&)s);}
LSP(교체가능) 위반 사례void Actor::Attack(Actor& target, int damage) {	if (target.IsPc()) {target.CastPc().SendPacket(“Attacked”, damage);	} else if (target.IsNpc()) {target.CastNpc().SendEvent(“Attacked”, damage);	}}void Actor::Skill(Actor& target, int s) {	if (target.IsPc()) {target.CastPc().SendPacket(“Skilled”, s);	} else if (target.IsNpc()) {target.CastNpc().SendEvent(“Skilled”, s);	}}
LSP(교체가능) 위반 사례OCP(개방폐쇄)도 위반!void Actor::Attack(Actor& target, int damage) {	if (target.IsPc()) {target.CastPc().SendPacket(“Attacked”, damage);	} else if (target.IsNpc()) {target.CastNpc().SendEvent(“Attacked”, damage);	}}void Actor::Skill(Actor& target, int s) {	if (target.IsPc()) {target.CastPc().SendPacket(“Skilled”, s);	} else if (target.IsNpc()) {target.CastNpc().SendEvent(“Skilled”, s);	}}Actor 자식 클래스에 Door 가 추가된다면?
LSP(교체가능) 만족void Actor::Attack(Actor& target, int damage) {target.Event(“Attacked”, damage);}void Actor::Skill(Actor& target, int s) {target.Event(“Skilled”, s);}virtual void Actor::Event(string& type, int n) = 0;void Pc::Event(string& type, int n) { SendPacket(type, n); }void Npc::Event(string& type, int n) { SendEvent(type, n); }void Door::Event(string& type, int n) { DoorEvent(type, n); }
직사각형을 상속받은 정사각형
직사각형을 상속받은 정사각형정사각형 is a 직사각형?
LSP(교체가능)를 만족시키려면
좀 더 실질적인 예제
좀 더 실질적인 예제bool Party::CanJoin(Pc& p) {	// do something	if (IsParty()) {		if (GetMember() < 12) {			return true;		}	} else {	// 혈맹이라면		if (GetMember() < 140) {	// do something
좀 더 실질적인 예제
왜 이런 일이?That’s not my job
LSP(교체가능) 정리concrete 클래스 자체에는 논리적 결함이 없어 보이더라도, 잘못 쓸 가능성이 있다면 문제가 있다수학에서는 (정사각형 is a 직사각형), 하지만 코드에서는 (정사각형 is not a 직사각형) 이 가능하다실보다 득이 많다면, LSP(교체가능)원칙이 깨지더라도 협약(convention)으로 해결할 수도 있다
stack(Java 와 C++)java.lang.Objectextended by java.util.AbstractCollectionextended by java.util.AbstractListextended by java.util.Vectorextended by java.util.Stacktemplate<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;};
SRP(Single Responsibility)단일 책임 원칙OCP(Open Close)개방-폐쇄 원칙LSP(Liskov Substitution)리스코프 교체 원칙ISP(Interface Segregation)인터페이스 격리 원칙DIP(Dependency Inversion)의존 관계 역전 원칙
ISP(Interface Segregation)인터페이스 격리 원칙
ISP - 인터페이스 격리 원칙
OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.
OOP 설계 원칙 S.O.L.I.D.
ISP - 인터페이스 격리 원칙
너무 많은 걸 알고 있는 인터페이스class Obj {	// 레퍼런스만 관리	virtual intAttack(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);
필요한 것만 알고 있는 인터페이스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);
ISP(인터페이스분리) 정리같은 로직이 반복되면 up-class 하고 싶겠지만 욕심내지 않는다코드 재사용은 상속 대신 포함(aggregation)으로CTimerObject대신 ITimerObject와 CTimerHandler활용상속은 코드 재사용보다는 OCP(개방폐쇄)나 LSP(교체가능), DIP(의존역전)를 위해 사용
SRP(Single Responsibility)단일 책임 원칙OCP(Open Close)개방-폐쇄 원칙LSP(Liskov Substitution)리스코프 교체 원칙ISP(Interface Segregation)인터페이스 격리 원칙DIP(Dependency Inversion)의존 관계 역전 원칙
DIP(Dependency Inversion)의존 관계 역전 원칙
DIP - 의존 관계 역전 원칙상위 수준 모듈이 하위 수준 모듈에 의존하면 안 된다추상(Abstraction) 에서 상세(Detail) 구현에 의존하면 안 된다
왜 의존 관계 역전인가?Button 은 Lamp 에의존관계다
DIP - 의존 관계 역전 원칙게임 엔진의 문제개발 도중, 엔진이 버전업 되었다면?interface 를 누가 결정하고 관리하는가?OS 업체?Printer 같은 주변기기 업체?
정리해 봅시다
OOP 설계 원칙 S.O.L.I.D.
SRP(Single Responsibility) 단일 책임클래스가 변경되는 이유는 유일해야 한다OCP(Open Close) 개방폐쇄 원칙확장에 대해 열려있고수정에 대해 닫혀있다LSP(Liskov Substitution) 리스코프 교체Base Class의 포인터나 참조값을 사용하는 코드에서는 실제로 어떤 클래스인지 몰라도 쓸 수 있어야 한다ISP(Interface Segregation) 인터페이스 격리클라이언트는 자신이 쓰지않는 인터페이스에 의존하지 않는다DIP(Dependency Inversion) 의존 관계 역전상위 모듈이 하위 모듈에게 의존하면 안 된다
비교해 봅시다
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);}
SRP(단일책임)여러 책임이 섞여 있는 클래스를 책임별 분리ISP(인터페이스분리)클라이언트가 클래스의 특정 기능만 이용한다면 그런 기능의 부분 집합을 별도 인터페이스로 추출
OCP(개방폐쇄)코드 추가만으로 기능 변경 가능한가DIP(의존역전)변경의 주체가 누구인가
현실은 시궁창// 에라 모르겠다// 해볼 수도 있겠으나 귀찮다. 일단 여기까지// 구현의 편의를 위해 이렇게 한다. 시간이 없거든// 작업중입니다T_T// 그래 나도 이러면 안되는 지 알어... 미안해...// 원래는 lock 걸어야 하지만 이 정도면 괜찮을 듯? 한 번이라도 죽으면 lock 걸자.07.10.xx// 죽었다. lock 쓰는 걸로 바꾼다. 07.12.xx// 사실 이렇게 짜면 안 되는데 이 클래스는 너무 고치기 무서워서 못 건드리겠음// 다시는 이런 일이 없어야 할 것임
현실은 시궁창당장 업데이트 해야 하는데 5대 법칙이 어쩌고 하면 혼날지도
그럼에도 불구하고
설계를 신경써야 한다
결론클래스를 만들때는 고객의 입장에서 생각할 것놀래키지 않는다구조를 잡을때는 신중하게실제로 써 본 뒤에 구조잡기안정화 단계란 영원히 오지 않을지도?안정된 코드는 오래된 코드언제가 “적당”한가?라이브러리보다는 비즈니스 layer 가 중요절대적인 법칙은 없다
Q & A
Reference실전 코드로 배우는 실용주의 디자인 패턴소프트웨어 개발의 지혜 - 야스미디어zdnet - 객체지향 SW 설계의 원칙http://www.zdnet.co.kr/ArticleView.asp?artice_id=00000039134727http://www.zdnet.co.kr/ArticleView.asp?artice_id=00000039135552http://www.zdnet.co.kr/ArticleView.asp?artice_id=00000039139151http://www.zdnet.co.kr/ArticleView.asp?artice_id=00000039137043http://www.objectmentor.com/resources/publishedArticles.html실용주의 디자인 패턴 0장애자일 프로그래밍 - 남기룡
사진높은 응집도, 낮은 결합도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_rightThat’s not my jobhttp://life-engineering.com/2008/04/28/thats-not-my-job/자동차 사고https://www.youngsamsung.com/pblog.do?cmd=view&seq=459&memId=4&categoryId=49내가 짰구나http://www.slideshare.net/wgshim/experience-report-agile-adoption-stories-in-lg-electronics

More Related Content

PDF
オブジェクト指向プログラミング入門 -- Java object-oriented programming primer
PDF
静的解析を使った開発ツールの開発
PDF
GoでMinecraftっぽいの作る
PPTX
Vertical Slicing Architectures
PDF
ソフトウェアの核心にある複雑さに立ち向かう
PDF
DDD 20121106 SEA Forum November
PPTX
Open Closed Principle kata
PPTX
C#とILとネイティブと
オブジェクト指向プログラミング入門 -- Java object-oriented programming primer
静的解析を使った開発ツールの開発
GoでMinecraftっぽいの作る
Vertical Slicing Architectures
ソフトウェアの核心にある複雑さに立ち向かう
DDD 20121106 SEA Forum November
Open Closed Principle kata
C#とILとネイティブと

What's hot (20)

PDF
ドメイン駆動設計という設計スタイル
PDF
2022/4/15_(DDD) Kotlin 1.5 で stable になった value class を深掘りする
PPTX
Database on Kubernetes - HA,Replication and more -
PDF
ドメイン駆動設計 分析しながら設計する
PDF
マイクロサービスバックエンドAPIのためのRESTとgRPC
PPTX
PDF
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
PDF
GitHubにバグ報告して賞金$500を頂いた話
PPTX
ドメイン駆動設計の学習曲線とブレークポイント
PDF
INTRODUCTION TO FLUTTER.pdf
PDF
Entity Framework(Core)についての概要を学ぼう
PPTX
Permission in Android Security: Threats and solution
PDF
ドメイン駆動設計の基礎知識:設計のスタイル、開発のスタイル
PDF
HTTP/2の現状とこれから
PPT
PDF
強いて言えば「集約どう実装するのかな、を考える」な話
PDF
From Generator to Fiber the Road to Coroutine in PHP
PPTX
Dangling DNS records takeover at scale
PPTX
Domain Driven Design Ch7
PPTX
fetch APIを安全に使う方法をおさらいしてみよう
ドメイン駆動設計という設計スタイル
2022/4/15_(DDD) Kotlin 1.5 で stable になった value class を深掘りする
Database on Kubernetes - HA,Replication and more -
ドメイン駆動設計 分析しながら設計する
マイクロサービスバックエンドAPIのためのRESTとgRPC
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
GitHubにバグ報告して賞金$500を頂いた話
ドメイン駆動設計の学習曲線とブレークポイント
INTRODUCTION TO FLUTTER.pdf
Entity Framework(Core)についての概要を学ぼう
Permission in Android Security: Threats and solution
ドメイン駆動設計の基礎知識:設計のスタイル、開発のスタイル
HTTP/2の現状とこれから
強いて言えば「集約どう実装するのかな、を考える」な話
From Generator to Fiber the Road to Coroutine in PHP
Dangling DNS records takeover at scale
Domain Driven Design Ch7
fetch APIを安全に使う方法をおさらいしてみよう
Ad

Viewers also liked (6)

PPTX
프로그램은 왜 실패하는가 1장
PDF
Srijan's Agile & Lean Software Development Philosophy
PDF
스프링 시큐리티 구조 이해
PDF
Spring Boot 소개
PPTX
테스트 자동화와 TDD(테스트 주도 개발방법론)
PDF
카카오스토리 웹팀의 코드리뷰 경험
프로그램은 왜 실패하는가 1장
Srijan's Agile & Lean Software Development Philosophy
스프링 시큐리티 구조 이해
Spring Boot 소개
테스트 자동화와 TDD(테스트 주도 개발방법론)
카카오스토리 웹팀의 코드리뷰 경험
Ad

Similar to OOP 설계 원칙 S.O.L.I.D. (20)

PDF
Oop design principle SOLID
PDF
Oop design principle
PPTX
Learn design pattern-1
PDF
스프링 코어 강의 1부 - 봄 맞이 준비 운동
PPT
Responding to change
PPTX
[HaU] 신입 기술 면접 준비 java
PDF
C++ api design 품질
PDF
R2서버정진욱
PDF
Zeppelin(Spark)으로 데이터 분석하기
PPT
PL/SQL - 10g Release1
PPTX
[Dev rookie]designpattern
PDF
ES6 for Node.js Study
PPTX
Assembly 스터디 2
 
PPTX
ES2015 훑어보기 for Django Girls Seoul
PPT
카사 공개세미나1회 W.E.L.C.
PDF
Deep dive functional thinking
PPTX
클로저 1
PPTX
About Visual C++ 10
PDF
Introduction to Fork Join Framework_SYS4U I&C
PPTX
javascript01
Oop design principle SOLID
Oop design principle
Learn design pattern-1
스프링 코어 강의 1부 - 봄 맞이 준비 운동
Responding to change
[HaU] 신입 기술 면접 준비 java
C++ api design 품질
R2서버정진욱
Zeppelin(Spark)으로 데이터 분석하기
PL/SQL - 10g Release1
[Dev rookie]designpattern
ES6 for Node.js Study
Assembly 스터디 2
 
ES2015 훑어보기 for Django Girls Seoul
카사 공개세미나1회 W.E.L.C.
Deep dive functional thinking
클로저 1
About Visual C++ 10
Introduction to Fork Join Framework_SYS4U I&C
javascript01

More from Ryan Park (20)

PPTX
위대한 게임개발팀의 공통점
PPTX
Taocp1 2 4
PPTX
즉흥연기와프로그래밍
PDF
KGC2010 - 낡은 코드에 단위테스트 넣기
PPTX
Unicode 이해하기
PDF
Unicode100
PPTX
Unicode
PPTX
Unicode
PPTX
Unicode
PPTX
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
PPTX
나도기술서번역한번해볼까 in NDC10
PPTX
나도(기술서)번역한번해볼까
PPTX
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
PPTX
Programming Game AI by Example. Ch7. Raven
PPTX
AIbyExample - Ch7 raven. version 0.8
PPTX
온라인 게임에서 사례로 살펴보는 디버깅
PPT
Working Effectively With Legacy Code - xp2005
PDF
UnitTest, Tdd For Games Kgc2007 ParkPD
PPT
Agile Test Driven Development For Games What, Why, And How
PPT
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...
위대한 게임개발팀의 공통점
Taocp1 2 4
즉흥연기와프로그래밍
KGC2010 - 낡은 코드에 단위테스트 넣기
Unicode 이해하기
Unicode100
Unicode
Unicode
Unicode
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
나도기술서번역한번해볼까 in NDC10
나도(기술서)번역한번해볼까
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
Programming Game AI by Example. Ch7. Raven
AIbyExample - Ch7 raven. version 0.8
온라인 게임에서 사례로 살펴보는 디버깅
Working Effectively With Legacy Code - xp2005
UnitTest, Tdd For Games Kgc2007 ParkPD
Agile Test Driven Development For Games What, Why, And How
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...

OOP 설계 원칙 S.O.L.I.D.

  • 2. OOP 설계 원칙S.O.L.I.D.이러다가 v.10.0 까지 나올 기세v.2.5NCsoft박일http://parkpd.egloos.com
  • 3. 강사 소개KGC 07 게임에 적용해 보는 TDDKGC 08, NCDC 09 Lineage2 Production SystemKGC 09, NDC 10 사례로 살펴보는 디버깅KGC 10 낡은 코드에 테스트 코드 넣기
  • 4. 잠깐만 UML 을 배웁시다
  • 5. 잠깐만 UML 을 배웁시다
  • 6. 잠깐만 UML 을 배웁시다
  • 7. 잠깐만 UML 을 배웁시다
  • 8. 대원칙 - 높은 응집도, 낮은 결합도응집도 : 하나의 클래스가 하나의 기능(책임)을 온전히 순도 높게 담당하는 정도결합도 : 클래스간의 서로 다른 책임들이 얽혀 있어서 상호의존도가 높은 정도
  • 9. SRP(Single Responsibility)단일 책임 원칙OCP(Open Close)개방-폐쇄 원칙LSP(Liskov Substitution)리스코프 교체 원칙ISP(Interface Segregation)인터페이스 격리 원칙DIP(Dependency Inversion)의존 관계 역전 원칙
  • 10. SRP(Single Responsibility)단일 책임 원칙OCP(Open Close)개방-폐쇄 원칙LSP(Liskov Substitution)리스코프 교체 원칙ISP(Interface Segregation)인터페이스 격리 원칙DIP(Dependency Inversion)의존 관계 역전 원칙
  • 12. SRP : 단일 책임 원칙한 클래스는 하나의 역할만 맡는다클래스가 변경되는 이유는 유일해야 한다
  • 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 들
  • 25. interface(표준)의 문제점변경 비용이 비싸다interface 가 변경되면 모든 구현 클래스에서 컴파일 에러 발생concrete class 이 뭔지 알기 어렵다BlueRayvs 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
  • 29. ‘하위 호환성’ - DirectXdll이 바뀌어도 문제가 없다
  • 30. LSP 위반 사례void DrawShape(const Shape& s) { if (typeid(s) == typeid(Square))DrawSquare((Square&)s)); else if (typeid(s) == typeid(Circle))DrawCircle((Circle&)s);}
  • 31. LSP(교체가능) 위반 사례void Actor::Attack(Actor& target, int damage) { if (target.IsPc()) {target.CastPc().SendPacket(“Attacked”, damage); } else if (target.IsNpc()) {target.CastNpc().SendEvent(“Attacked”, damage); }}void Actor::Skill(Actor& target, int s) { if (target.IsPc()) {target.CastPc().SendPacket(“Skilled”, s); } else if (target.IsNpc()) {target.CastNpc().SendEvent(“Skilled”, s); }}
  • 32. LSP(교체가능) 위반 사례OCP(개방폐쇄)도 위반!void Actor::Attack(Actor& target, int damage) { if (target.IsPc()) {target.CastPc().SendPacket(“Attacked”, damage); } else if (target.IsNpc()) {target.CastNpc().SendEvent(“Attacked”, damage); }}void Actor::Skill(Actor& target, int s) { if (target.IsPc()) {target.CastPc().SendPacket(“Skilled”, s); } else if (target.IsNpc()) {target.CastNpc().SendEvent(“Skilled”, s); }}Actor 자식 클래스에 Door 가 추가된다면?
  • 33. LSP(교체가능) 만족void Actor::Attack(Actor& target, int damage) {target.Event(“Attacked”, damage);}void Actor::Skill(Actor& target, int s) {target.Event(“Skilled”, s);}virtual void Actor::Event(string& type, int n) = 0;void Pc::Event(string& type, int n) { SendPacket(type, n); }void Npc::Event(string& type, int n) { SendEvent(type, n); }void Door::Event(string& type, int n) { DoorEvent(type, n); }
  • 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.Objectextended by java.util.AbstractCollectionextended by java.util.AbstractListextended by java.util.Vectorextended by java.util.Stacktemplate<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)의존 관계 역전 원칙
  • 45. ISP - 인터페이스 격리 원칙
  • 49. ISP - 인터페이스 격리 원칙
  • 50. 너무 많은 걸 알고 있는 인터페이스class Obj { // 레퍼런스만 관리 virtual intAttack(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)의존 관계 역전 원칙
  • 55. DIP - 의존 관계 역전 원칙상위 수준 모듈이 하위 수준 모듈에 의존하면 안 된다추상(Abstraction) 에서 상세(Detail) 구현에 의존하면 안 된다
  • 56. 왜 의존 관계 역전인가?Button 은 Lamp 에의존관계다
  • 57. DIP - 의존 관계 역전 원칙게임 엔진의 문제개발 도중, 엔진이 버전업 되었다면?interface 를 누가 결정하고 관리하는가?OS 업체?Printer 같은 주변기기 업체?
  • 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// 사실 이렇게 짜면 안 되는데 이 클래스는 너무 고치기 무서워서 못 건드리겠음// 다시는 이런 일이 없어야 할 것임
  • 66. 현실은 시궁창당장 업데이트 해야 하는데 5대 법칙이 어쩌고 하면 혼날지도
  • 69. 결론클래스를 만들때는 고객의 입장에서 생각할 것놀래키지 않는다구조를 잡을때는 신중하게실제로 써 본 뒤에 구조잡기안정화 단계란 영원히 오지 않을지도?안정된 코드는 오래된 코드언제가 “적당”한가?라이브러리보다는 비즈니스 layer 가 중요절대적인 법칙은 없다
  • 70. Q & A
  • 71. Reference실전 코드로 배우는 실용주의 디자인 패턴소프트웨어 개발의 지혜 - 야스미디어zdnet - 객체지향 SW 설계의 원칙http://www.zdnet.co.kr/ArticleView.asp?artice_id=00000039134727http://www.zdnet.co.kr/ArticleView.asp?artice_id=00000039135552http://www.zdnet.co.kr/ArticleView.asp?artice_id=00000039139151http://www.zdnet.co.kr/ArticleView.asp?artice_id=00000039137043http://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_rightThat’s not my jobhttp://life-engineering.com/2008/04/28/thats-not-my-job/자동차 사고https://www.youngsamsung.com/pblog.do?cmd=view&seq=459&memId=4&categoryId=49내가 짰구나http://www.slideshare.net/wgshim/experience-report-agile-adoption-stories-in-lg-electronics