1. 알고자 하는 것
이전에 함수 추출하기(Extract Method) 글을 통해 코드의 내용에 직관적인 이름을 붙여 가독성을 높일 수 있다고 학습한 적이 있었다.
이러한 추출하기 기법은 함수 뿐 아니라 클래스 단위로도 가능하며, 마찬가지로 클래스로 코드의 내용을 추출해 직관적으로 코드의 가독성을 높이고 응집도를 높일 수 있다.
하지만 함수/클래스 추출하기와 반대로, 때로는 함수/클래스로 추출했던 코드를 다시 본문 코드에 옮겨넣는 것이 코드의 가독성을 높일 수 있는 상황이 있다. 이러한 리팩토링 방법을 함수/클래스 인라인 (Function / Class Inline) 이라고 한다.
- 함수 인라인 (Function Inline)
- 클래스 인라인 (Class Inline)
2. 알게 된 것
- 함수/클래스 추출하기를 사용해 코드의 가독성을 높인 뒤에, 기능의 변경사항으로 코드가 줄어들거나 변경되고 나서 다시 보았을 때 다음과 같은 형태의 코드가 되어있을 수도 있다.
- 기존에 추출했던 코드가 간소화되어 이제는 함수/클래스의 본문이 함수/클래스의 이름만큼, 또는 함수/클래스의 이름보다 의도를 더 명확하게 표현하게 됨
- 단순히 함수/클래스의 호출을 감싸는 우회형 (Indirection) 함수/클래스가 됨
- 함수/클래스 추출이 잘못되어 다시 하나로 합친 뒤 리팩토링을 해야함
- 이런 경우, 추출한 함수/클래스를 다시 합치는 Inline 리팩토링 기법을 사용할 수 있다.
함수 인라인 (Function Inline)
- 코드의 변경으로 추출했던 함수가 다음과 같이 한 줄의 코드만을 포함하는 메서드가 되었다고 가정하자.
public class Rating {
public int rating(Driver driver) {
return moreThanFiveLateDeliveries(driver) ? 2 : 1;
}
// 함수 추출하기 (Extract Function)
private boolean moreThanFiveLateDeliveries(Driver driver) {
return driver.getNumberOfLateDeliveries() > 5;
}
}
- driver의 Late Delivery 수가 5 이상인지를 판단하는 메서드로, moreThanFiveLateDeliveries 라는 의도를 표현하는 메서드명으로 추출된 것은 분명 함수 추출하기의 리팩토링 의도로써 괜찮을 수 있다.
- 하지만 본문 내용을 보았을 때, driver.getNumberOfLateDeliveries() > 5; 라는 코드를 보았을 때에도 충분히 코드의 의도를 파악할 수 있다.
- 이런 경우 굳이 함수로 한줄의 코드를 감싸는 것 보다는 다시 함수를 본문에 inline 하여 메서드를 없애는 경우가 더 나을 수도 있다.
public class Rating {
public int rating(Driver driver) {
// Function inline
return driver.getNumberOfLateDeliveries() > 5 ? 2 : 1;
}
}
클래스 인라인 (Function Inline)
- 다음과 같이 Shipment 클래스에서 클래스 추출하기를 통해 추출된 TrackingInformation 클래스를 가지고 있고, getTrackingInfo() 함수를 통해 trackingInformation의 정보를 출력하는 함수가 있다고 가정하자.
public class Shipment {
/**
* private String shippingCompany;
* private String trackingNumber;
*/
private TrackingInformation trackingInformation;
public Shipment(TrackingInformation trackingInformation) {
this.trackingInformation = trackingInformation;
}
public TrackingInformation getTrackingInformation() {
return trackingInformation;
}
public void setTrackingInformation(TrackingInformation trackingInformation) {
this.trackingInformation = trackingInformation;
}
public String getTrackingInfo() {
// return this.shippingCompany + ": " + this.trackingNumber;
// Output : SHP:135
return this.trackingInformation.display();
}
}
- 이 때, getTrackingInfo() 함수는 단순히 TrackingInformation 클래스의 display() 함수의 호출을 감싸는 함수로써만 동작한다.
- 이 경우, 단순히 delegate 역할만을 하는 TrackingInformation은 크게 의미를 가지지 않게 되므로 해당 클래스를 제거하고 해당 클래스가 가지는 필드와 display() 함수를 Shipment 클래스에 inline 시킬 수 있다.
public class Shipment {
public static void main(String[] args) {
// 기존 함수 호출
// Shipment shipment = new Shipment(new TrackingInformation("UPS", "12345"));
// shipment.getTrackingInfo();
// 클래스 인라인 함수 호출
Shipment shipment = new Shipment("UPS", "12345");
shipment.getTrackingInfo();
}
// TrackingInformation Field 가져오기
private String shippingCompany;
private String trackingNumber;
public Shipment(String shippingCompany, String trackingNumber) {
this.shippingCompany = shippingCompany;
this.trackingNumber = trackingNumber;
}
public String getShippingCompany() {
return shippingCompany;
}
public String getTrackingNumber() {
return trackingNumber;
}
public String getTrackingInfo() {
// 기존 TrackingInformation의 display() 함수 inline
return this.shippingCompany + ":" + this.trackingNumber;
}
}
- 단순히 delegate 역할만을 수행하던 TrackingInformation 클래스의 필드와 display() 함수를 Shipment에 inline 함으로써 불필요한 클래스와 delegate 함수를 줄일 수 있다.
3. 정리
- 함수/클래스 추출하기를 통해 코드의 내용에 대해 명확한 이름으로 의도를 표현할 수 있다.
- 하지만 변경사항으로 코드가 변경됨으로써 기존 추출하기를 사용한 코드가 단순히 다음과 같은 역할이 될 수도 있다.
- 기존 코드가 간소화되어 본문 자체가 함수명보다 의도를 더 잘 표현함
- 단순히 함수/클래스를 감싸는 우회형 (Indirection) 코드가 됨
- 이럴 때, 추출했던 함수/클래스를 기존 코드에 합치는 Inline 리팩토링 기법을 사용할 수 있다.
- 이제는 불필요해진 함수를 줄일 수 있고, 단순히 delegate만을 수행하는 불필요한 클래스를 줄일 수 있다.
Reference
'Clean Code' 카테고리의 다른 글
Java 리팩토링 - 특이 케이스 추가하기 (Introduce Special Case) (0) | 2024.01.16 |
---|---|
Java 리팩토링 - 기본형을 객체로 바꾸기 (Replace Primitive with Object) (0) | 2024.01.15 |
Java 리팩토링 - 함수 옮기기 (Move Function) (0) | 2023.12.25 |
Java 리팩토링 - 변수 캡슐화하기 (with. Getter/Setter) (0) | 2023.12.17 |
Java 리팩토링 - 플래그 인수 제거하기 (0) | 2023.11.12 |