refactoring 메소드 호출의 단순화
TRANSCRIPT
Refactoring����������� ������������������ 메소드����������� ������������������ 호출의����������� ������������������ 단순화
cecil
Contents
•메소드를����������� ������������������ 직관적으로����������� ������������������ •파라미터����������� ������������������ 갯수의����������� ������������������ 조정����������� ������������������ •불필요한����������� ������������������ 정보를����������� ������������������ 숨김����������� ������������������ •생성자를����������� ������������������ 팩토리����������� ������������������ 메소드로����������� ������������������ •메소드의����������� ������������������ 예외����������� ������������������ 선언
메소드를����������� ������������������ 직관적으로����������� ������������������ (기본적인����������� ������������������ 리팩토링)
•Rename����������� ������������������ Method����������� ������������������ • 메소드의����������� ������������������ 이름이����������� ������������������ 그����������� ������������������ 목적을����������� ������������������ 드러내지����������� ������������������ 못하면����������� ������������������ 이름을����������� ������������������ 바꿔라����������� ������������������
•Add����������� ������������������ Parameter����������� ������������������ • 메소드를����������� ������������������ 호출하는����������� ������������������ 부분에서����������� ������������������ 더����������� ������������������ 많은����������� ������������������ 정보를����������� ������������������ 필요로����������� ������������������ 한다면����������� ������������������ 파라미터를����������� ������������������ 추가하라����������� ������������������ • 이����������� ������������������ 리팩토링을����������� ������������������ 하지����������� ������������������ 않도록����������� ������������������ 하는����������� ������������������ 것이����������� ������������������ 중요(대안:����������� ������������������ 파라미터����������� ������������������ 오브젝트����������� ������������������ 도입)����������� ������������������
•Remove����������� ������������������ Parameter����������� ������������������ •파라미터가����������� ������������������ 메소드에서����������� ������������������ 더����������� ������������������ 이상����������� ������������������ 사용되지����������� ������������������ 않으면����������� ������������������ 제거하라
파라미터����������� ������������������ 갯수����������� ������������������ 조정을����������� ������������������ 위한����������� ������������������ 리팩토링
많은����������� ������������������ 수의����������� ������������������ 파라미터는����������� ������������������ 메소드를����������� ������������������ 복잡하게����������� ������������������ 만든다
Separate����������� ������������������ Query����������� ������������������ from����������� ������������������ Modifier
Customer
getTotalOutstanding����������� ������������������ setReadyForSummaries
Customer
getTotalOutstandingAndSetReadyForSummaries
값을����������� ������������������ 리턴할����������� ������������������ 뿐만����������� ������������������ 아니라����������� ������������������ 상태도����������� ������������������ 변경하는����������� ������������������ 메소드는����������� ������������������ 분리하라
값을����������� ������������������ 리턴하고,����������� ������������������ 눈에����������� ������������������ 띄눈����������� ������������������ 부작용이����������� ������������������ 없는����������� ������������������ 것은����������� ������������������ 매우����������� ������������������ 가치����������� ������������������ 있는����������� ������������������ 일����������� ������������������ 예외)����������� ������������������ 동시성����������� ������������������ 문제:����������� ������������������ 동시성이����������� ������������������ 문제가����������� ������������������ 될����������� ������������������ 경우����������� ������������������ getAndSet����������� ������������������ 메소드를����������� ������������������ 가질����������� ������������������ 필요가����������� ������������������ 있음.
Parameterize����������� ������������������ Method
몇몇����������� ������������������ 메소드가����������� ������������������ 다른����������� ������������������ 값을����������� ������������������ 포함하고����������� ������������������ 있는����������� ������������������ 것을����������� ������������������ 제외하고는����������� ������������������ 비슷한����������� ������������������ 일을����������� ������������������ 하고����������� ������������������ 있다면,����������� ������������������ ����������� ������������������ 파라미터를����������� ������������������ 가진����������� ������������������ 하나의����������� ������������������ 메소드로����������� ������������������ 만들어라
Employee
fivePercentRaise����������� ������������������ tenPercentRaise
Employee
raise(percentage)
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;����������� ������������������ }����������� ������������������
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()����������� ������������������ 파라미터����������� ������������������ 값의����������� ������������������ 변화가����������� ������������������ 크다면,����������� ������������������ 이����������� ������������������ 리팩토링을����������� ������������������ 적용하면����������� ������������������ 안됨.
Preserve����������� ������������������ Whole����������� ������������������ Object어떤����������� ������������������ 객체에서����������� ������������������ 여러개의����������� ������������������ 값을����������� ������������������ 얻은����������� ������������������ 다음����������� ������������������ 메소드를����������� ������������������ 호출하면서����������� ������������������ 파라미터로����������� ������������������ 넘기고����������� ������������������ 있다면,����������� ������������������ 대신����������� ������������������ 그����������� ������������������ 객체를����������� ������������������ 넘겨라
int����������� ������������������ low����������� ������������������ =����������� ������������������ daysTempRange().getLow();����������� ������������������
int����������� ������������������ high����������� ������������������ =����������� ������������������ daysTempRange().getHigh();����������� ������������������ ����������� ������������������
withinPlan����������� ������������������ =����������� ������������������ plan.withinRange(low,����������� ������������������ high);
withinPlan����������� ������������������ =����������� ������������������ plan.withinRange(daysTempRange());
장점:����������� ������������������ 파라미터����������� ������������������ 리스트����������� ������������������ 변경에����������� ������������������ 유연하게����������� ������������������ 대처가����������� ������������������ 가능,����������� ������������������ 코드의����������� ������������������ 가독성을����������� ������������������ 높임.����������� ������������������
단점:����������� ������������������ 파라미터로����������� ������������������ 넘겨진����������� ������������������ 객체와����������� ������������������ 호출된����������� ������������������ 객체����������� ������������������ 사이에����������� ������������������ 종속성을����������� ������������������ 생성����������� ������������������
만약����������� ������������������ 이����������� ������������������ 리팩토링이����������� ������������������ 종속성����������� ������������������ 구조를����������� ������������������ 나쁘면����������� ������������������ 한다면����������� ������������������ 사용하면����������� ������������������ 안됨.
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();����������� ������������������ ����������� ������������������ }
Replace����������� ������������������ Parameter����������� ������������������ with����������� ������������������ Method
객체가����������� ������������������ 메소드를����������� ������������������ 호출한����������� ������������������ 결과를����������� ������������������ 다른����������� ������������������ 메소드에����������� ������������������ 파라미터로����������� ������������������ 넘기는����������� ������������������ 상황에서,����������� ������������������ 호출된����������� ������������������ 메소드가����������� ������������������ 이����������� ������������������ 메소드를����������� ������������������ 호출할����������� ������������������ 수����������� ������������������ 있다면,����������� ������������������ 직접����������� ������������������ 호출하도록����������� ������������������ 변경
int����������� ������������������ basePrice����������� ������������������ =����������� ������������������ _quantity����������� ������������������ *����������� ������������������ _itemPrice; discountLevel����������� ������������������ =����������� ������������������ getDiscountLevel();double����������� ������������������ finalPrice����������� ������������������ =����������� ������������������ discountedPrice����������� ������������������ (basePrice,����������� ������������������ discountLevel);
int����������� ������������������ basePrice����������� ������������������ =����������� ������������������ _quantity����������� ������������������ *����������� ������������������ _itemPrice;double����������� ������������������ finalPrice����������� ������������������ =����������� ������������������ discountedPrice����������� ������������������ (basePrice);
파라미터는����������� ������������������ 필요할����������� ������������������ 때만����������� ������������������ 사용하라.
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
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����������� ������������������ 와����������� ������������������ 유사����������� ������������������
차이점:����������� ������������������ 이����������� ������������������ 리팩토링은����������� ������������������ 새로운����������� ������������������ 객체를����������� ������������������ 도입함으로,����������� ������������������ 리팩토링����������� ������������������ 절차가����������� ������������������ 틀림.
불필요한����������� ������������������ 정보를����������� ������������������ 숨기는����������� ������������������ 리팩토링
•Remove����������� ������������������ Setting����������� ������������������ Method����������� ������������������ • 어떤����������� ������������������ 필드가����������� ������������������ 생성시에����������� ������������������ 값이����������� ������������������ 정해지고,����������� ������������������ 이후����������� ������������������ 변경되지����������� ������������������ 않아야����������� ������������������ 한다면����������� ������������������ 설정����������� ������������������ 메소드를����������� ������������������ 제거하라����������� ������������������
•Hide����������� ������������������ Method����������� ������������������ • 메소드가����������� ������������������ 다른����������� ������������������ 클래스에서����������� ������������������ 사용되지����������� ������������������ 않는다면,����������� ������������������ private로����������� ������������������ 만들어라����������� ������������������
•Encapsulate����������� ������������������ Downcast����������� ������������������ • 메소드가����������� ������������������ 그����������� ������������������ 호출부에서����������� ������������������ 다운캐스트����������� ������������������ 될����������� ������������������ 필요가����������� ������������������ 있는����������� ������������������ 객체를����������� ������������������ 리턴하고����������� ������������������ 있다면,����������� ������������������ 다운����������� ������������������ ����������� ������������������
캐스트를����������� ������������������ 메소드����������� ������������������ 안으로����������� ������������������ 옮겨라����������� ������������������ (ex:����������� ������������������ java����������� ������������������ 1.4이하����������� ������������������ 버전의����������� ������������������ Collection����������� ������������������ Classes)
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)����������� ������������������ 문자열을����������� ������������������ 이용한����������� ������������������ 생성
메소드����������� ������������������ 예외����������� ������������������ 선언과����������� ������������������ 관련된����������� ������������������ 리팩토링
테스트와����������� ������������������ 예외를����������� ������������������ 구분하여����������� ������������������ 사용하라
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;����������� ������������������ }
비검사����������� ������������������ 예외를����������� ������������������ 사용하는����������� ������������������ 경우:����������� ������������������ 검사의����������� ������������������ 책임이����������� ������������������ 호출부에����������� ������������������ 있는����������� ������������������ 경우����������� ������������������
검사����������� ������������������ 예외를����������� ������������������ 사용하는����������� ������������������ 경우:����������� ������������������ 검사의����������� ������������������ 책임이����������� ������������������ 수신수에����������� ������������������ 있는����������� ������������������ 경우
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];����������� ������������������ }
예외가����������� ������������������ 조건����������� ������������������ 테스트를����������� ������������������ 대신하는����������� ������������������ 역할을����������� ������������������ 하면����������� ������������������ 안된다.����������� ������������������
호출부에서����������� ������������������ 동작을����������� ������������������ 호출하기����������� ������������������ 전에����������� ������������������ 조건을����������� ������������������ 테스트����������� ������������������ 할����������� ������������������ 수����������� ������������������ 있다면����������� ������������������ 테스트를����������� ������������������ 제공해야����������� ������������������ 하고,����������� ������������������ 호출부에서����������� ������������������ 그것을����������� ������������������ 사용해야����������� ������������������ 한다.
Q&A
Reference• Martin����������� ������������������ Fowler.����������� ������������������ 리팩토링.����������� ������������������ (윤성준,����������� ������������������ 조재박역).����������� ������������������ 서울:����������� ������������������ 대청미디어,����������� ������������������ 2003