refactoring 메소드 호출의 단순화

20
Refactoring 메소드 호출의 단순화 cecil

Upload: hyeonseok-choi

Post on 20-May-2015

229 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Refactoring 메소드 호출의 단순화

Refactoring����������� ������������������  메소드����������� ������������������  호출의����������� ������������������  단순화

cecil

Page 2: Refactoring 메소드 호출의 단순화

Contents

•메소드를����������� ������������������  직관적으로����������� ������������������  •파라미터����������� ������������������  갯수의����������� ������������������  조정����������� ������������������  •불필요한����������� ������������������  정보를����������� ������������������  숨김����������� ������������������  •생성자를����������� ������������������  팩토리����������� ������������������  메소드로����������� ������������������  •메소드의����������� ������������������  예외����������� ������������������  선언

Page 3: Refactoring 메소드 호출의 단순화

메소드를����������� ������������������  직관적으로����������� ������������������  (기본적인����������� ������������������  리팩토링)

•Rename����������� ������������������  Method����������� ������������������  • 메소드의����������� ������������������  이름이����������� ������������������  그����������� ������������������  목적을����������� ������������������  드러내지����������� ������������������  못하면����������� ������������������  이름을����������� ������������������  바꿔라����������� ������������������  

•Add����������� ������������������  Parameter����������� ������������������  • 메소드를����������� ������������������  호출하는����������� ������������������  부분에서����������� ������������������  더����������� ������������������  많은����������� ������������������  정보를����������� ������������������  필요로����������� ������������������  한다면����������� ������������������  파라미터를����������� ������������������  추가하라����������� ������������������  • 이����������� ������������������  리팩토링을����������� ������������������  하지����������� ������������������  않도록����������� ������������������  하는����������� ������������������  것이����������� ������������������  중요(대안:����������� ������������������  파라미터����������� ������������������  오브젝트����������� ������������������  도입)����������� ������������������  

•Remove����������� ������������������  Parameter����������� ������������������  •파라미터가����������� ������������������  메소드에서����������� ������������������  더����������� ������������������  이상����������� ������������������  사용되지����������� ������������������  않으면����������� ������������������  제거하라

Page 4: Refactoring 메소드 호출의 단순화

파라미터����������� ������������������  갯수����������� ������������������  조정을����������� ������������������  위한����������� ������������������  리팩토링

많은����������� ������������������  수의����������� ������������������  파라미터는����������� ������������������  메소드를����������� ������������������  복잡하게����������� ������������������  만든다

Page 5: Refactoring 메소드 호출의 단순화

Separate����������� ������������������  Query����������� ������������������  from����������� ������������������  Modifier

Customer

getTotalOutstanding����������� ������������������  setReadyForSummaries

Customer

getTotalOutstandingAndSetReadyForSummaries

값을����������� ������������������  리턴할����������� ������������������  뿐만����������� ������������������  아니라����������� ������������������  상태도����������� ������������������  변경하는����������� ������������������  메소드는����������� ������������������  분리하라

값을����������� ������������������  리턴하고,����������� ������������������  눈에����������� ������������������  띄눈����������� ������������������  부작용이����������� ������������������  없는����������� ������������������  것은����������� ������������������  매우����������� ������������������  가치����������� ������������������  있는����������� ������������������  일����������� ������������������  예외)����������� ������������������  동시성����������� ������������������  문제:����������� ������������������  동시성이����������� ������������������  문제가����������� ������������������  될����������� ������������������  경우����������� ������������������  getAndSet����������� ������������������  메소드를����������� ������������������  가질����������� ������������������  필요가����������� ������������������  있음.

Page 6: Refactoring 메소드 호출의 단순화

Parameterize����������� ������������������  Method

몇몇����������� ������������������  메소드가����������� ������������������  다른����������� ������������������  값을����������� ������������������  포함하고����������� ������������������  있는����������� ������������������  것을����������� ������������������  제외하고는����������� ������������������  비슷한����������� ������������������  일을����������� ������������������  하고����������� ������������������  있다면,����������� ������������������  ����������� ������������������  파라미터를����������� ������������������  가진����������� ������������������  하나의����������� ������������������  메소드로����������� ������������������  만들어라

Employee

fivePercentRaise����������� ������������������  tenPercentRaise

Employee

raise(percentage)

Page 7: Refactoring 메소드 호출의 단순화

Parameterize����������� ������������������  Method����������� ������������������  (cont’d)

공통된����������� ������������������  부분이����������� ������������������  덜����������� ������������������  명확하게����������� ������������������  나타나는����������� ������������������  경우����������� ������������������  파라미터로����������� ������������������  넘겨����������� ������������������  받을����������� ������������������  수����������� ������������������  잇는����������� ������������������  몇개의����������� ������������������  값을����������� ������������������  기초로����������� ������������������  반복되는����������� ������������������  코드를����������� ������������������  찾아라!

protected����������� ������������������  Dollars����������� ������������������  baseCharge()����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   double����������� ������������������  result����������� ������������������  =����������� ������������������  Math.min(lastUsage(),100)����������� ������������������  *����������� ������������������  0.03;����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������   if����������� ������������������  (lastUsage()����������� ������������������  >����������� ������������������  100)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������   result����������� ������������������  +=����������� ������������������  (Math.min����������� ������������������  (lastUsage(),200)����������� ������������������  -����������� ������������������  100)����������� ������������������  *����������� ������������������  0.05;����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  

����������� ������������������   ����������� ������������������   }����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  if����������� ������������������  (lastUsage()����������� ������������������  >����������� ������������������  200)����������� ������������������  {����������� ������������������   result����������� ������������������  +=����������� ������������������  (lastUsage()����������� ������������������  -����������� ������������������  200)����������� ������������������  *����������� ������������������  0.07;����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  }return����������� ������������������  new����������� ������������������  Dollars����������� ������������������  (result);����������� ������������������  ����������� ������������������  

}����������� ������������������  

protected����������� ������������������  Dollars����������� ������������������  baseCharge()����������� ������������������  { double����������� ������������������  result����������� ������������������  =����������� ������������������  usageInRange(0,����������� ������������������  100)����������� ������������������  *����������� ������������������  0.03;result����������� ������������������  +=����������� ������������������  usageInRange����������� ������������������  (100,200)����������� ������������������  *����������� ������������������  0.05;result����������� ������������������  +=����������� ������������������  usageInRange����������� ������������������  (200,����������� ������������������  Integer.MAX_VALUE)����������� ������������������  *����������� ������������������  0.07;����������� ������������������  ����������� ������������������  

����������� ������������������   return����������� ������������������  new����������� ������������������  Dollars����������� ������������������  (result);����������� ������������������  ����������� ������������������  }����������� ������������������  protected����������� ������������������  int����������� ������������������  usageInRange(int����������� ������������������  start,����������� ������������������  int����������� ������������������  end)����������� ������������������  {����������� ������������������   if����������� ������������������  (lastUsage()����������� ������������������  >����������� ������������������  start)����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  Math.min(lastUsage(),end)����������� ������������������  -����������� ������������������  start;����������� ������������������   else����������� ������������������  return����������� ������������������  0;����������� ������������������  }����������� ������������������  

Page 8: Refactoring 메소드 호출의 단순화

Replace����������� ������������������  Parameter����������� ������������������  with����������� ������������������  Explicit����������� ������������������  Method

파라미터의����������� ������������������  값에����������� ������������������  따라����������� ������������������  다른����������� ������������������  코드를����������� ������������������  실행하는����������� ������������������  메소드가����������� ������������������  있다면,����������� ������������������  파라미터����������� ������������������  값에����������� ������������������  대한����������� ������������������  별도의����������� ������������������  메소드를����������� ������������������  만들어라void����������� ������������������  setValue����������� ������������������  (String����������� ������������������  name,����������� ������������������  int����������� ������������������  value)����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������   if����������� ������������������  (name.equals("height"))����������� ������������������  ����������� ������������������   ����������� ������������������   _height����������� ������������������  =����������� ������������������  value;����������� ������������������   if����������� ������������������  (name.equals("width"))����������� ������������������  ����������� ������������������   ����������� ������������������   _width����������� ������������������  =����������� ������������������  value;����������� ������������������  ����������� ������������������  ����������� ������������������   Assert.shouldNeverReachHere();����������� ������������������  }

void����������� ������������������  setHeight(int����������� ������������������  arg)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������  _height����������� ������������������  =����������� ������������������  arg;����������� ������������������  }void����������� ������������������  setWidth����������� ������������������  (int����������� ������������������  arg)����������� ������������������  {����������� ������������������  ����������� ������������������   _width����������� ������������������  =����������� ������������������  arg;����������� ������������������  ����������� ������������������  }

장점:����������� ������������������  조건에����������� ������������������  따른����������� ������������������  행동을����������� ������������������  피할����������� ������������������  뿐만����������� ������������������  아니라,����������� ������������������  컴파일����������� ������������������  타임에����������� ������������������  검사����������� ������������������  가능����������� ������������������  ����������� ������������������  ex)����������� ������������������  Switch.setState(true)����������� ������������������  ->����������� ������������������  Switch.beOn()����������� ������������������  파라미터����������� ������������������  값의����������� ������������������  변화가����������� ������������������  크다면,����������� ������������������  이����������� ������������������  리팩토링을����������� ������������������  적용하면����������� ������������������  안됨.

Page 9: Refactoring 메소드 호출의 단순화

Preserve����������� ������������������  Whole����������� ������������������  Object어떤����������� ������������������  객체에서����������� ������������������  여러개의����������� ������������������  값을����������� ������������������  얻은����������� ������������������  다음����������� ������������������  메소드를����������� ������������������  호출하면서����������� ������������������  파라미터로����������� ������������������  넘기고����������� ������������������  있다면,����������� ������������������  대신����������� ������������������  그����������� ������������������  객체를����������� ������������������  넘겨라

int����������� ������������������  low����������� ������������������  =����������� ������������������  daysTempRange().getLow();����������� ������������������  

int����������� ������������������  high����������� ������������������  =����������� ������������������  daysTempRange().getHigh();����������� ������������������  ����������� ������������������  

withinPlan����������� ������������������  =����������� ������������������  plan.withinRange(low,����������� ������������������  high);

withinPlan����������� ������������������  =����������� ������������������  plan.withinRange(daysTempRange());

장점:����������� ������������������  파라미터����������� ������������������  리스트����������� ������������������  변경에����������� ������������������  유연하게����������� ������������������  대처가����������� ������������������  가능,����������� ������������������  코드의����������� ������������������  가독성을����������� ������������������  높임.����������� ������������������  

단점:����������� ������������������  파라미터로����������� ������������������  넘겨진����������� ������������������  객체와����������� ������������������  호출된����������� ������������������  객체����������� ������������������  사이에����������� ������������������  종속성을����������� ������������������  생성����������� ������������������  

만약����������� ������������������  이����������� ������������������  리팩토링이����������� ������������������  종속성����������� ������������������  구조를����������� ������������������  나쁘면����������� ������������������  한다면����������� ������������������  사용하면����������� ������������������  안됨.

Page 10: Refactoring 메소드 호출의 단순화

Preserve����������� ������������������  Whole����������� ������������������  Object����������� ������������������  (Example)

class����������� ������������������  Room...boolean����������� ������������������  withinPlan(HeatingPlan����������� ������������������  plan)����������� ������������������  {����������� ������������������   ����������� ������������������   int����������� ������������������  low����������� ������������������  =����������� ������������������  daysTempRange().getLow();����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  

����������� ������������������   ����������� ������������������   ����������� ������������������   int����������� ������������������  high����������� ������������������  =����������� ������������������  daysTempRange().getHigh();����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   return����������� ������������������  plan.withinRange(low,����������� ������������������  high);����������� ������������������   ����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  

}����������� ������������������  ����������� ������������������  !class����������� ������������������  HeatingPlan...����������� ������������������  

boolean����������� ������������������  withinRange����������� ������������������  (int����������� ������������������  low,����������� ������������������  int����������� ������������������  high)����������� ������������������  { ����������� ������������������   return����������� ������������������  (low����������� ������������������  >=����������� ������������������  _range.getLow()����������� ������������������  &&����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  

����������� ������������������   ����������� ������������������   ����������� ������������������   ����������� ������������������   ����������� ������������������   high����������� ������������������  <=����������� ������������������  _range.getHigh());����������� ������������������   ����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  }private����������� ������������������  TempRange����������� ������������������  _range;����������� ������������������  ����������� ������������������  

class����������� ������������������  Room...����������� ������������������  ����������� ������������������   boolean����������� ������������������  withinPlan(HeatingPlan����������� ������������������  plan)����������� ������������������  {����������� ������������������   ����������� ������������������   return����������� ������������������  plan.withinRange(daysTempRange());����������� ������������������  ����������� ������������������   }����������� ������������������  !class����������� ������������������  HeatingPlan...����������� ������������������   boolean����������� ������������������  withinRange����������� ������������������  (TempRange����������� ������������������  roomRange)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  (roomRange.getLow()����������� ������������������  >=����������� ������������������  _range.getLow()����������� ������������������  &&����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   ����������� ������������������   roomRange.getHigh()����������� ������������������  <=����������� ������������������  _range.getHigh());����������� ������������������  ����������� ������������������   }

class����������� ������������������  HeatingPlan...����������� ������������������   boolean����������� ������������������  withinRange����������� ������������������  (TempRange����������� ������������������  roomRange)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  (_range.includes(roomRange));����������� ������������������  ����������� ������������������  ����������� ������������������   }����������� ������������������  !class����������� ������������������  TempRange...����������� ������������������   boolean����������� ������������������  includes����������� ������������������  (TempRange����������� ������������������  arg)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  arg.getLow()����������� ������������������  >=����������� ������������������  this.getLow()����������� ������������������  &&����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   arg.getHigh()����������� ������������������  <=����������� ������������������  this.getHigh();����������� ������������������  ����������� ������������������   }

Page 11: Refactoring 메소드 호출의 단순화

Replace����������� ������������������  Parameter����������� ������������������  with����������� ������������������  Method

객체가����������� ������������������  메소드를����������� ������������������  호출한����������� ������������������  결과를����������� ������������������  다른����������� ������������������  메소드에����������� ������������������  파라미터로����������� ������������������  넘기는����������� ������������������  상황에서,����������� ������������������  호출된����������� ������������������  메소드가����������� ������������������  이����������� ������������������  메소드를����������� ������������������  호출할����������� ������������������  수����������� ������������������  있다면,����������� ������������������  직접����������� ������������������  호출하도록����������� ������������������  변경

int����������� ������������������  basePrice����������� ������������������  =����������� ������������������  _quantity����������� ������������������  *����������� ������������������  _itemPrice; discountLevel����������� ������������������  =����������� ������������������  getDiscountLevel();double����������� ������������������  finalPrice����������� ������������������  =����������� ������������������  discountedPrice����������� ������������������  (basePrice,����������� ������������������  discountLevel);

int����������� ������������������  basePrice����������� ������������������  =����������� ������������������  _quantity����������� ������������������  *����������� ������������������  _itemPrice;double����������� ������������������  finalPrice����������� ������������������  =����������� ������������������  discountedPrice����������� ������������������  (basePrice);

파라미터는����������� ������������������  필요할����������� ������������������  때만����������� ������������������  사용하라.

Page 12: Refactoring 메소드 호출의 단순화

Replace����������� ������������������  Parameter����������� ������������������  with����������� ������������������  Method����������� ������������������  (Example)

public����������� ������������������  double����������� ������������������  getPrice()����������� ������������������  { int����������� ������������������  basePrice����������� ������������������  =����������� ������������������  _quantity����������� ������������������  *����������� ������������������  _itemPrice;int����������� ������������������  discountLevel;if����������� ������������������  (_quantity����������� ������������������  >����������� ������������������  100)����������� ������������������  discountLevel����������� ������������������  =����������� ������������������  2; else����������� ������������������  discountLevel����������� ������������������  =����������� ������������������  1;double����������� ������������������  finalPrice����������� ������������������  =����������� ������������������  discountedPrice����������� ������������������  (basePrice,����������� ������������������  discountLevel);����������� ������������������  ����������� ������������������  

����������� ������������������   ����������� ������������������   return����������� ������������������  finalPrice;����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  }����������� ������������������  private����������� ������������������  double����������� ������������������  discountedPrice����������� ������������������  (int����������� ������������������  basePrice,����������� ������������������  int����������� ������������������  discountLevel)����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������   if����������� ������������������  (discountLevel����������� ������������������  ==����������� ������������������  2)����������� ������������������  return����������� ������������������  basePrice����������� ������������������  *����������� ������������������  0.1;����������� ������������������  ����������� ������������������   else����������� ������������������  return����������� ������������������  basePrice����������� ������������������  *����������� ������������������  0.05;����������� ������������������  ����������� ������������������  }

public����������� ������������������  double����������� ������������������  getPrice()����������� ������������������  {����������� ������������������   int����������� ������������������  basePrice����������� ������������������  =����������� ������������������  _quantity����������� ������������������  *����������� ������������������  _itemPrice; ����������� ������������������   int����������� ������������������  discountLevel����������� ������������������  =����������� ������������������  getDiscountLevel();����������� ������������������   double����������� ������������������  finalPrice����������� ������������������  =����������� ������������������  discountedPrice����������� ������������������  (basePrice,����������� ������������������  discountLevel);����������� ������������������  ����������� ������������������  ����������� ������������������   return����������� ������������������  finalPrice;����������� ������������������  }����������� ������������������  private����������� ������������������  double����������� ������������������  discountedPrice����������� ������������������  (int����������� ������������������  basePrice,����������� ������������������  int����������� ������������������  discountLevel)����������� ������������������  {����������� ������������������   if����������� ������������������  (getDiscountLevel()����������� ������������������  ==����������� ������������������  2)����������� ������������������  return����������� ������������������  basePrice����������� ������������������  *����������� ������������������  0.1;����������� ������������������  ����������� ������������������  ����������� ������������������   else����������� ������������������  return����������� ������������������  basePrice����������� ������������������  *����������� ������������������  0.05;����������� ������������������  }����������� ������������������  !private����������� ������������������  int����������� ������������������  getDiscountLevel()����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������   if����������� ������������������  (_quantity����������� ������������������  >����������� ������������������  100)����������� ������������������  return����������� ������������������  2;����������� ������������������  else����������� ������������������  return����������� ������������������  1;����������� ������������������  }

public����������� ������������������  double����������� ������������������  getPrice()����������� ������������������  { ����������� ������������������   int����������� ������������������  basePrice����������� ������������������  =����������� ������������������  _quantity����������� ������������������  *����������� ������������������  _itemPrice; ����������� ������������������   double����������� ������������������  finalPrice����������� ������������������  =����������� ������������������  discountedPrice����������� ������������������  (basePrice);����������� ������������������  ����������� ������������������  ����������� ������������������   return����������� ������������������  finalPrice;����������� ������������������  }����������� ������������������  private����������� ������������������  double����������� ������������������  discountedPrice����������� ������������������  (int����������� ������������������  basePrice,)����������� ������������������  { ����������� ������������������   if����������� ������������������  (getDiscountLevel()����������� ������������������  ==����������� ������������������  2)����������� ������������������  return����������� ������������������  basePrice����������� ������������������  *����������� ������������������  0.1;����������� ������������������  ����������� ������������������  ����������� ������������������   else����������� ������������������  return����������� ������������������  basePrice����������� ������������������  *����������� ������������������  0.05;����������� ������������������  }

private����������� ������������������  double����������� ������������������  getPrice����������� ������������������  ()����������� ������������������  {����������� ������������������   if����������� ������������������  (getDiscountLevel()����������� ������������������  ==����������� ������������������  2)����������� ������������������  return����������� ������������������  getBasePrice()����������� ������������������  *����������� ������������������  0.1;����������� ������������������  ����������� ������������������  ����������� ������������������   else����������� ������������������  return����������� ������������������  getBasePrice()����������� ������������������  *����������� ������������������  0.05;����������� ������������������  }����������� ������������������  !private����������� ������������������  double����������� ������������������  getBasePrice()����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������   return����������� ������������������  _quantity����������� ������������������  *����������� ������������������  _itemPrice;����������� ������������������  }

Extract����������� ������������������  Method

Replace����������� ������������������  Parameter����������� ������������������  with����������� ������������������  Method

Inline����������� ������������������  Method

Page 13: Refactoring 메소드 호출의 단순화

Introduce����������� ������������������  Parameter����������� ������������������  Object

자연스럽게����������� ������������������  몰려����������� ������������������  다니는����������� ������������������  파라미터����������� ������������������  그룹을����������� ������������������  가지고����������� ������������������  있다면,����������� ������������������  그것을����������� ������������������  객체로����������� ������������������  바꾸어라.

Customer

amountInvoiceIn(Date����������� ������������������  start,����������� ������������������  Date����������� ������������������  end)����������� ������������������  amountReceivedIn(Date����������� ������������������  start,����������� ������������������  Date����������� ������������������  end)����������� ������������������  amountOverdueIn(Date����������� ������������������  start,����������� ������������������  Date����������� ������������������  end)

Customer

amountInvoiceIn(DateRange)����������� ������������������  amountReceivedIn(DateRange)����������� ������������������  amountOverdueIn(DateRange)

����������� ������������������  Preserve����������� ������������������  Whole����������� ������������������  Object����������� ������������������  와����������� ������������������  유사����������� ������������������  

차이점:����������� ������������������  이����������� ������������������  리팩토링은����������� ������������������  새로운����������� ������������������  객체를����������� ������������������  도입함으로,����������� ������������������  리팩토링����������� ������������������  절차가����������� ������������������  틀림.

Page 14: Refactoring 메소드 호출의 단순화

불필요한����������� ������������������  정보를����������� ������������������  숨기는����������� ������������������  리팩토링

•Remove����������� ������������������  Setting����������� ������������������  Method����������� ������������������  • 어떤����������� ������������������  필드가����������� ������������������  생성시에����������� ������������������  값이����������� ������������������  정해지고,����������� ������������������  이후����������� ������������������  변경되지����������� ������������������  않아야����������� ������������������  한다면����������� ������������������  설정����������� ������������������  메소드를����������� ������������������  제거하라����������� ������������������  

•Hide����������� ������������������  Method����������� ������������������  • 메소드가����������� ������������������  다른����������� ������������������  클래스에서����������� ������������������  사용되지����������� ������������������  않는다면,����������� ������������������  private로����������� ������������������  만들어라����������� ������������������  

•Encapsulate����������� ������������������  Downcast����������� ������������������  • 메소드가����������� ������������������  그����������� ������������������  호출부에서����������� ������������������  다운캐스트����������� ������������������  될����������� ������������������  필요가����������� ������������������  있는����������� ������������������  객체를����������� ������������������  리턴하고����������� ������������������  있다면,����������� ������������������  다운����������� ������������������  ����������� ������������������  

캐스트를����������� ������������������  메소드����������� ������������������  안으로����������� ������������������  옮겨라����������� ������������������  (ex:����������� ������������������  java����������� ������������������  1.4이하����������� ������������������  버전의����������� ������������������  Collection����������� ������������������  Classes)

Page 15: Refactoring 메소드 호출의 단순화

Replace����������� ������������������  Constructor����������� ������������������  With����������� ������������������  Factory����������� ������������������  Method

객체를����������� ������������������  생성할����������� ������������������  때����������� ������������������  생성하는����������� ������������������  것외에����������� ������������������  다른����������� ������������������  작업을����������� ������������������  하고����������� ������������������  있다면,����������� ������������������  생성자를����������� ������������������  팩토리����������� ������������������  메소드로����������� ������������������  대체하라

class����������� ������������������  Employee����������� ������������������  {����������� ������������������  private����������� ������������������  int����������� ������������������  _type; static����������� ������������������  final����������� ������������������  int����������� ������������������  ENGINEER����������� ������������������  =����������� ������������������  0;����������� ������������������  ����������� ������������������  

����������� ������������������   ����������� ������������������   static����������� ������������������  final����������� ������������������  int����������� ������������������  SALESMAN����������� ������������������  =����������� ������������������  1;����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������   static����������� ������������������  final����������� ������������������  int����������� ������������������  MANAGER����������� ������������������  =����������� ������������������  2;����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������  ����������� ������������������   Employee����������� ������������������  (int����������� ������������������  type)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������  _type����������� ������������������  =����������� ������������������  type;����������� ������������������  ����������� ������������������   }����������� ������������������  }

static����������� ������������������  Employee����������� ������������������  create(int����������� ������������������  type)����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������   switch����������� ������������������  (type)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   case����������� ������������������  ENGINEER:����������� ������������������   ����������� ������������������   ����������� ������������������   return����������� ������������������  new����������� ������������������  Engineer();����������� ������������������  ����������� ������������������   ����������� ������������������   case����������� ������������������  SALESMAN:����������� ������������������   ����������� ������������������   ����������� ������������������   return����������� ������������������  new����������� ������������������  Salesman();����������� ������������������  ����������� ������������������   ����������� ������������������   case����������� ������������������  MANAGER:����������� ������������������   ����������� ������������������   ����������� ������������������   return����������� ������������������  new����������� ������������������  Manager();����������� ������������������  ����������� ������������������   ����������� ������������������   default:����������� ������������������  ����������� ������������������   ����������� ������������������   ����������� ������������������   …⋯����������� ������������������  ����������� ������������������   }����������� ������������������  }����������� ������������������  Employee.create(ENGINEER);

class����������� ������������������  Person...����������� ������������������   static����������� ������������������  Person����������� ������������������  createMale(){����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  new����������� ������������������  Male();����������� ������������������  ����������� ������������������  ����������� ������������������   }����������� ������������������  ����������� ������������������   static����������� ������������������  Person����������� ������������������  createFemale()����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  new����������� ������������������  Female();����������� ������������������  ����������� ������������������   }����������� ������������������  }����������� ������������������  …⋯����������� ������������������  Person����������� ������������������  kent����������� ������������������  =����������� ������������������  Person.createMale();

문자열을����������� ������������������  이용한����������� ������������������  서브����������� ������������������  클래스����������� ������������������  객체����������� ������������������  생성 명시적����������� ������������������  메소드로����������� ������������������  서브����������� ������������������  클래스����������� ������������������  객체����������� ������������������  생성

etc)����������� ������������������  문자열을����������� ������������������  이용한����������� ������������������  생성

Page 16: Refactoring 메소드 호출의 단순화

메소드����������� ������������������  예외����������� ������������������  선언과����������� ������������������  관련된����������� ������������������  리팩토링

테스트와����������� ������������������  예외를����������� ������������������  구분하여����������� ������������������  사용하라

Page 17: Refactoring 메소드 호출의 단순화

Replace����������� ������������������  Error����������� ������������������  Code����������� ������������������  with����������� ������������������  Exception

메소드가����������� ������������������  에러를����������� ������������������  나타내는����������� ������������������  특별한����������� ������������������  코드를����������� ������������������  가지고����������� ������������������  있다면,����������� ������������������  대신����������� ������������������  예외를����������� ������������������  던져라.

int����������� ������������������  withdraw(int����������� ������������������  amount)����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������   if����������� ������������������  (amount����������� ������������������  >����������� ������������������  _balance)����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  -1;����������� ������������������  ����������� ������������������  ����������� ������������������   else����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   _balance����������� ������������������  -=����������� ������������������  amount;����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  0;����������� ������������������  ����������� ������������������  ����������� ������������������   }����������� ������������������  }

void����������� ������������������  withdraw(int����������� ������������������  amount)����������� ������������������  throws����������� ������������������  BalanceException����������� ������������������  {����������� ������������������   if����������� ������������������  (amount����������� ������������������  >����������� ������������������  _balance)����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������   throw����������� ������������������  new����������� ������������������  BalanceException();����������� ������������������  ����������� ������������������   ����������� ������������������  _balance����������� ������������������  -=����������� ������������������  amount;����������� ������������������  }

비검사����������� ������������������  예외를����������� ������������������  사용하는����������� ������������������  경우:����������� ������������������  검사의����������� ������������������  책임이����������� ������������������  호출부에����������� ������������������  있는����������� ������������������  경우����������� ������������������  

검사����������� ������������������  예외를����������� ������������������  사용하는����������� ������������������  경우:����������� ������������������  검사의����������� ������������������  책임이����������� ������������������  수신수에����������� ������������������  있는����������� ������������������  경우

Page 18: Refactoring 메소드 호출의 단순화

Replace����������� ������������������  Exception����������� ������������������  with����������� ������������������  Test

호출부에서����������� ������������������  먼저����������� ������������������  검사할����������� ������������������  수����������� ������������������  있는����������� ������������������  조건에����������� ������������������  대해����������� ������������������  예외를����������� ������������������  던지고����������� ������������������  있다면,����������� ������������������  호출부가����������� ������������������  먼저����������� ������������������  검사하도록����������� ������������������  바꿔라.

double����������� ������������������  getValueForPeriod����������� ������������������  (int����������� ������������������  periodNumber)����������� ������������������  {����������� ������������������  ����������� ������������������  ����������� ������������������   try����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  _values[periodNumber]; ����������� ������������������   }����������� ������������������  catch����������� ������������������  (ArrayIndexOutOfBoundsException����������� ������������������  e)����������� ������������������  {����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  0;����������� ������������������  ����������� ������������������  ����������� ������������������   }����������� ������������������  }

double����������� ������������������  getValueForPeriod����������� ������������������  (int����������� ������������������  periodNumber)����������� ������������������  {����������� ������������������   if����������� ������������������  (periodNumber����������� ������������������  >=����������� ������������������  _values.length)����������� ������������������  ����������� ������������������  ����������� ������������������   ����������� ������������������   return����������� ������������������  0;����������� ������������������  ����������� ������������������  ����������� ������������������   return����������� ������������������  _values[periodNumber];����������� ������������������  }

예외가����������� ������������������  조건����������� ������������������  테스트를����������� ������������������  대신하는����������� ������������������  역할을����������� ������������������  하면����������� ������������������  안된다.����������� ������������������  

호출부에서����������� ������������������  동작을����������� ������������������  호출하기����������� ������������������  전에����������� ������������������  조건을����������� ������������������  테스트����������� ������������������  할����������� ������������������  수����������� ������������������  있다면����������� ������������������  테스트를����������� ������������������  제공해야����������� ������������������  하고,����������� ������������������  호출부에서����������� ������������������  그것을����������� ������������������  사용해야����������� ������������������  한다.

Page 19: Refactoring 메소드 호출의 단순화

Q&A

Page 20: Refactoring 메소드 호출의 단순화

Reference• Martin����������� ������������������  Fowler.����������� ������������������  리팩토링.����������� ������������������  (윤성준,����������� ������������������  조재박역).����������� ������������������  서울:����������� ������������������  대청미디어,����������� ������������������  2003