# 4. 코드는 한 번만 작성하라

## 가이드 라인

* 코드를 복사하지 않는다
* 코드를 재사용 가능한 일반적인 형태로 작성하거나 기존메서드를 대신 호출
* 유지보수성 개선. 코드 복사는 여러곳에서 버그를 고쳐야하기 때문에 비효율적이고 에러 발생이 쉬움

> **악취** 퍼레이드의 하이라이트는 **중복 코드다**
>
> -켄트백, 마틴파울러

### 1. 필요성

* **중복코드**는 코드 수정시 다른 곳도 수정해야하므로 버그의 발생률이 높아진다
* 이런 **중복코드**는 분석하기 어렵고, 수정하기가 어려워지게 한다
* **코드는 무조건 변합니다. 그러니 복사해서 임시방편으로 해결하기 보다 장기적으로 유지보수성을 생각하여 코드를 작성할 줄 알아야함**&#x20;

### 2. 적용가이드

* **상위클래스 추출**
  * 의미 명확화
  * 클래스의 상세정보 비대증세 제거
  * 공통 부분 추출하여 활용 및 재정의를 통한 다형성 활용&#x20;
* 예제 p.92&#x20;

  * Account
    * CheckingAccount
    * SavingAccount
  * 중복내용 대상 -> makeTransfer 메서드&#x20;

```java
public class Account {
    public Transfer makeTransfer(String counterAccount, Money amount)
        throws BusinessException {
        if (isValid(counterAccount)) {
            CheckingAccount acct = Accounts.findAcctByNumber(counterAccount);
            return new Transfer(this, acct, amount);
        } else {
            throw new BusinessException("Invalid account number!");
        }
    }

    private boolean isValid(String number) {
        int sum = 0;
        for (int i = 0; i < number.length(); i++) {
            sum = sum + (9 - i) * Character.getNumericValue(number.charAt(i));
        }
        return sum % 11 == 0;
    }
}


public class SavingsAccount extends Account {
    CheckingAccount registeredCounterAccount;

    @Override
    public Transfer makeTransfer(String counterAccount, Money amount)
        throws BusinessException {
        Transfer result = super.makeTransfer(counterAccount, amount);
        if (result.getCounterAccount().equals(this.registeredCounterAccount)) {
            return result;
        } else {
            throw new BusinessException("Counter-account not registered!");
        }
    }
}



public class CheckingAccount extends Account {
    private int transferLimit = 100;

    @Override
    public Transfer makeTransfer(String counterAccount, Money amount)
        throws BusinessException {
        if (amount.greaterThan(this.transferLimit)) {
            throw new BusinessException("Limit exceeded!");
        }
        return super.makeTransfer(counterAccount, amount);
    }
}
```


---

# 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://ssosso.gitbook.io/study/dev-build-up/undefined/4..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.
