-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #46 from yeslee-v/44-3장-코드와-함께-춤을
44 3장 코드와 함께 춤을
- Loading branch information
Showing
2 changed files
with
251 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
# 3장 코드와 함께 춤을 | ||
|
||
## 소프트웨어 엔트로피는 늘어나게 마련이다 | ||
|
||
- 코드가 지저분해지는 것을 소프트웨어 엔트로피(software entropy)라고 한다. | ||
|
||
- 개발자가 다른 사람이 쓴 코드를 이해하지 못하거나 서로 코딩 스타일이 달라서 발생한다. | ||
|
||
- 기술 스택과 제품 요구사항을 개선하다 보면 혼란이 가중된다. | ||
|
||
- 코딩 스타일과 버그 탐지 도구, 코드 리뷰와 지속적인 리팩토링은 엔트로피를 낮출 수 있다. | ||
|
||
## 결코 피할 수 없는 기술 부채 | ||
|
||
- 기술 부채(technical debt)는 소프트웨어 엔트로피를 가중시키는 주요 원인으로 기존 코드의 단점을 수정하면서 나중으로 미뤄둔 작업을 말한다. | ||
|
||
- 신중히 고민하고 의도적으로 만들어진 부채(예. 일단 출시하고 결과를 보고 대처)는 보편적으로 발생한다. | ||
|
||
- 신중하지 못했지만 의도적으로 만들어진 부채(예. 설계할 시간이 없어요)는 주로 팀이 출시일 압박을 받는 상황에서 만들어진다. | ||
|
||
- 어떤 결정이 신중하지 못한 부채임을 의미하는 단어는 '일단'이다. | ||
|
||
- 신중하지도 못하고 의도치도 않았던 부채(예. 계층화가 도대체 뭔가요?)는 몰라서 모르는 것들(unknown unknowns; 알려지지 않은 미지) 때문에 발생한다. | ||
|
||
- 신중했지만 의도치 않게 발생되는 부채(예. 뭘 실수했는지 이젠 알겠네요)는 성장 과정에서 자연스럽게 나타나는 결과다. | ||
|
||
- 건전한 팀은 프로젝트 회고(retrospective)같은 절차를 활용해 의도치 않았던 부채를 찾아내고 부채의 해결 여부와 적절한 해결 시점을 논의한다. | ||
|
||
- 부채는 프로젝트가 지저분해질 정도로 오래 살아남았다는 의미도 담고 있으므로 성공의 표시일 수도 있다. | ||
|
||
## 기술 부채를 상환하는 방법 | ||
|
||
- 업무를 진행하면서 필요한 부분은 정리하고 조금씩 리팩토링을 하자. | ||
|
||
- 변경사항은 작고 독립적인 커밋과 PR(풀 리퀘스트)로 만들자. | ||
|
||
- 단기적인 관점에서 기술 부채를 해결하다 보면 새 기능의 출시가 늦어지지만, 부채를 더 많이 쌓아두면 출시가 빨라진다. | ||
|
||
- 반대로 장기적인 관점에서는 부채를 해결하면 출시 속도가 빨라지고 부채를 쌓아두면 오히려 출시 속도가 느려진다. | ||
|
||
- 기술 부채를 논의하는 좋은 방법 | ||
|
||
1. 상황을 사실 그대로 설명한다. | ||
|
||
2. 부채의 위험과 비용을 기술한다. | ||
|
||
3. 해결책을 제안한다. | ||
|
||
4. (부채를 그대로 두는 방법을 비롯해) 대안에 대해 논의한다. | ||
|
||
5. trade off를 따져본다. | ||
|
||
- 제안 내용은 문서로 작성하고 여러분 각자가 판단한 가치가 아닌 부채를 해결하는 데 드는 비용과 그로 인해 얻을 수 있는 장점에만 집중하자. | ||
|
||
## 코드 변경으로 인한 고통을 조금이라도 줄이려면 | ||
|
||
- 코드 변경은 기존의 동작을 유지하고 기존 스타일과 패턴을 유지한 채 진행되어야 한다. | ||
|
||
- 새 기능 추가, 리팩토링, 코드 삭제 또는 버그 수정 등 코드를 변경하는 기법은 거의 같다. | ||
|
||
### 레거시 코드 변경 알고리즘을 활용하자 | ||
|
||
- 기존 코드를 안전하게 수정할 수 있는 과정 by 레거시 코드 활용 전략(마이클 C.페더스 지음) | ||
|
||
1. 변경 지점을 확인한다. | ||
|
||
2. 테스트할 지점을 확인한다: 수정하고자 하는 코드의 진입점으로 테스트가 직접 호출하고 값을 넣어주는 부분 | ||
|
||
3. 의존성(dependency)을 나눈다: 코드를 테스트하기 위해 필요한 객체나 메서드로 테스트가 용이하지 않은 코드의 구조를 바꾼다. 이 때 코드의 동작이 바뀌면 안된다. | ||
|
||
- 크고 복잡한 메서드는 더 작은 크기의 메서드로 나눠 각각 분리된 기능이 독립적으로 테스트될 수 있게 한다. | ||
|
||
- 인터페이스(또는 그 밖의 간접성)을 이용해 복잡한 객체를 테스트하기 충분한 단순 구현체로 대체할 수 있는 방법을 마련한다. | ||
|
||
- 제어하기 어려운 실행 환경(예. 시간의 흐름)을 시뮬레이션할 수 있는 명시적 제어 지점을 주입한다. | ||
|
||
4. 테스트를 작성한다. | ||
|
||
5. 변경을 적용하고 리팩토링한다: 설계 고도화 과정 | ||
|
||
### 코드는 처음보다 더 깔끔하게 유지하자 | ||
|
||
- 버그를 수정하거나 새로운 기능을 추가할 때는 주변 코드를 정리하자. | ||
|
||
- 코드를 정리하는 커밋은 동작을 변경하는 커밋과 구분하자. | ||
|
||
- 커밋의 크기가 작을수록 변경사항을 리뷰하기도 편하다. | ||
|
||
- 업무를 진행하면서 코드 악취(code smell; 버그는 아니지만 문제를 유발할 수 있는 패턴을 사용하는 코드)를 대상으로 삼자. | ||
|
||
### 점진적으로 변경하자 | ||
|
||
- 리팩토링은 대부분 둘 중 한가지 유형을 띈다. | ||
|
||
- 수십 개의 파일을 한 번에 수정하는 '모조리 바꿔' 식의 변경 | ||
|
||
- 리팩토링과 새로운 기능이 섞인 PR | ||
|
||
- 두 유형은 리뷰하기가 어려우므로 리팩토링 커밋은 작게 유지한다. | ||
|
||
- 리팩토링을 마구잡이로 수행하기 앞서 우선 팀의 동의를 얻어야 한다. | ||
|
||
### 리팩토링은 실용적으로 진행하자 | ||
|
||
- 새로운 기능을 출시하기 위해 리팩토링을 미루는 결정은 오히려 올바른 결정일 수도 있다. | ||
|
||
- 오래되고 사용되지 않는(deprecated) 코드나 위험도가 낮은, 거의 호출되지 않는 코드는 리팩토링이 필요없다. | ||
|
||
### IDE(integrated development environment; 통합 개발 환경)를 활용하자. | ||
|
||
- 가능하다면 도구의 장점을 활용하자. | ||
|
||
- IDE를 이용한 리팩토링은 간단한 수정만으로도 엄청난 양의 코드를 변경할 수 있으므로 반드시 사람이 리뷰해야 한다. | ||
|
||
### 버전 제어 시스템(version control system)의 권장 기법을 활용하자 | ||
|
||
- 코드를 개발하는 동안 변경사항은 일찍 그리고 자주 커밋해야 한다. | ||
|
||
- 리뷰를 요청하기 전에는 브랜치를 rebase하거나 커밋을 squash해서 커밋 메시지를 명료하게 정리하자. | ||
|
||
- 보통 [이슈 ID]-[커밋 메시지] 형식으로 작성한다. | ||
|
||
- 팀에 커밋 메시지 규칙이 없다면 [git 커밋 메시지를 작성하는 7가지 요령](https://cbea.ms/git-commit/)을 따르는 것도 좋다. | ||
|
||
- 제목과 본문 사이에 빈 줄은 한 행 삽입한다. | ||
|
||
- 제목은 50자 이내로 제한한다. | ||
|
||
- 제목은 대문자로 쓴다. | ||
|
||
- 제목 끝에 마침표를 붙이지 않는다. | ||
|
||
- 제목은 명령형 문장으로 작성한다. | ||
|
||
- 본문의 각 행은 72자가 넘지 않게 한다. | ||
|
||
- 본문에는 코드가 '어떻게' 바뀌었는지보다는 '무슨' 코드가 '왜' 바뀌었는지를 설명한다. | ||
|
||
## 소프트웨어 개발에서 빠지기 쉬운 함정을 최대한 피하려면 | ||
|
||
- 대부분의 엔지니어는 규칙의 가치에 대해서는 과소평가하고 규칙을 무시하는 행위의 가치는 과대평가하는 경향이 있다. | ||
|
||
- 코드를 재작성하거나 규칙을 깨뜨리거나 또는 기술 스택에 새로운 기술을 추가할 때는 주의를 기울이자. | ||
|
||
- 가능하다면 평범한 기술을 사용하자. | ||
|
||
- 설령 동의하기 어렵더라도 규칙을 무시해서는 안되며, 코드를 fork하는 상황은 피하자. | ||
|
||
### 되도록 검증된 기술을 사용하자 | ||
|
||
- 성공적인 기업이 오래된 라이브러리와 오래된 패턴으로 견고한 코드를 유지할 수 있는 데는 이유가 있다. | ||
|
||
- 성공을 거두는 데는 시간이 걸리며, 기술을 갈아타는 것은 집중을 방해하는 요소가 되기 때문이다. | ||
|
||
- 새로운 기술은 성숙하지 못하다(낮은 안정성, 미흡한 문서화, 낮은 호환성, 작은 커뮤니티 규모 등)는 문제를 갖고 있다. | ||
|
||
- [평범한 기술은 어디서 문제가 발생하는지 잘 알려져 있다는 장점이 있다.](https://boringtechnology.club/) | ||
|
||
- 새로운 기술을 도입했을 때의 장점이 도입 비용보다 커야 한다. | ||
|
||
- 신기술이 회사의 경쟁력을 높여줄 수 있다면 그 기술을 도입할 만한 가치가 있다. | ||
|
||
- 새로운 프로그래밍 언어를 도입했을 때 획득할 수 있는 장점과 약점을 균형있게 고려해야 한다. | ||
|
||
- 새로 선택하는 프로그래밍 언어의 생태계가 얼마나 성숙해 있는지는 특히 중요하다. | ||
|
||
- 빌드 및 패키징 시스템은 잘 갖춰져 있는가? | ||
|
||
- IDE 지원 수준은 어떤가? | ||
|
||
- 주요 라이브러리는 경험이 풍부한 개발자가 관리하고 있는가? | ||
|
||
- 테스트 프레임워크가 있는가? | ||
|
||
- 관련 기술을 가진 엔지니어를 고용할 수 있는가? | ||
|
||
- 얼마나 쉽게 배울 수 있는가? | ||
|
||
- 언어의 성능은 어떤가? | ||
|
||
- 언어의 생태계는 회사의 기존 도구와 잘 통합이 되는가? | ||
|
||
- 언어가 사장되지 않는 한, 단지 오래됐다거나 관심이 줄었다는 사실이 그 언어를 사용하지 않을 이유는 되지 못한다. | ||
|
||
### 제발 악동은 되지 말자 | ||
|
||
- 단지 마음에 들지 않는다는 이유로 회사(또는 업계)의 표준을 무시하면 안된다. | ||
|
||
- 단기적으로는 다른 사람이 하는 대로 따르면서 그 방법이 표준으로 채택된 이유를 되도록 이해하자. | ||
|
||
- 표준을 바꿀 때는 실용주의적 사고(우선순위, 소유권, 비용 등)에 입각해 대처해야 한다. | ||
|
||
## upstream 커밋 없이 fork만 하는 것은 금물이다 | ||
|
||
- 코드에 기여할 생각이 없으면서 해당 리포지토리를 포크하는 것은 권장되지 않는다. | ||
|
||
- 보통은 해당 프로젝트의 방향이 마음에 들지 않거나 원래 프로젝트가 취소되거나 주 레포지토리에 변경사항을 병합하는 것을 허락받기가 어려운 상황에서 주로 fork를 한다. | ||
|
||
- 회사 내부에서 fork한 리포지토리를 관리하는 것은 위험하다. | ||
|
||
### 코드 재작성에 대한 욕구를 견디자 | ||
|
||
- 코드 재작성은 그에 들어가는 비용보다 장점이 클 때만 시도해야 한다. | ||
|
||
## 개발자의 필수 체크리스트 | ||
|
||
### 이것만은 지키자 | ||
|
||
- 점진적으로 리팩토링하자. | ||
|
||
- 리팩토링 커밋과 기능 관련 커밋은 분리하자. | ||
|
||
- 변경사항을 작게 유지하자. | ||
|
||
- 처음 상태보다 코드를 더 깔끔하게 유지하자. | ||
|
||
- 평범한 기술을 사용하자. | ||
|
||
### 이것만은 피하자 | ||
|
||
- '기술 부채'라는 단어를 남용하지 말자. | ||
|
||
- 테스트를 목적으로 메서드나 변수를 외부에 공개해서는 안된다. | ||
|
||
- 특정 언어에 연연하지 말자. | ||
|
||
- 회사의 표준과 도구를 무시해서는 안된다. | ||
|
||
- upstream 커밋 없이 코드 베이스를 fork해서는 안된다. | ||
|
||
## 레벨업을 위한 읽을거리 | ||
|
||
- 레거시 코드 활용 전략(마이클 C.페더스 지음, 이정문 외 옮김) | ||
|
||
- The Legacy Code Programmers'Toolbox(Jonathan Boccara 지음) | ||
|
||
- https://martinfowler.com/ | ||
|
||
- 리팩토링 2판(Martin Fowler 지음, 개앞맵시 외 옮김) | ||
|
||
- [맨먼스 미신(Fred Brooks 지음, 강중빈 옮김)](https://product.kyobobook.co.kr/detail/S000001033010) |