실용주의 프로그래머 읽어보기 6주차
실용주의 프로그래머 읽어보기 6주차
들어가며
이 포스트는 데이비드 토머스, 앤드류 헌트의 「실용주의 프로그래머」 Topic37 ~ 41까지 읽고 개인적으로 학습한 내용을 정리한 글입니다.
- 책: 실용주의 프로그래머
- 저자: 데이비드 토머스, 앤드류 헌트
- 출판사: 인사이트
- 챕터: Topic 37 ~ Topic 41
핵심 내용 정리
프로그램이 정확하게 생산적으로 작동하면서 천수를 누리도록 하려면 사려 깊은 생각과 판단으로 결정을 내려야한다
Topic 37. 파충류의 뇌에 귀 귀울이기
- 상관없이 모든 본능에는 공통점이 있다. 말로 표현할 수 없다는 것, 생각이 아니라 ㄴ낌이라는 점
백지의 공포
- 누구나 텅 빈 화면을 두려워한다
- 원인
- 파충류의 뇌가 여러분에게 무언가 할 말이 있어서
- 인식의 지평 바로 밑에 도사리고 있는 모종의 의심
- 어떤 작업을 앞두고 마음 속에 의심이 계속 남아 있거나 왠지 꺼림칙하다면, 자신의 경험이 자신에게 말을 거는 중일지도 모른다
- 자신이 실수할까봐 두려운 것
- 코드의 오류를 자신의 부족한 능력 때문이라고 받아들일 수도 있다
- 파충류의 뇌가 여러분에게 무언가 할 말이 있어서
자신과 싸우기
- 생각을 비트로 바꾸는 일이 전혀 힘들지 않은 날이 있고, 코딩이 진창에서 오르막길을 걷는 것처럼 느껴지는 날도 있다
- 잘 나아가지 않는 다면 자신의 코드가 무언가를 말하려는 것이다
파충류와 이야기하는 법
Tip 61 여러분 내면의 파충류에게 귀 기울여라
- 하고 있는 일을 멈추고, 자신의 뇌가 정리를 좀 할 수 있도록 약간의 시간과 공간을 확보하라
- 이 방법이 잘 되지 않으면 문제를 표면으로 끄집어내 보라
- 작성한 코드에 대해 그림을 그리거나, 동료에게 설명해 보기
놀이 시간이다!
- 괜찮은 자기기만
- 자신에게 무언가를 프로토타이핑해야 한다고 자신에게 말하는 것
- 꺼림칙했던 느낌이 코딩 도중에 갑자기 명확한 문제로 구체화되면 즉각 해결하라
- 실험을 끝마쳤는데도 여전히 불안한 마음이 들면 다시 처음부터 시작하라 => 첫 단계는 산책, 수다, 휴식
‘여러분’의 코드뿐이 아니다
- 다른 사람이 작성한 코드를 다루는 경우
- 다른 사람의 코드를 기계적으로 읽으면서 중요한 대목을 메모
- 처리 방식이 이상해 보이는 부분이 눈에 띄면 작성
코드뿐이 아니다
- 직감에 귀 기울이는 방법은 계속 갈고닦아야 할 중요한 기술
Topic 38. 우연에 맡기는 프로그래밍
- 우리는 의도적으로 프로그래밍 해야 한다
우연에 맡기는 프로그래밍 하기
구현에서 생기는 우연
- 단순히 코드가 지금 작성된 방식이 그렇기 때문에 생기는 우연한 일들이 있다. 이런 우연에 기대다 보면 결국 문서화되지 않은 에러나 예외적인 경우의 동작에 의존하게 되고 만다
- 의존의 함정에 빠지는 이유
- 정말로 제대로 돌아가는 게 아닐지도 모른다
- 우리가 의존하는 조건이 단지 우연인 경우도 있다
- 문서화되지 않은 동작은 라이브러리의 다음 릴리스에서 변경될 수도 있다
- 불필요한 추가 호출은 코드를 더 느리게 만든다
- 추가로 호출한 루틴에 새로운 버그가 생길 수도 있다
비슷하다고 괜찮을 리는 없다
- 유사한 패턴이라도, 근본적인 문제를 해결하지 않았다면 무의미하다
유령 패턴
- 우연에 불과한 것들을 인간은 패턴과 인과 관계를 맺으려한다
상황에서 생기는 우연
- 잘 되는 듯한 답을 찾는 것과 올바른 답을 찾는 것은 다르다
암묵적인 가정
- 확고한 사실에 근거하지 않은 가정은 어떤 프로젝트에서든 재앙의 근원이 된다
의도적으로 프로그래밍하기
- 언제나 여러분이 지금 무엇을 하고 있는지 알아야 한다
- 더 경험이 적은 프로그래머에게 코드를 상세히 설명할 수 없으면 아마 우연에 기대고 있는 것이다
- 자신도 잘 모르는 코드를 만들지 말라
- 계획을 세우고 그것을 바탕으로 진행하라
- 신뢰할 수 있는 것에만 기대라. 가정에 의존하지 말라
- 가정을 기록으로 남겨라
- 코드뿐 아니라 여러분이 세운 가정도 테스트해보아야 한다
- 노력을 기울일 대상의 우선순위를 정하라. 중요한 것에 먼저 시간을 투자하라
- 과거의 노예가 되지 말라. 기존 코드가 앞으로 짤 코드를 지배하도록 놓아두지 말라
Topic 39 알고리즘의 속도
알고리즘을 추정한다는 말의 의미
- 중요한 알고리즘은 대부분 선형적이지 않다
- 많은 알고리즘의 증가폭이 선형보다 작지만, 나머지 알고리즘들은 증가폭이 선형보다 훨씬 크다 => 즉, 수행 시간이나 메모리 요구량이 n보다 훨씬 빠르게 늘어난다
상식으로 추정하기
단순 반복문
- O(n)
- exhaustive search, 배열에서 최댓값 찾기, 체크섬 생성 등
중첩 반복문
- O(n * n)
- 버블 정렬이나 간단한 정렬 알고리즘
반씩 자르기’
- O(log n)
- 이진 트리 탐색, 정수의 2진수 표현
분할 정복
- O(log n)
- 퀵 정렬 등
조합적
- 순열, factorial 등
실전에서의 알고리즘 속도
Tip 63 사용하는 알고리즘의 차수를 추정하라 Tip 64 여러분의 추정을 테스트하라
Topic 49 리팩토링
- 마틴 파울러의 리팩토링
- 밖으로 드러나는 동작은 그대로 유지한 채 내부 구조를 변경함으로써 이미 존재하는 코드를 재구성하는 체계적 기법
리팩터링은 언제 하는가?
- 중복을 발견했을 때
- 더 직교적으로 바꿀 수 있는 무언가를 발견했을 때
- 코드가 지금 상황에 뒤떨어졌을 때
- 꼭 필요한 기능에
- 성능 감소
- 테스트를 통과할 때
현실 세계의 복잡한 문제들
Tip 65 일찍 리팩터링하고, 자주 리팩터링하라
- 대부분의 일처럼 리팩터링도 문제가 작을 때, 코딩하는 동안 함께 진행하는 편이 더 쉽다
리팩터링은 어떻게 하는가?
- 리팩터링과 기능 추가를 동시에 하지 말라
- 리팩터링 시작 전 든든한 테스트가 있는지 확인해라
- 단계를 작게 나누어 신중하게 작업하라. 단계를 작게 나누고, 한 단계가 끝날 때마다 테스트를 돌린다면 기나긴 디버깅 작업을 피할 수 있다
Topic 41 테스트로 코딩하기
Tip 66 테스트는 버그를 찾기 위한 것이 아니다
테스트가 코딩을 주도한다
Tip 67 테스트가 코드의 첫 번째 사용자다
- 테스트는 우리의 코딩을 인도하는 필수 피드백이다
TDD
- TDD의 기본 주기
- 추가하고 싶은 작은 기능 하나를 결정한다
- 그 기능이 구현되었을 때 통과하게 될 테스트를 하나 작성한다
- 테스트를 실행한다. 다른 테스트는 통과하고 바금 추가한 테스트 딱 하나만 실패해야 한다
- 실패하는 테스트를 통과시킬 수 있는 최소한의 코드만 작성한다. 그리고 이제 모든 테스트가 통과하는지 확인한다
- 코드를 리팩터링한다. 방금 작성한 테스트나 함수를 개선할 수 있는 부분이 없는지 살펴본다. 개선한 후에도 테스트가 계속 통과하는지 확인한다
TDD: 목표가 어디인지 알아야한다
Tip 68 상향식이나 하향식이 아니라 끝에서 끝까지 만들어라
단위테스트
- 소프트웨어 단위 테스트란 어떤 모듈에게 이것저것을 시켜보는 코드를 가리킨다
- 일종의 인위적인 환경을 구축하고, 테스트할 모듈의 루틴들을 호출
- 반환된 결과들을 이미 알고 있는 값과 비교하거나 똑같은 테스트를 이전에 돌렸을 때 나온 값과 비교해 올바른지 검사
- 이를 회귀 테스트(regression testing)이라 한다
계약을 지키는지 테스트하기
Tip 69 테스트할 수 있도록 설계하라
- 단위 테스트를 계약을 잘 지키는지 보는 테스트라 여김
- 단위 테스트가 알려주는 두 가지
- 코드가 계약을 잘 지키는 지
- 코드로 표현된 계약의 의미가 우리가 생각한 것과 일치하는지 여부 확인
테스트 접점 만들기
- 아무리 테스트를 잘 갖추었어도 모든 버그를 발견할 수는 없다
- 로그 파일을 통한 추적 메시지를 통해 어떤 모듈의 내부 상태를 다양한 형태로 볼 수 있는 방법이 있다
테스트 문화
Tip 70 여러분의 소프트웨어를 테스트하라. 그러지 않으면 사용자가 테스트하게 된다
- 소프트웨어를 철저하게 테스트할 계획을 세우는 것이 좋다
- 우리의 선택지는 셋 중 하나다. “테스트 먼저”, “코드와 테스트를 함께”, “테스트하지 않음”
This post is licensed under CC BY 4.0 by the author.