> For the complete documentation index, see [llms.txt](https://ssosso.gitbook.io/study/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ssosso.gitbook.io/study/dev-build-up/undefined/4..md).

# 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);
    }
}
```
