Debug It! 실용주의 디버깅 (20141026, 마지막)
내용은 알차나 생각보단 큰 파급력은 없는 좀 그저 그런 책. 각 장 뒤에 나온 요약을 적어둔다.
- 구조적인 접근
- 다음을 꼭 지키자
- 소프트웨어가 왜 이상하게 작동되는지 알기
- 문제를 고치기
- 다른 부분을 깨뜨리지 않기
- 전반적인 품질 유지나 향상시키기
- 같은 문제가 다른 곳에도 있는지 확인하고 재발을 막기
- 소프트웨어를 잘 활용해 어떤 일이 벌어지는지를 보여주자.
- 한 번에 한 문제만 해결하자.
- 무엇을 찾고 있는지를 정확하게 알자.
- 어떤 일이 벌어지고 있는가?
- 어떻게 실행돼야 하는가?
- 간단한 것부터 먼저 살피자.
- 다음을 꼭 지키자
- 재현
- 무엇보다도 먼저 재현 방법을 찾자.
- 버그가 발견된 버전의 소프트웨어를 실행하자.
- 재현하려는 환경을 버그가 발견된 환경과 똑같이 만들자.
- 버그 재현에 꼭 필요한 입력을 다음 방법을 통해서 찾자.
- 추론
- 로그로 의심 가는 입력을 기록
- 재현 방법을 반복해서 다듬어 신뢰할 수 있고 편리하게 만들자.
- 재현 단계, 데이터 크기, 시간을 줄인다.
- 비결정성 제거
- 자동화
- 진단
- 가설을 세운 후 실험으로 확인한다.
- 실험으로 무엇을 알고 싶은지를 분명히 안다.
- 한 번에 하나만 수정한다.
- 지금까지 시도해 본 것들을 기록한다.
- 아무것도 무시하지 않는다.
- 제대로 되지 않는다면
- 수정해도 효과가 없는 것 같다면 원했던 부분을 고친 게 아니다.
- 가정을 확인한다.
- 원인이 여러 개인 것은 아닌지? 내부 시스템을 변경하는 것은 아닌지?
- 진단을 확인한다.
- 가설을 세운 후 실험으로 확인한다.
- 수정
- 버그 수정헤는 다음 3가지 목표가 있다.
- 문제 수정
- 회귀 방지
- (가독성, 아키텍쳐, 테스트 커버리지 같은) 전반적인 코드 품질을 유지하거나 향상시키기
- 깨끗한 소스에서 시작한다.
- 코드를 변경하기 전에 먼저 모든 테스트가 통과하는지 확인한다.
- 변경하기 전에 수정된 것을 어떻게 테스트할지 고민한다.
- 증상이 아닌 원인을 고친다.
- 리팩토링 한다. 하지만 기능을 변경하면서 동시에 하지 마라.
- 로직을 하나 바꿀 때마다 체크인한다.
- 버그 수정헤는 다음 3가지 목표가 있다.
- 반영
- 근본 원인 분석에 시간을 할애하자.
- 개발 과정 중 어느 시점에서 에러가 발생했는가?
- 무엇이 잘못됐는가?
- 문제 재발을 방지하자.
- 문제를 자동으로 검사하자.
- 잘못 사용할 수 없게 코드를 리팩토링하자.
- 동료와 얘기하고, 필요하다면 프로세스를 고치자.
- 다른 개발자와 함께 선순환 구조를 만들자.
- 근본 원인 분석에 시간을 할애하자.
- 문제 발견
- 버그 추적 시스템
- 각자의 사정에 맞는 수준의 것을 고르자.
- 사용자가 직접 사용할 수 있게 하자.
- 리포트의 정확도를 위해 환경과 설정에 대한 리포트를 자동화 하자.
- 버그 리포트는 다음을 목표로 한다.
- 명확하게
- 애매한 구분 없이
- 상세하게
- 최소로
- 유일하게
- 사용자와 같이 작업할 때는 다음을 따르자.
- 버그 제출 프로세스를 최적화한다.
- 의사소통이 핵심이다. 참을성을 갖고 사용자의 임장에서 생각해보자.
- 고객 지원 팀, QA 팀과의 좋은 관계를 조성하고, 버그를 고치는 동안 그들의 지원을 최대한 활용하자.
- 버그 추적 시스템
- 실질적인 무관용
- 버그는 최대한 빨리 찾고, 찾자마자 수정하자.
- 버그 없는 소프트웨어를 만들 수 있다는 마음가짐으로 행동하되, 실용주의를 가미한 완벽주의를 따르자.
- 코드의 품질이 나쁠 때는 다음과 같이 하자.
- 은탄환은 없다는 사실을 알자.
- 기초를 먼저 세우자.
- 깨끗한 코드를 더러운 코드로부터 격리하고, 계속 깨끗하게 유지 하자.
- 버그 선별을 통해서 버그 데이터베이스의 최상위 버그부터 작업 하자.
- 점진적으로 나쁜 코드에 테스트를 추가하고 리팩토링해 정리 하자.
- 특수한 경우
- 기존 릴리스를 패치할 때는 위험을 줄이는 데 집중하자.
- 버그를 고칠 때는 호환성 문제가 없을지 주의하자.
- 시간 틈(timing window)이 있다면 이를 줄이려고 하지 말고 아예 없애자.
- 하이젠버그를 만났을 때는 정보 수집할 때 생기는 부작용을 최소화 하자.
- 성능 버그를 고칠 때는 항상 프로파일링을 정확하게 하는 것부터 시작하자.
- 아무리 통신 채널이 제한돼 있어도 우리에게 필요한 정보를 얻어내기에는 충분할 수 있다.
- 서드파티 코드보다는 우리가 작성한 코드를 먼저 의심하자.
- 이상적인 디버깅 환경
- 테스트를 자동화하고 다음과 같이 만든다.
- 통과/실패를 명확하게
- 독립적이게
- 한 번 클릭만으로 실행할 수 있게
- 충분한 커버리지를 제공하게
- 테스트를 자동화하고 다음과 같이 만든다.
- 소프트웨어가 스스로를 디버깅하게 만들기
- 다음을 하기 위해 단언문을 사용하자.
- 문서화를 위해, 그리고 가정을 자동으로 검증하기 위해
- 우리의 소프트웨어가 제품에서는 견고해도 디버깅 중에는 잘 깨지게 하기 위해
- 다음과 같은 디버깅 빌드를 만들자.
- 디버그하기 좋은 옵션으로 컴파일한 디버깅 빌드
- 핵심 하위시스템을 디버깅용으로 교체할 수 있는 디버깅 빌드
- 진단에 유용한 기능을 제공할 수 있는 제어 기능이 들어가 있는 디버깅 빌드
- 자원 누수나 예외 처리 문제 같은 조직적인 문제를 먼저 찾아내자.
- 다음을 하기 위해 단언문을 사용하자.
- 안티 패턴
- 버그 데이터베이스를 관리해서 버그의 실제 우선순위를 잘 반영하게 한다.
- 오염자 부담(polluter pay) : 하던 일을 완전히 끝내기 전에는 누구도 새로운 작업을 할 수 없게 한다. 버그가 생기면 그 작업을 했던 사람이 고치게 한다.
- 한 팀이 한 제품을 처음부터 배포, 그 이후까지 맡게 한다.