# 3. 10년 이상 쓸 수 있는 지속 가능한 코드 작성
###### tags: `지호`, `프론트엔드 Back to the Basics`
---
## 1. 좋은 코드란 무엇인가
### 좋은 코드
- 사람이 읽기 좋아야 한다
- 간결하고 의도가 명확해야한다
- 의존성이 적어야한다
- 하나의 함수, 메소드, 클래스는 각각 명확한 하나의 책임만 지녀야한다
### 디버깅
1. 정상 시스템의 동작, 그러니까 기대하는 동작을 정의한다
2. 원인을 섣불리 추측하지 않고, 일단은 "모른다"고 생각하고 출발한다
3. 근본적인 원인을 알 때까지 최대한 많은 데이터를 모으며 현상을 관찰한다
4. 증상이 아닌 원인을 수정한다
<br/>
## 2.테스트와 TDD, BDD
### 테스트
- 실행 속도가 빨라야 한다
- 내부 구현을 변경했다고 해서 테스트를 실패하면 안된다
- 입출력 위주의 인터페이스를 중심으로 작성한다
- 버그를 찾을 수 있어야 한다
- 테스트 결과에 일관성이 있어야 한다
- 의도가 명확히 드러나야 한다
### 코드 커버리지
- 보통 라인 수를 기준으로 측정
- 70%를 넘으면 훌륭
### TDD와 BDD
- 테스트를 먼저 작성하고 그 후 실제 코드를 작성하는 방법
- 장점
- 테스트를 먼저 작성하기 때문에 전체 코드에서 얼마나 많은 코드가 테스트되는가를 측정하는 테스트 커버리지 비율이 자연스럽게 높아진다
- 테스트 되는 것만 코드로 작성하므로 코드가 방대해지지 않는다
- 버그때문에 발생하는 시간 낭비 줄여주고, 코드가 원하는 바를 명확히 달성하는지 쉽게 확인할 수 있다
- 방법
1. 테스트를 먼저 작성한다 (만족하는 코드가 없는 상태이므로 당연히 테스트는 실패)
2. 테스트를 통과하는 코드를 작성한다
3. 리팩토링: 중복이 보이거나 더 개선할 방법이 있다면 코드를 개선
<br/>
## 3. 리팩토링
### 대상
- 너무 큰 함수나 클래스
- 이름이 명확하지 않은 함수나 변수 이름
- 중복 코드
- 전역 변수 -> 가능하면 함수 내 혹은 모듈 내에 두자
- 과도한 콜수, 조건문 중첩
- 과도하게 긴 식별자
### 방법
1. 함수 추출 혹은 옯기기: 로직을 별도의 함수나 모듈로 분리
2. 중간 변수 도입: 어떤 값인지 설명하는 중간 변수
3. var는 let, const로 변환
4. 함수의 사이드 이펙트 최소화 -> 순수함수 ( 똑같은 입력이 주어졌을 때 똑같은 출력이 나오는 함수)
5. 빠른 실패 (fast fail)
6. 반복문 보다는 파이프 (filter, forEach...)
7. switch 대신 object literal
```javascript=
function sayJob(job) {
switch(job) {
case 'engineer':
console.log('엔지니어');
break;
case 'developer':
console.log('개발자');
break;
case 'designer':
console.log('디자이너');
break;
}
}
to
function sayJob(job) {
const translated = {
engineer: '엔지니어',
developer: '개발자',
designer: '디자이너',
};
console.log(translated[job]);
}
```
9. 배열이나 객체는 불변 객체처럼 Immutable하게 다루기
```javascript=
const blackPink = [ '지수', '제니', '로제', '리사' ];
blackPink.forEach((value, index) => {
blackPink[index] += '❤️';
});
console.log(blackPink);
to
const blackPink = [ '지수', '제니', '로제', '리사' ];
const blackPinkWithLove = blackPink.map((value, index) => {
blackPink[index] += '❤️';
});
console.log(blackPinkWithLove);
```
10. 문자열 합치기 보다는 ES6 템플릿 문자열