# 8.4 문장을 호출한 곳으로 옮기기 (Move Statements to Callers)

↔️ 문장을 함수로 옮기기

리팩터링 전

```javascript
emitPhotoData(outStream, person.photo);

function emitPhotoData(outStream, photo){
	outStream.write(photo.title);
	outStream.write(photo.location);
}
```

리팩터링 후

```javascript
emitPhotoData(outStream, person.photo);
	outStream.write(photo.location);

function emitPhotoData(outStream, photo){
	outStream.write(photo.title);
}
```

## 🧷 배경

함수는 프로그래머가 만드는 추상화 블록이다. 하지만 추상화의 경계를 올바르게 긋기가 어렵다. 함수 관점에서 생각해보면, 초기에는 응집도 높고 한 가지 일만 수행하던 함수가 어느새 둘 이상의 다른 일을 수행하게 바뀔 수도 있다.

여러 곳에서 사용하던 기능이 일부 호출자에게 다르게 동작하도록 바뀌어야 할 때 발생한다. 이때, 문장을 호출한 곳으로 옮기기 리팩터링을 적용하면 달라지는 동작을 호출자로 옮긴 뒤에 필요할 때마다 독립적으로 수정할 수 있다.

## 🧷 절차

1\. 호출자가 한두 개 뿐이고 피호출 함수도 간단한 상황이라면, 피호출 함수의 처음( 혹은 마지막) 줄을 잘라내어 호출자로 복사해 넣는다.

2\. 더 복잡한 상황에서는, 이동하지 않길 원하는 모든 문장을 함수로 추출한 다음 검색하기 쉬운 임시 이름을 지어준다.

3\. 원래 함수를 인라인 한다.

4\. 추출된 함수의 이름을 원래 함수의 이름으로 변경한다.

## 🧷 예시

```javascript
function renderPerson(outStream, person) {
  outStream.write(`<p>${person.name}</p>\n`);
  renderPhoto(outStream, persons.photo);
  emitPhotoData(outStream, person.photo);
}

function listRecentPhotos(outStream, photos) {
  photos
    .filter(p => p.data > recentDateCutoff())
    .forEach(p => {
      outStream.write("<div>\n"
      emitPhotoData(outStream, p);
      outStream.write("/</div>\n");
      });
  }

function emitPhotoData(outStream, photo) {
  outStream.write(`<p>제목: ${photo.title}</p>`);
  outStream.write(`<p>날짜: ${photo.date.toDateString()}</p>`);
  outStream.write(`<p>위치: ${photo.location}</p>`);
}
```

📍 `renderPerson()`은 그대로 둔 채 `listRecentPhotos()`가 위치 정보를 다르게 렌더링 하도록 만들어보자.

단순한 상황에서는 `renderPerson()`의 마지막 줄을 잘라내어 두 호출 코드 아래에 붙여넣으면 끝이다. 까다로운 방법으로 해보자.

1. `emitPhotoData()`에 남길 코드를 함수로 추출한다.

```javascript
function renderPerson(outStream, person) {
  outStream.write(`<p>${person.name}</p>\n`);
  renderPhoto(outStream, persons.photo);
  emitPhotoData(outStream, person.photo);
}

function listRecentPhotos(outStream, photos) {
  photos
    .filter(p => p.data > recentDateCutoff())
    .forEach(p => {
      outStream.write("<div>\n"
      emitPhotoData(outStream, p);
      outStream.write("/</div>\n");
      });
  }

function emitPhotoData(outStream, photo) {
  // 함수 추출
  zztmp(outStream, photo);
  outStream.write(`<p>위치: ${photo.location}</p>`); 
}

function zztmp(outStream, photo) {
  // 바뀌지 않을 코드
  outStream.write(`<p>제목: ${photo.title}</p>`);
  outStream.write(`<p>날짜: ${photo.date.toDateString()}</p>`); 
}
```

2. 피호출 함수를 호출자들로 인라인한다.

```javascript
function renderPerson(outStream, person) {
  outStream.write(`<p>${person.name}</p>\n`);
  renderPhoto(outStream, persons.photo);
  // 분리하기
  zztmp(outStream, person.photo);
  outStream.write(`<p>위치: ${photo.location}</p>`);  // 첫번째 호출 위치로 인라인
}

function listRecentPhotos(outStream, photos) {
  photos
    .filter(p => p.data > recentDateCutoff())
    .forEach(p => {
      outStream.write("<div>\n");
      // 분리하기
      zztmp(outStream, p);
      outStream.write(`<p>위치: ${photo.location}</p>`);  // 두번째 호출 위치로 인라인
      outStream.write("/</div>\n");
      });
  }

function emitPhotoData(outStream, photo) {
  // 함수 추출
  zztmp(outStream, photo);
  outStream.write(`<p>위치: ${photo.location}</p>`); 
}

function zztmp(outStream, photo) {
  // 바뀌지 않을 코드
  outStream.write(`<p>제목: ${photo.title}</p>`);
  outStream.write(`<p>날짜: ${photo.date.toDateString()}</p>`); 
}
```

3. 원래 함수를 지우고, `zztmp()` 이름을 원래 함수의 이름으로 되돌린다.

```javascript
function renderPerson(outStream, person) {
  outStream.write(`<p>${person.name}</p>\n`);
  renderPhoto(outStream, persons.photo);
  emitPhotoData(outStream, person.photo);
  outStream.write(`<p>위치: ${photo.location}</p>`); 
}

function listRecentPhotos(outStream, photos) {
  photos
    .filter(p => p.data > recentDateCutoff())
    .forEach(p => {
      outStream.write("<div>\n");
      emitPhotoData(outStream, p);
      outStream.write(`<p>위치: ${photo.location}</p>`); 
      outStream.write("/</div>\n");
      });
  }

function emitPhotoData(outStream, photo) {
  outStream.write(`<p>제목: ${photo.title}</p>`);
  outStream.write(`<p>날짜: ${photo.date.toDateString()}</p>`); 
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://koseoyoung.gitbook.io/library/refactoring/chapter-08/8.4-move-statements-to-callers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
