2018.11.04

실용주의 프로그래머 요약

요약 갈무리

서론

  • 실용주의 프로그래머는 무엇이 다른가? (...) 문제를 항상 더 큰 맥락에 놓으려 노력하고, 항상 더 큰 그림을 보려 한다.

1 고양이가 내 소스코드를 삼켰어요

  • 실용주의 프로그래머는 경력에 대해 책임을 지고, 자신의 무지나 실수를 인정하기를 두려워하지 않는다.
  • 다른 사람이나 다른 무언가를 비난하거나 변명을 만들어 내지 말라.
  • 변명 대신에 대안을 제시하라. 안 된다고 하지 말고 상황을 개선하기 위해 무엇을 할 수 있는지 설명하라.

2 소프트웨어 엔트로피

  • 도심에서 어떤 건물은 아름답고 깨끗한 반면, 다른 건물은 썩어 가는 유령선 같다. 왜? 깨끗하고 온전하며 사람들이 거주하는 건물이, 부서지고 황폐한 을씨년스러운 곳으로 금세 바뀌어 버리는 이유는 뭘까? (...) 사람들은 아주 재미있는 유인 메커니즘을 발견했다. 깨진 창문.

  • 깨진 창문을 내버려두지 말라. '깨진 창문'을 고치지 않는 채로 내버려 두지 말라. 발견하자마자 바로 고쳐라. 적절히 고칠 시간이 충분하지 않다면 판자로 덮는 것만이라도 하라. 불쾌한 코드를 주석처리하거나, 아직 구현되지 않았음이라는 메시지를 표시하거나, 가짜 데이터로 대치해 놓거나 하라. 더 이상의 손상을 예방하기 위해 어떤 조치든 취하고 현 상황을 잘 관리하고 있다는 것을 보여줘라.

  • 엔트로피가 우리를 지배하도록 내버려 두지 마라.

3 돌멩이 수프와 삶은 개구리

  • 전쟁을 마치고 집으로 돌아가는 군인 세 명이 배가 고팠다. (...) 큰 냄비에 물을 끓인 다음 돌멩이 세 개를 조심스레 넣었다. 놀란 마을 사람들이 이 광경을 지켜보려고 밖으로 나왔다. "이건 돌멩이 수프입니다." 군인들이 말했다. "그것만 집어넣는 거예요?"라고 마을 사람들이 물었다. (...) 마을 사람 하나가 달려가더니 금세 자신의 비밀 창고에서 당근 한 바구니를 갖고 나왔다. (...) 그들은 결국 큰 냄비 가득 김이 모락모락 나는 수프를 만들어 냈다.

  • 허락을 구하는 때부터, 뭔가가 지연되거나 사람들이 멍한 눈으로 여러분을 바라본다. 위원회가 생길 테고, 예산 승인이 필요하고, 일들이 복잡해지기 시작한다. 모든 사람이 각자 자신의 자원을 지키려고 할 것이다. 때때로 이걸 '시작 피로(start-up fatigue)'라고 부른다. 돌멩이를 내놔야 할 때다. 큰 무리 없이 요구할 수 있을 만한 것을 찾아내라. 그리고 그걸 잘 개발하라. 일단 되면, 사람들에게 보여주고, 그들이 경탄하게 하라. (...) 그들에게 미래를 살짝이라도 보여주면 그들은 원조를 위해 집결할 것이다.

  • 사람들은 개구리를 잡아서 끓는 물 속에 넣으면 곧바로 튀어나와 버릴 거라고 한다. 그렇지만 차가운 물이 든 냄비 속에 개구리를 넣고 조금씩 물을 덥히면 개구리는 온도가 서서히 오르는 것을 감지하지 못할 것이고, 결국은 삶아질 때까지 그냥 그대로 있을 것이다. (...) 개구리는 단지 변화를 감지하지 못하는 것이다. 그런 개구리처럼 되지 마라. 큰 그림에 늘 주의를 기울여라. 개인적으로 무엇을 하고 있는가에만 정신을 쏟지 말고, 주변에서 무슨 일이 벌어지는지 지속적으로 살펴보라.

4 적당히 괜찮은 소프트웨어

  • 우리는 종종 뭔가 나아지게 하려다가 괜찮은 것마저 망친다. - 리어왕

  • 단지 우리는 여러분이 생산해 낸 것이 어느 정도면 적당히 괜찮은지를 결정하는 과정에서 사용자가 참가할 기회를 가져야 한다는 걸 말하고 있는 것이다.

  • 하지만 예술가들은 여러분에게 언제 멈춰야 할지를 알지 못하면 이 모든 고된 작업을 망치게 될 거라고 말해 준다. 칠한 위에 덧칠하고, 세부묘사 위에 다시 세부묘사를 하다 보면, 그림은 물감 속에서 사라진다.

5 지식 포트폴리오

  • 지식에 대한 투자가 언제나 최고의 이윤을 낸다. - 벤자민 프랭클린

  • 더 많은 기술에 익숙하다면, 변화에 더 잘 적응할 수 있을 것이다.

  • 매년 새로운 언어를 최소 하나는 배워라.

  • 기술 서적을 분기마다 한 권씩 읽어라. (...) 습관이 들면, 한 달에 한 권씩 읽어라.

  • 비 기술 서적도 읽어라. (...) 방정식에서 인간이라는 변을 잊지 마라.

  • 고립은 경력에 치명적일 수 있다. 여러분 회사 밖에서는 사람들이 어떤 일을 하는지 알아보라.

  • 중요한 점은 여러분이 읽거나 듣는 것에 대해 '비판적으로'생각하는 것이다.

6 소통하라!

  • 말하고 싶은 게 무엇인지 알아라. (...) 사람들은 종종 키보드 앞에서 서론을 쳐 넣고는 무엇이건 머리에 떠오르는 대로 입력해 나가는 방식에 행복해 한다.

  • 문서를 만들 때에 내용에만 집중한다. 우리는 이것이 실수라고 생각한다. 어떤 요리사든지 간에 모양새에 신경 쓰지 않으면 부엌에서 몇 시간 동안 뼈빠지게 일한 노력이 헛수고가 될 수 있다고 말해주고 싶다.

  • 무엇을 말하는가와 어떻게 말하는가 모두 중요하다.

7 중복의 해악

  • DRY - Don't Repeat Yourself

  • 중복이 어떻게 생기는가?

    • 강요된 중복. 개발자들은 다른 선택이 없다고 느낀다. 환경이 중복을 요구하는 것처럼 보인다.
    • 부주의한 중복. 개발자들은 자신들이 정보를 중복하고 있다는 것을 깨닫지 못한다.
    • 참을성 없는 중복. 중복이 쉬워 보이기 때문에 개발자들이 게을러져서 중복을 하게 된다.
    • 개발자간의 중복. 한 팀에 있는 여러 사람들이 동일한 정보를 중복한다
  • 참을성 없는 중복

    • 모든 프로젝트는 시간의 압박을 받는다. (...) 이미 작성했던 것과 비슷한 루틴이 필요한가? 원래의 것을 복사하고 약간만 바꾸도록 유혹받을 것이다.
    • 만약 이런 유혹을 느낀다면 '돌아가는 길이 지름길이다'라는 진부한 격언을 기억하라. 지금 당장 몇 초를 절약할 수 있을지라도, 나중에는 몇 시간을 잃게 될런지 모른다.
    • 참을성 없는 중복은 발견하기도 쉽고 다루기도 쉬운 형태지만, 나중의 고통을 피하기 위해서는 훈련이 필요하고, 미연에 시간을 투자할 의지가 있어야 한다.
  • 개발자간의 중복

    • 한 프로젝트에서 일하는 서로 다른 개발자 사이에서 발생한다. 전체 기능 집합이 부주의하게 중복될 수 있고, 그런 중복은 수년 동안 발견되지 않을 수 있으며, 이는 결국 유지보수 문제로 귀결될 것이다.
    • 깨끗한 설계와 강력하고 기술적인 프로젝트 리더, 그리고 그 설계 내에서 책임의 분배가 제대로 이해되도록 하는 것, 이런 것들로 개발자 간의 중복 문제를 다루어라.
    • 우리가 느끼기에 최선책은 개발자간 적극적이고 빈번한 소통을 장려하는 것이다. 공통의 문제를 다루기 위한 토론장을 만들어라.
    • 재사용하기 쉽게 만들어라.

8 직교성

  • 컴퓨터에서 이 용어는 일종의 독립성이나, 결합도 줄이기를 의미한다. 하나가 바뀌어도 나머지에 어떤 영향도 주지 않으면 서로 직교한다고 할 수 있다.

  • 생산성 향상

    • 변화가 국소화 되서 개발 시간과 테스트 시간이 줄어든다.
    • 컴포넌트 하나가 M가지 서로다른 일을 한다고 치고, 또 다른 컴포넌트 하나가 N 가지 일을 한다고 가정하다. 만약 그것들이 직교적이라면 M x N개만크 일을 한다.
  • 리스크 감소

    • 시스템이 잘 깨어지지 않는다. 어떤 부분을 골라서 약간 바꾸고 수리해도 거기서 생기는 문제점들은 그 부분에만 한정될 것이다.
    • 직교적인 시스템은 해당 컴포넌트들에게 대해 테스트를 설계하고 실행하기 훨씬 쉽기 때문에, 아무래도 더 많은 테스트를 하게 된다.
  • '특정 기능에 대한 요구사항을 극적으로 변경했을 경우, 몇 개의 모듈이 영향을 받는가?' 직교적인 시스템에서는 답이 '하나'여야 한다. GUI를 옮기는 것 때문에 데이터베이스 스키마가 변경되어서는 안 된다.

  • 코딩

    • 코드의 결합도를 줄여라.
    • 유사한 함수를 피하라. (...) 아마도 시작과 끝에서는 공통 코드를 공유하지만 중간에 알고리즘이 다를 것이다. 중복 코드는 구조적 문제의 징후다. '디자인 패턴'에서 소개한 스트래티지 패턴을 사용하여 더 나은 구현을 할 수 없는지 고려해보기 바란다.
  • 단위 테스트를 만든다는 것 자체가 직교성을 테스트해 볼 수 있는 흥미로운 작업이다. 단위 테스트를 빌드하고 링크하기 위해서는 어떤 작업이 필요한가? 시스템 나머지의 상당 부분을 끌어들여 테스트케이스를 만들고 컴파일 혹은 링크해야하지 않는가? 만약 그렇다면 이는 모듈과 시스템의 나머지 부분과도 결합도를 적절히 줄이지 못했다는 증거다.

9 가역성

  • 당신이 가진 생각이 딱 하나밖에 없다면, 그것만큼 위험한 것은 없다. -- 에밀 사르티에

  • 최종 결정이란 없다.

  • 누구도 미래에 대해서는 알 수 없으며, 우리라고 예외는 아니다. 여러분의 코드가 로큰롤을 할 수 있게 하라. 락을 할 수도 있고 필요한 경우 롤을 할 수도 있게 하는 것이다.

10 예광탄

  • 사람들이 힘든 계산보다 예광탄을 더 좋아한다는 사실은 놀랄 일이 아니다. 예광탄은 반응도 즉각적이고, 실제 탄환과 동일한 환경 조건에서 날아가기 때문에 외부의 영향도 최소화된다.

  • 목표물을 찾기 위해 예광탄을 써라.

  • 예광탄 코드 접근 방법에는 여러 장점이 있다.

    • 사용자들은 뭔가 작동되는 것을 일찍부터 보게 된다.

    • 개발자들은 들어가서 일할 수 있는 구조를 얻는다. 아무것도 쓰여 있지 않는 백지가 가장 채우기 힘든 종이다.

    • 통합 작업을 수행할 기반이 생긴다

    • 보여줄 것이 생긴다

    • 진전 상황에 대해 더 정확하게 감을 잡을 수 있다.

  • 프로토타입은 나중에 버릴 수 있는 코드를 만든다. 예광탄 코드는 기능은 별로 없지만 완결된 코드이며, 최종 시스템 골격의일부를 이룬다. 프르토타입을 예광탄이 하나라도 발사되기 전에 먼저 일어나는 정찰과 정보 수집으로 생각하면 되겠다.

11 프로토타입과 포스트잇

  • 프로토타입은 반드시 코드로 작성해야 한다고 생각하는 사람도 있지만, 꼭 그럴 필요는 없다.

  • 포스트잇은 작업흐름과 애플리케이션 로직과 같은 동적인 것들을 프로토타이핑해 볼 수 있는 훌륭한 도구다.

  • 포로토타이핑은 학습 경험이며, 프로토타입의 가치는 생성된 코드에 있는 것이 아니라 이를 통해 배우게 되는 교훈에 있다.

  • 프로토타입 코드를 만들 때는 시작하기 전에 항상 모든 사람에게 여러분이 폐기처분할 코드를 작성하고 있다는 사실을 이해시켜야 한다.

12 도메인 언어

  • 컴퓨터 언어는 여러분이 문제에 대해 생각하는 방식과 의사소통에 대해서 생각하는 방식에 영향을 미친다.

  • 문제 도메인에 가깝게 프로그래밍하라.

13 추정

  • 언제쯤 도착하느냐고 할머니께서 물으신다면, 아마도 점심을 준비해야 하는지 아니면 저녁을 준비해야 하는지 알기 위해서일 것이다. 반대로 물속에서 사고를 당한 다이버라면 정확히 언제 도착할 것인지에 대해 초 단위까지 관심이 있을 것이다.

  • 항상 좋은 답을 알려주는 기본적인 추정 기술에 대해 이야기해주고 싶다. 이미 그 일을 해본 사람에게 물어보라는 것이다.

  • 어떤 종류의 추정이건 연습의 첫 단계는 상대방이 무엇을 묻고 있는지에 대해 이해하는 것이다.

  • 추정치가 잘못되었더라도 움츠리거나 도망가지 마라. 왜 여러분의 추측과 실제 값이 달라졌는지 원인을 찾아야 한다.

  • 점증적 개발

    • 요구사항 체크하기
    • 위험 분석하기
    • 설계, 구현, 통합
    • 사용자와 함께 검증하기
  • 누군가 추정에 대해 물으면 무엇이라 대답해야 할까? 나라면 "나중에 전화드릴께요."라 말할 것이다. (...) 자판기 앞에서 말한 추정치는 커피와 마찬가지로 여러분에게 해를 끼칠 것이다.

14 일반 텍스트의 힘

  • 일반 텍스트란 사람이 직접 읽고 이해할 수 있는 형태의 인쇄가능한 문자로 이루어진 텍스트를 말한다.

15 조개 놀이

  • 모든 목공은 훌륭하고 튼튼하며 믿을만한 작업대를 필요로 한다.

  • GUI 의 단점은, 여러분이 보는 것이 여러분이 얻는 전부라는 것이다.

  • 명령어 셸의 힘을 사용하라.

16 파워 에디팅

  • 강력한에디터 하나를 골라서 그걸 제대로 익혀라.

  • 입력해야 하는 키 개수를 줄여라.

17 소스코드 관리

  • 진보라는 것은 변화와는 거리가 멀고 오히려 기억에 의존한다. 과거를 기억하지 못하는 사람은 과거를 반복할 운명이다. - 조지 산티야나

  • 언제나 소스코드 관리 시스템을 사용하라.

18 디버깅

  • 비난 대신 문제를 해결하라

  • 디버깅을 할 때 당황하지 마라.

  • 표면에 보이는 증상만 고치려는 욕구에 저항하라. (...) 항상 문제의 근본적인 원인을 발견하려고 노력하고, 그 문제의 특정한 증상만 고치려고 하지 말라.

  • 버그를 고치는 최선의 첫 단계는 그 버그를 재현할 수 있게 만드는 것이다.

  • OS, 컴파일러 혹은 써드파티 제품에 버그가 있을 수도 있다. 하지만 처음부터 그런 생각을 하진 말라.

  • 가정하지 마라. 증명하라.

19 텍스트 처리

  • 텍스트 처리 언어를 하나 익혀라.

20 코드 생성기

  • 목공들은 똑같은걸 반복해서 만들어야 하는 작업을 대할 때, 속임수를 쓴다. (...) 지그를 제대로 만들기만 하면 같은 조각을 여러 번 재생산해낼 수 있다.

21 계약에 의한 설계

  • 상식과 정직만큼 사람을 놀라게 하는 건 없다. -- 랄프 왈도 에머슨

  • 소프트웨어 시스템의 모든 함수는 메서드는 뭔가를 한다. 그 뭔가를 시작하기 전에 해당 루틴은 세상의 상태에 대해 어떤 기대를 갖고 있을 테고, 루틴이 끝난 후에 세상의 상태가 어떠해야 한다는 진술을 할 수 있을 것이다.

  • 우리는 부끄럼 타는 코드를 작성할 것을 권했다. (...) 시작하기 전에 자신이 수용할 것에 대해서 엄격하게 하고, 내어줄 것에 대해서는 최소한도를 약속하는 것이다. 무엇이든 수용하고, 이 세상 전부를 돌려주기로 약속을 한다고 계약에 쓰여있다면, 여러분은 정말이지 많은 코드를 작성해야 할 것이다!

  • 서브클래스는 사용자가 차이점을 모르고서도 기반 클래스 인터페이스를 통해 사용할 수 있어야 한다.

  • 입력 도메인 범위가 무엇인지, 경계 조건이 무엇인지, 루틴이 뭘 전달한다고 약속하는지 - 혹은 더 중요한 것으로, 무엇을 전달한다고 약속하지 않는지 - 하는 것들을 설계 시기에 나열하는 것만으로도 더 나은 소프트웨어를 작성하는 데에 엄청난 도움이 된다.

  • 누구의 책임인가?

    • 호출자와 호출되는 루틴 중에 선행조건을 확인하는 것은 누구의 책임인가? 언어의 일부로 구현되어 있는 경우, 대답은 어느 쪽도 아니다 이다. 선행조건은 호출자가 루틴을 부른 뒤, 그러나 루틴 자체로 들어가기 전에 무대 뒤에서 테스트된다. 따라서 명시적으로 체크해야할 매개 변수가 하나라도 있으면, 이것은 호출자가 테스트를 수행해야 한다. 루틴 스스로는 선행 조건을 위배하는 매개변수를 결코 보지 못할 것이기 때문이다.
  • 오류 발생시 소비자의 입장을 우선하라

22 죽은 프로그램은 거짓말을 하지 않는다

  • 망치지 말고 멈추라. 가능한 빨리 문제를 발견하게 되면, 좀 더 일찍 시스템을 멈출 수 있다는 이득이 있다.

  • 분명히 실행 중인 프로그램을 그냥 종료해 버리는 것은 때로 적절치 못하다. 해제되지 않는 자원이 남아 있을 수도 있고, 로그 메세지를 기록할 필요가 있을 수도 있고, 열려있는 트랜잭션을 청소해야 하거나, 다른 프로세스들과 상호작용해야 할 필요가 있을지도 모른다.

23 단정적 프로그래밍

  • 자기 비난에는 사치성이 있다. 우리가 자신을 비난할 때, 다른 사람은 우리를 비난할 권리가 없다고 우리는 느낀다. -- 오스카 와일드, 도리안 그레이의 초상

  • 단정문을 사용해서 불가능한 상황을 예방하라

  • 물론 단정문에 전달된 조건은 부작용이 있으면 안 된다. 또한, 컴파일 중에 단정 기능이 꺼져 있을 수도 있다는 걸 기억하라. 실행되어야만 하는 코드는 절대 assert 속에 두지 마라.

24 언제 예외를 사용할까

  • 우리는 모든 가능한 에러(특히 의외의 것들)를 체크하는 것이 좋다고 했다. 그렇지만, 실제로 이렇게 하다보면 코드가 꽤 지저분해질 수 있다.

  • 예외가 문제가 있다면 하나는 이걸 언제 사용할지 아는 것이다. 우리는 예외가 프로그래밍의 정상 흐름으 일부로 사용되는 일은 거의 없어야 한다고 믿는다. 예외는 의외의 상황을 위해 남겨두어야 한다.

  • 파일을 열어 읽으려고 하는데 그 파일이 존재하지 않는다면 예외가 발생해야 하는가? 우리의 답은, '경우에 따라 다르다.'이다.

  • 예외는 예외적인 문제에 사용하라.

25 리소스 사용의 균형

  • 시작한 것은 끝내라

  • 집합적인 자료구조 안의 자료에 대해 책임을 지는 게 누구인지 정해놓아야 한다.(...) 주로 다음 세 가지 방법 가운데 선택할 수 있다.

      1. 최상위 구조 자신이 자기 안에 들어있는 하위 구조들의 할당을 해제할 책임이 있다. 하위 구조들은 또다시 재귀적으로 자기 안에 들어있는 자료들을 해제할 책임이 있고, 이런 식으로 진행된다.
      1. 최상위 구조에서 그냥 할당이 해제된다. 그 안에서 참조하던 구조들은 모두 연결이 끊어져 고아가 된다.
      1. 최상위 구조는 하나라도 하위 구조를 가지고 있을 경우 자기의 할당 해제를 거부한다.
  • 실용주의 프로그래머는 자신을 포함해서 아무도 믿지 않기 때문에, 정말로 리소스가 적절하게 해제되었는지 실제로 점검하는 코드를 늘 작성하는 것이 언제나 좋다고 우리는 생각한다.

26 결합도 줄이기와 디미터 법칙

  • 좋은 울티라는 좋은 이웃을 만든다. -- 로버트 프로스트, 담장 고치기

  • 부끄럼 타는 코드를 작성하는 것이 이롭다고 설명했다. 이때 '부끄럼 타는'이란 자신을 남에게 속속들이 드러내지 말고, 너무 많은 사람과 상호작용하지 말라는 두 가지 의미를 모두 내포해야 한다.

  • 왜 의존의 증가가 나쁠까? 시스템 어딘가의 무관한 변화가 여러분의 코드에 영향을 미칠 수 있는 위험이 커지기 때문이다.

  • 직접 위계구조를 헤집고 다니지 말고, 필요한 정보는 직접 물어보도록 한다.

  • 해당 모듈들이 서로 결합하고 있다는 것을 잘 알고, 또 그것을 받아들일 수 있다면 아직 괜찮은 설계라 할 수 있다.

27 메타프로그래밍

  • 통합하지 말고 설정하라.

  • 비지니스 정책이나 룰은 프로젝트의 다른 어떤 부분보다 변화하기 쉽기 때문에 이를 유연한 포맷을 통해 유지보수하는 것이 좋다.

  • 일반화할 기회를 놓치지 말자.

28 시간적 결합

  • 시간에는 우리에게 의미 있는 두 가지 측면이 있다. 동시성과 순서가 그것이다.

  • 작업흐름 분석을 통해 동시성을 개선하라.

  • 순차적으로 실행한다고 하더라도, (...) 이것들 중 많은 것을 병행해서 실행할 수 있음을 안다.

29 단지 뷰일 뿐이야

  • '잘 정의된 단 하나의 책임만 가지는 것'이라는 말이야말로 모듈에 대한 좋은 정의가 된다.

30 칠판

  • 칠판을 사용해 작업흐름을 조율하라.

31 우연에 맡기는 프로그래밍

  • 지금 잘 작동하는데 괜히 건드렸다 일을 만들필요가 있을까나? 우리는 그래야 할 몇 가지 이유를 생각해낼 수 있다.

    • 정말로 제대로 돌아가는 것이 아닐지도 모른다. 우리에게만 그런 것 처럼 보일 수 있다.
    • 여러분이 의존하는 조건이 단지 우연인 경우도 있다.
    • 문서화되지 않은 동작은 라이브러리의 동작은 다음 릴리즈에서 변경될 가능성이 있다.
    • 불필요한 추가 호출은 코드를 더 느리게 만든다.
    • 추가로 호출한 루틴 때문에 새로운 버그들이 코드에 들어올 가능성이 있다.
  • 우연에 맡기는 프로그래밍을 하지 말라.

  • 의도적으로 프로그래밍 하기

    • 언제나 자기가 지금 무엇을 하고 있는지 알아야 한다. 프레드는 일이 서서히 자기 손 밖으로 벗어나도록 내버려 두었고, 결국 개구리처럼 삶아져 버렸다.
    • 맹목적으로 코딩하지 말라. 완전하게 이해하지 못한 어플리케이션을 빌드하려 하거나 익숙하지 않은 기술을 사용하려고 시도하는 행동은 우연에게 자기를 미혹해도 좋다는 초청장을 보내는 것과 다름 없다.
    • 계획을 세우고 그것을 바탕으로 진행해라. 머리 속에 있는 계획이든, 냅킨 뒤에 적어놓은 계획이든, CASE 도구로 만든 한쪽 벽면에 가득 찰 정도 계획이든 상관없다.
    • 신뢰할 수 있는 것에만 기대라. 우연한 일에나 가정에 의존하지 말라. 어떤 상황에서 신뢰할 만한 것과 아닌 것을 판단하지 못하겠거든, 일단 가장 최악의 상황을 가정하라.
    • 여러분의 가정을 문서로 남겨라.
    • 코드만 테스트할 것이 아니라 여러분이 세운 가정도 테스트해 보아야 한다.
    • 노력을 기울일 대상의 우선순위를 정하라. 기반 또는 인프라가 올바르지 않다면 현란한 부가 기능들도 다 소용 없다.
    • 과거의 노예가 되지 말라. 기존 코드가 앞으로 짤 코드를 지배하도록 놓아두지 말라. 더 이상 적절한 코드가 아니라고 생각되면, 어떤 코드라도 교체할 수 있다.

32 알고리즘의 속도

  • 기간이 얼마나 걸릴까 등을 추정해 보는 것에 대해 이야기 했다. 하지만 실용주의 프로그래머가 거의 날마다 사용하는 또 다른 종류의 추정이 있다. 알고리즘이 사용하는 자원. 곧 시간, 프로세서, 메모리 등등을 추정하는 것이 그것이다.

  • 최고라고 언제나 최고는 아니다. 적당한 알고리즘을 선택할 때도 실용적이어야 할 필요가 있다. 가장 빠른 알고리즘이 언제나 가장 좋은 알고리즘은 아니다. 입력값의 규모가 작다면 단순한 삽입 정렬도 퀵정렬과 비슷한 성능을 내준다. 그러나 삽입 정렬을 작성하고 디버깅하는데 걸리는 시간은 퀵정렬보다 적다.

33 리팩터링

  • 내 주변을 돌러보니 변화와 쇠퇴뿐... --라이트, "함께 하소서"

  • 소프트웨어는 건축보다 오히려 정원일에 더 가깝다. 딱딱하기보다는 유기적인 존재다.

  • 사업가들은 건물 건축이라는 메타포를 더 편안하게 여긴다. 정원일보다 더 과학적이며, 반복가능하고, 관리를 위한 엄격한 보고 위계질서도 있고 등등 때문이다.

  • 리팩터링을 하지 않는 핑계로 자주 사용되는 이유가 일정의 압박이다. 하지만 이것은 설득력 있는 이유가 되지 못한다. 지금 리팩터링 하지 않으면, 일이 더 진척되었을 때, 곧 신경 써야 할 의존성이 더 많이 생겼을 때 문제를 고치기 위해 훨씬 더 많은 시간을 투자해야 한다. 그떄가 되면 일정에 더 여유가 생길까? 우리의 경험에 비추어 봤을 때 그런 일은 없다.

  • 일찍 리팩터링하고, 자주 리팩터링 하라.

  • 분명히 리팩터링은 천천히, 신중하게, 조심스럽게 진행해야 하는 작업이다. 마틴 파얼러는 손해보다 이득이 큰 방향으로 리팩터링을 하기 위한 다음 몇가지 간단한 조언을 제공한다.

    • 리팩터링과 새로운 기능 추가를 동시에 하지 말라.
    • 리팩터링을 시작하기 전 든든한 테스트 집합이 있는지 먼저 확인한다.
    • 단계를 작게 나누어서 신중하게 작업한다.

34 테스트하기 쉬운 코드

  • 소프트웨어 컴포넌트도 조립해서 쓸 수 있어야 한다는 생각이다. 이것은 여러분이 사용할 컴포넌트가 신뢰할 수 있는 경우에만 가능하다.

  • 테스트 코드를 쉽게 접근할 수 있게 해놓는 것은, 매우 귀중한 두 가지 자원을 제공하는 것이다.

    • 여러분 모듈의 모든 기능을 어떻게 이용해야 하는지 보여주는 예제
    • 후일 코드 변경시 검증하기 위한 회귀 테스트를 구축할 수 있는 수단
  • 디버깅하면서 그 자리에서 몇 가지 테스트를 만드는 경우도 있다. (...) 디버깅 시간이 끝나면 이런 코드들을 정식 태스트의 형태로 만들어 두어야 한다. 한번 잘못된 코드라면, 다시 잘못될 가능성도 높다. 여러분이 만든 테스트를 그냥 버리지 말고, 기존의 단위 테스트에 추가해 둔다.

  • 소프트웨어를 테스트하라. 그렇지 않으면 사용자가 테스트하게 될 것이다.

35 사악한 마법사

  • 자신이 이해하지 못하는, 마법사가 만들어 준 코드는 사용하지 말라.

36 요구사항의 구렁텅이

  • 완성이라는 것은 더 이상 더할 것이 없을 때가 아니라, 더 이상 빼낼 것이 없을 때 얻게 되는 것이다. -- 생택쥐베리

  • 요구사항이란 어떤 것이 성취되어야 한다는 진술이라는 것이다.

  • 사용자들이 어떤 작업을 현재 어떻게 하느냐는 것을 알아내는 것보다, 왜 그걸 하는지 그 내재적 이유를 알아내는 것이 더 중요하다.

  • 요구사항 문서를 만들 때 생기는 큰 위험은 지나치게 자세히 서술하는 것이다. 좋은 요구사항 문서는 추상적이다. 요구사항에 관한 한 비지니스에 필요한 사항을 정확히 반영하는 가장 간단한 진술문이 최고다. 그렇다고 해서 모호하게 하라는 말은 아니다.

  • 요구사항은 아키텍처가 아니다. 요구사항은 설계가 아니며, 사용자 인터페이스도 아니다. 요구사항은 필요다.

  • 구체적인 것보다 추상적인 것이 더 오래간다.

  • 요구사항 증가 관리의 핵심은, 새 기능이 일정에 미칠 영향을 프로젝트 후원자에게 인식시키는 것이다. (...)'기능 하나만 더'라는 소용돌이 속으로 빨려 들어가기는 무척 쉽다. 하지만 요구사항을 추적함으로써, '기능 하나만 더'가 실은 이번 달에 추가된 15번째 새 기능이었다는 사실을 분명히 알 수 있게 된다.

37 불가능한 퍼즐 풀기

  • 프리기아의 왕 고르디우스는 아무도 풀 수 없는 매듭을 묶었다. 고르디우스의 매듭을 푸는 자가 아시아의 왕이 될 것이라는 이야기가 전해졌다. 알렉산더 대왕은 검으로 그 매듭을 잘라내 버렸다. 요구사항에 대한 조금 다른 해석, 그것이 다였다. 그는 결국 아시아의 대부분을 다스리게 되었다.

  • 생각의 틀틀 벗어나지 말고, 틀을 찾아라.

  • 어떤 때는 문제가 생각보다 훨씬 어렵다는 것을 발견하는 때도 있다. (...) 바로 이 때가 한 걸음 뒤로 물러서서 다음 질문을 스스로에게 해 보아야 할 시점이다.

    • 더 쉬운 방법이 존재하는가?
    • 진짜 문제를 풀려고 노력하고 있나. 그렇지 않다면 중요하지 않은 기술적 문제에 정신이 팔려 있는 것인가?
    • 왜 이것이 문제인가?
    • 문제를 이렇게 풀기 어렵게 만드는 것이 무엇인가?
    • 반드시 이 방법으로 해야 하는가?
    • 반드시 해야 하는 일이긴 한가?

38 준비가 되어야만

  • 가끔은 망설이는 자가 재난을 모면한다. -- 제임스 써버, 풀밭의 유리창

  • 모든 사람이 백지를 두려워한다. 새로운 프로젝트를 시작하는 일은 두려운 경험이 되기도 한다. 많은 사람들이 일을 시작하는 최초 행위를 미루기 좋아한다.

  • 프로토타이핑이 진행되면서 갑자기 기본적인 몇몇 전제가 틀렸다는 것을 깨닫는 어떤 계시의 순간이 여러분에게 찾아올지도 모른다.

39 명세의 함정

  • 명세 작성에는 굉장히 무거운 책임이 따른다. 문제는 많은 설계자들이 명세서 작성을 멈추지 못한다는 점이다. 설계자들은 사소한 세부사항까지도 고난에 차도록 시시콜콜하게 밝혀놓지 않는 한 그날 하루 일을 제대로 하지 못했다고 느낀다.

  • 명세서가 어떤 시스템이나 그 시스템에 대한 요구사항의 모든 세부사항과 미묘한 차이점들을 모조리 잡아낼 수 있으리라고 믿는 것은 너무 순진한 생각이다.

  • 언어 자체의 표현 능력에도 문제가 있다.

  • 신발끈을 리본 모양으로 매는 방법을 설명하는 짧은 글을 하나 써보라. (...) 설명은 경이적일 정도로 어렵다. 하지만 우리들 대부분은 의식적으로 생각하지 않고 신발끈을 묶을 수 있다.

  • 어떤 일들은 설명하기보다 실제로 하는 것이 쉽다.

  • 명세와 구현은 단지 동일한 과정, 즉 요구사항을 포착해서 명문화하려는 노력의 다른 측면일 뿐이다.

  • 명세서가 안심용 담요 역할을 해서 개발자들이 코드 작성이라는 무서운 세상으로부터 보호받는 기간이 길어질수록 진짜 코드 작성 단계로 옮겨가기는 점점 더 힘들어진다.

40 동그라미와 화살표

  • 형식적 방법의 노예가 되지 마라

  • 대개의 최종 사용자는 이런 다이어그램들을 전혀 이해하지 못하므로, 설계자가 해석해 주어야 한다. 따라서 실제 시스템의 사용자들이 정말 형식적 확인을 통해 요구사항을 점검하는 일은 없는 셈이다.

  • 형식적 방법들을 전문화를 권장하는 것처럼 보인다.

  • 형싱적 방법들은 동적으로 연결해야 할 객체들 사이에 정적인 관계를 설정하도록 권장하면서 여러분을 잘못된 길로 이끌 것이다.

  • 비싼 도구가 더 좋은 설계를 낳지는 않는다.

41 실용주의 팀

  • 품질은 팀의 이슈다. 만약 가장 부지런한 개발자라 해도 품질에 무심한 팀에 배치된다면 귀찮은 문제를 고치는 그의 열정은 줄어들 것이다.

  • 팀 전체가 깨진 창문(아무도 고치려고 하지 않는 사소한 결점)을 용납하지 않아야 한다. 팀은 상품의 품질에 대해 책임을 져야만 한다.

  • 깨진 창문을 없애라 철학을 이해하는 개발자들을 지원하고 그렇지 못한 개발자들은 이해하도록 격려해야 한다.

  • 개인보다는 팀이 삶은 개구리가 되기 쉽다. 사람들은 누군가가 문제를 처리하겠거니 생각하거나, 사용자가 요구하는 변화에 대해 팀 리더가 이미 오케이했거니 하고 여긴다. 제아무리 단단히 통제되는 팀이라도 자기네 프로젝트가 심각하게 변화하는 것에 대해 둔감할 수 있다.

  • 무뚝뚝하고 과묵해 보이는 프로젝트 팀이야말로 최악이다. 그런 팀은 회의를 아무 체계 없이 하고, 나서서 말하는 이도 없다. 문서는 엉망진창이다. 어떤 문서도 닮은 데가 없고, 각기 다른 용어를 사용한다.

  • 훌륭한 프로젝트 팀은 뚜렷한 특성을 갖는다. 모든 사람이 좋아할 만한 잘 준비된 퍼포먼스를 보게 될 걸 알기 때문에 사람들은 회의를 기대한다. 그들이 생산해 내는 문서는 깔끔하고 정확하며 일관적이다. 팀은 한 목소리로 이야기한다. 심지어 유머감각도 있을 것이다.

42 유비쿼터스 자동화

  • 생각 없이 행할 수 있는 중요한 작업의 수가 늘어남에 따라 문명은 발전한다. -- 알프레드 노드 화이트헤드

  • 반복되는 작업이 있는가? 동일한 순서의 명령을 거듭 입력하고 있지는 않는가? 그 과정을 자동화하는 셸 스크립트를 몇개 작성해 보라. 늘상 같은 순서의 아이콘들을 클릭하는가? 그걸 대신해 줄 메크로를 만들 수 있겠는가?

43 가차 없는 테스트

  • 개발자 대부분은 테스트를 싫어한다. 코드가 어디에서 깨지는지 무의식적으로 알고 약한 지점을 피해 다니면서, 살살 테스트하려 한다. 실용주의 프로그래머들은 다르다. 우리는 지금 당장 버그를 찾아 나서도록 내몰리지만, 그 대신 나중에 다른 사람이 자기 버그를 발견하게 되는 수치를 피할 수 있는 것이다.

  • 현존하는 테스트의 그물을 빠져 나가는 버그가 있으면, 다음번에는 그걸 잡아낼 수 있도록 새 테스트를 추가해야 한다. 버그는 한 번만 잡아라.

44 결국은 모두 글쓰기

  • 아무리 흐린 먹물이라도 가장 훌륭한 기억력보다 낫다. -- 중국 속담

  • 실용주의 프로그래머들은 문서화를 전체 개발 프로세스의 필요불가결한 부분으로 포용한다.

  • 문서가 애초부터 전체의 일부가 되게 하고, 나중에 집어넣으려고 하지 말라.

45 위대한 유산

  • 프로젝트의 성공은 사용자들의 기대를 얼마나 잘 충족하는가에 따라 측정된다.

  • 몇몇 컨설턴트들은 이 과정을 '기대 관리'라고 부른다. 사용자가 시스템에서 무엇을 얻기를 기대해야 할지에 대해 적극적으로 제어하는 것을 일컫는 말이다. 이것은 좀 엘리트주의적인 입장이다. 우리의 역할은 사용자들의 희망을 제어하는게 아니다. 그들과 협동해서 그들이 아직 이야기하지 않은 기대까지도 포함해서, 개발 과정과 최종 결과전달물에 대해 공통된 이해에 도달하는 것이다.

46 오만과 편견

  • 옛 장인들은 자신의 작품에 서명하는 것을 자랑스러워했다. 여러분도 그래야 한다.

  • 우리는 소유권에 대한 긍지를 보고 싶다. "내가 이걸 만들었고, 내 작품의 품질을 보증합니다." 여러분의 서명이 품질의 보증수표로 인식되게 해야 한다. 사람들이 코드에 붙여진 여러분의 이름을 보고 그것이 튼튼하고 잘 작성되고 제대로 테스트되었으며 또 훌륭히 문서화되었을 것이라고 기대하도록 만들자. 진정으로 프로페션한 일. 진정한 프로페셔널이 작성한. 실용주의 프로그래머.