refactoring to patterns 이동현

37
REFACTORING TO PATTERNS 이이이 아.아.아 Annual Summary 2008

Upload: kaoru

Post on 25-Feb-2016

73 views

Category:

Documents


0 download

DESCRIPTION

아 . 꿈 . 사 Annual Summary 2008. Refactoring To Patterns 이동현. Refactoring. Patterns. XP. 이 책은 . XP 에서 왜 패턴을 언급 하지 않는가 ? 마틴 파울러는 그의 저서에서 패턴을 고려한 리팩토링은 몇 가지 안 되었고 , 누군가 더 많은 패턴을 고려한 리팩토링을 써 주길 바랬다 . 좀 더 실용적인 예제가 필요했다 . Standing on the Shoulders of Giants. 일반적으로 . 패턴을 공부했다 . - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Refactoring To  Patterns 이동현

REFACTORING TO PATTERNS

이동현

아 . 꿈 . 사Annual Summary 2008

Page 2: Refactoring To  Patterns 이동현
Page 3: Refactoring To  Patterns 이동현

XP

Refactor-ingPatterns

Page 4: Refactoring To  Patterns 이동현

이 책은 ..

XP 에서 왜 패턴을 언급 하지 않는가 ? 마틴 파울러는 그의 저서에서 패턴을 고려한 리팩토링은 몇 가지 안 되었고 ,

누군가 더 많은 패턴을 고려한 리팩토링을 써 주길 바랬다 . 좀 더 실용적인 예제가 필요했다 .

Page 5: Refactoring To  Patterns 이동현

Standing on the Shoulders of Giants

Page 6: Refactoring To  Patterns 이동현

일반적으로 ..

패턴을 공부했다 . 패턴은 많은 유용한 디자인 아이디어 전달 . 몇 가지 패턴 습득 후 . 스스로 좋은 소프트웨어 디자이너로 생각되어 흡족하다 . 그러나 .. 가끔 over-engineering 에 ..

경험이 쌓여 스킬이 늘어 나의 스타일에 변화가 생겼다 . XP 의 수용으로 과도한 up-front 디자인의 자제 .

Page 7: Refactoring To  Patterns 이동현

이 책을 쓴 이유

Over-Engineering Under-Engineering The Pattern Panacea Test Driven Development and Continuous Refactoring Refactoring and Patterns Evolutionary Design

Page 8: Refactoring To  Patterns 이동현

Over-Engineering

시스템의 미래의 요구사항을 알고 있다는 착각의 발현 . 예측이 틀리면 ? -> 모든 게 낭비 . 결과로 불필요한 복잡성의 증가와 부정적 side-effect. 아주 조용하게 일어난다 .

Page 9: Refactoring To  Patterns 이동현

Under-Engineering

Poor Design 시간이 없다 .. 빨리 빨리 .. 그래서 .. 좋은 디자인이 뭐야 ? 부족한 실력 .. 새로운 기능을 빨리 보고싶다 . 한번에 여러 프로젝트 참여 . 결국 ..

Fast, slow, slower 리듬으로 귀결 .

Page 10: Refactoring To  Patterns 이동현

The Pattern Panacea

닭 잡는데 소 잡는 칼 쓰기 .. 패턴 중독 .. 디자인 패턴은 만병통치약이 아니다 . 진정으로 더 나아가기 위해서는 패턴에 대한 맹신을 접어라 .

Page 12: Refactoring To  Patterns 이동현

Refactoring and Patterns

마틴의 리팩토링을 적용하면서 디자인 개선에 패턴이 도움이 되는걸 발견했다 . 디자인 패턴만 공부하면 원래의 핵심인 동기에 대한 부분을 놓치기 쉽다 . - In-

tent 에 집중하게 된다 . Applicability section 이라도 자세히 봤다면 ..

Our design patterns capture many of the structures that result from refactoring...Design patterns thus provide targets for your refactoring. [DP, 354]

There is a natural relation between patterns and refactorings. Patterns are whereyou want to be; refactorings are ways to get there from somewhere else. [F,107]

Page 13: Refactoring To  Patterns 이동현

Evolutionary Design

조상으로부터 물려받은 것이 있거든 그것을 얻되 네 것이 되게 하라 . - Goethe

결과 보다는 과정을 공부하는 것이 중요하다 .진짜 지혜는 그 과정 속에 숨어 있다 .

패턴을 리팩터링과 별개로 생각 하지 말고 ,리팩터링의 문맥에서 바라보라 .

Page 14: Refactoring To  Patterns 이동현

Refactoring

새로운 코드를 더 쉽게 추가할 수 있도록 하기 위해 . 기존 코드의 설계를 개선하기 위해 . 기존 코드를 더 잘 이해하기 위해 . 덜 짜증나는 코드로 만들기 위해 . 많은 눈 .

John Thompson 씨의 모자가게

깨진 창문 . 작은 단계 .

점심도 못 먹고 한 리팩터링 . 설계 부채 .

이걸로 관리자를 설득 하라 .

Page 15: Refactoring To  Patterns 이동현

Patterns

패턴 목표 패턴 지향 패턴 제거

Page 16: Refactoring To  Patterns 이동현

Code Smells

설계 문제 중복된 코드 코드의 의미가 불명확 함 코드가 복잡하다 .

이런 것들은 구체적인 가이드 라인이 되기엔 너무 추상적이다 . 구체적인 기준 제시 .

Page 17: Refactoring To  Patterns 이동현

Catalog of Code Smells Duplicated Code Long Method Conditional Complexity Primitive Obsession Indecent Exposure Solution Sprawl Alternative Classes with Different Interfaces Lazy Class Large Class Switch Statements Combinational Explosion Oddball Solution

Page 18: Refactoring To  Patterns 이동현

Alternative Classes with Different Interfaces Unify Interfaces with Adapter( 247 ) .Combinatorial Explosion Replace Implicit Language with Interpreter(269) Conditional Complexity Replace Conditional Logic with Strategy(129) Move Embellishment to Decorator(144) Replace State-Altering Conditionals with State(166) Introduce Null Object(301) Duplicated Code Form Template Method(205) Introduce Polymorphic Creation with Factory Method(88) Chain Constructors(340) Replace One/Many Distinctions with Composite(224) Extract Composite(214) Unify Interface with Adapter(247) Introduce Null Object(301)Indecent Exposure Encapsulate Classes with Factory(80)Large Class Replace Conditional Dispatcher with Command(191) Replace State-Altering Conditionals with State(166) Replace Implicit Language with Interpreter(269)

Lazy ClassInline Singleton(114)Long MethodCompose Method(123) Move Accumulation to Collection Parameter(313) Replace Conditional Dispatcher with Command(191) Move Accumulation to Visitor(320) Replace Conditional Logic with Strategy(129)Oddball SolutionUnify Interfaces with Adapter(247)Primitive Obsession Replace Type Code with Class(286) Replace Sate-Altering Conditionals with State(166) Replace Conditional Logic with Strategy(129) Replace Implicit Tree with Composite(178) Replace Implicit Language with Interpreter(269) Move Embellishment to Decorator(144) Encapsulate Composite with Builder(96) Solution SprawlMove Creation Knowledge to Factory(68)Switch StatementsReplace Conditional Dispatcher with Command(191) Move Accumulation to Visitor(320)

Page 19: Refactoring To  Patterns 이동현

리팩터링 형식

States Pattern Name and Intent Gives an application example Discusses motivation Benefits and Liabilities Mechanics

Specific things to do Presents detailed example

Page 20: Refactoring To  Patterns 이동현

Replace Constructors with Creation Methods

Page 21: Refactoring To  Patterns 이동현

요약 어떤 클래스의 인스턴스를 생성할 때 그것이 제공하는 여러 생성자 중 어떤 것을

호출해야 할지 결정하기 어렵다 .

인스턴스를 생성해 리턴하는 생성 메서드로 각 생성자를 대체하여 그 용도가 명확하게 드러나도록 한다 .

Page 22: Refactoring To  Patterns 이동현

동기

생성자가 많으면 그 자체만 보고 용도를 파악하기 어렵다 . 생성자가 많을 수록 , 프로그래머가 잘못 선택할 확률도 높아진다 . 어떤 생성자를 사용할지 고민하면 개발이 늦어진다 . 생성 메서드를 사용해서 이러한 문제점을 제거한다 . Extract Class , Extract Subclass 리팩터링을 먼저 고려 .

Page 23: Refactoring To  Patterns 이동현

장점과 단점

+ 상태 전이 로직을 줄이거나 없앨 수 있다 .+ 복잡한 상태 전이 로직이 단순해 진다 .+ 상태 전이 로직을 더 쉽게 알아볼 수 있게 된다 .- 원래의 상태 전이 로직이 이해하기에 별로 복잡하지 않다면 , 괜히 디자인만

복잡하게 만드는 것이다 .

Page 24: Refactoring To  Patterns 이동현

절차

….

Page 25: Refactoring To  Patterns 이동현

예제 public class Loan {

public Load( double commitment, int riskRating, Date maturity){

this(commitment, 0.00, riskRating, maturity, null);}

public Load( double commitment, int riskRating, Date maturity, Date expiry ){

this(commitment, 0.00, riskRating, maturity, expiry );}

public Load( double commitment, double outstanding, int riskRating, Date maturity, Date expiry){

this(null, commitment, outstanding, riskRating, maturity, expiry );}

public Load( CapitalStrategy capitalStrategy, double commitment,int riskRating, Date maturity, Date expiry)

{ this( capitalStrategy, commitment, 0.0, riskRating, maturity, expiry );}

public Load( CapitalStrategy capitalStrategy, double commitment,double outstanding, int riskRating,Date maturity, Date expiry ){

this.commitment = commitment;this.outstanding = outstanding;this.riskRating = riskRating;this.maturity = maturity;this.expiry = expiry;this.capitalStrategy = captialStrategy;

if(capitalStrategy == null ){

if( expiry == null )this.capitalStrategy = new CapitalStrategyTermLoan();

else if( maturity == null )this.capitalStrategy = new CapitalStrategyRevolver();

elsethis.capitalStrategy = new CapitalStrategyRCTL();

}}

}

Page 26: Refactoring To  Patterns 이동현

1. Load 생성자를 하나 고르고 이 생성자를 사용하는 클라이언트 코드를 찾는다 .

public class CapitalCalculationTests... public void testTermLoanNoPayments()

{...Loan temLoadn = new Loan(commitment, riskRating, maturity);...

}

Page 27: Refactoring To  Patterns 이동현

2. Extract Method 리팩터링을 적용해 CreateTermLoan 이라는 public 메서드를 만든다 .

public class CapitalCalculationTests...public void testTermLoanNoPayments()

{//...Loan temLoadn = createTermLoan(commitment, riskRating, maturity);//...

}

public class CapitalCalculationTests... public void testTermLoanNoPayments()

{...Loan temLoadn = new Loan(commitment, riskRating, maturity);...

}

public Loan createTermLoan(double commitment, int riskRating, Date maturity) {

return new Loan(commitment, riskRating, maturity);}

Extract Method

Page 28: Refactoring To  Patterns 이동현

3. Move Method 리팩터링을 적용해 생성 메서드 cre-ateTermLoan() 을 Loan 클래스로 옮긴다 .

public class Loanpublic static Loan createTermLoan(double commitment, int riskRating, Date maturity)

{return new Loan(commitment, riskRating, maturity);

}

public class CapitalCalculationTests...public void testTermLoanNoPayments()

{//...Loan temLoadn = createTermLoan(commitment, riskRating, maturity);//...

} public Loan createTermLoan(double commitment, int riskRating, Date maturity) {

return new Loan(commitment, riskRating, maturity);}

Move Method

Page 29: Refactoring To  Patterns 이동현

4. 선택한 생성자를 사용하는 모든 클라이언트 코드를 수정한다 .

public class CapitalCalculationTests...public void testTermLoanNoPayments(){

//...Loan temLoadn = Loan.createTermLoan(commitment, riskRating, maturity);//...}

}

Page 30: Refactoring To  Patterns 이동현

5. 이제 선택한 생성자를 사용하는 곳은 CreateTermLoan 뿐이다 .

Inline method 를 적용해 생성자 호출 부분을 제거한다 .

public class Loanpublic Loan(double commitment, int riskRating, Date maturity){

this(commitment, 0.00, riskRating, maturity, null)}

public static Loan createTermLoan(double commitment, int riskRating, Date maturity) {return new Loan(commitment, 0.00, riskRating, maturity, null);

}

Page 31: Refactoring To  Patterns 이동현

6. 다른 생성자에 대해서도 1-5 과정을 반복한다 .

Page 32: Refactoring To  Patterns 이동현

Replace Implicit Language with Interpreter 한 클래스 내의 여러 메서드에서 일종의 묵시적 언어를 이루는 요소들을

조합하고 있다면 . 그 묵시적 언어의 요소들을 각각의 클래스로 정의하고 그 객체의 조합을 통해

해석 가능한 수식을 만들어 낼 수 있도록 한다 .

Page 33: Refactoring To  Patterns 이동현
Page 34: Refactoring To  Patterns 이동현

묵시적 언어

10 달러 이하의 상품을 찾아라 . 흰색이 아니고 10 달러 이하인 상품을 찾아라 . 파란색이고 작으며 20 달러 이하인 상품을 찾아라 .

ProductFinder… public List byColor(..); … public List belowPriceAvoidingAColor(float price, Color color); public List byColorAndBelowPrice(Color color, float price); public List byColorSizeAndBelowPrice(…)

Page 35: Refactoring To  Patterns 이동현

Interpreter

belowPriceAvoidingAColor…

and

Price < target price not

Color == target color

AndSpec spec = new AndSpec( new BelowPriceSpec(price), new NotSpec( new ColorSpec(color) ));

Page 36: Refactoring To  Patterns 이동현

Q&A

Page 37: Refactoring To  Patterns 이동현

새해 복 많이 받으세요 .