최상단 광고

2012년 7월 9일 월요일

실용주의 프로그램 - 2편


36. 모듈 간의 결합도를 최소화하라

 객체의 모든 메서드는 다음에 해당하는 메서드만을 호출해야 한다 라는 디미터 법칙을 따른다,
  • 객체 자신의 메서드
  • 메서드의 매개 변수로 넘어온 인자의 메서드
  • 메서드 내부에서 생성된 객체의 메서드
  • 메서드가 직접 포함하고 있는 객체의 메서드
//객체의 모든 메서드는 다음에 해당하는 메서드만을 호출해야 한다
class Demeter
{
    private A a;

    private int func() { return 0; }

    public void example(B& b)
    {
        C c = new C();
        int f = func();         // 객체 자신의 메서드
        b.invert();             // 메서드의 매개 변수로 넘어온 인자의 메서드
        a = new A();
        a.setActive();      // 메서드 내부에서 생성된 객체의 메서드
        c.print();          // 메서드가 직접 포함하고 있는 객체의 메서드
    }
}

이 법칙을 잘 따라 설계를 하되 애플리케이션에 맞게 장점과 단점을 고려한다

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

알고리즘의선택, 사용할 데이터베이스 제품 등의 시스템 심층부분들은 통합하거나 
엔지니어링 하지 말고 설정 옵션으로 구현한다.

38. 코드에는 추상화를, 메타데이터에는 세부 내용을

 위 방식처럼 사용하면 아래와 같은 이점이 있다
  • 설계의 결합도를 줄여 좀 더 유연하고 적응성 있는 프로그램을 만들수 있다.
  • 세부사항을 코드 밖으로 몰아냄으로써 보다 강하고 추상적인 디자인을 만들수 있다.
  • 애플리케이션을 커스터마이징하기위해 재 컴파일 할 필요가 없다.
  • 메타 데이터는 범용 프로그래밍 언어보다 문제 도메인에 가까운 방식으로 표현될수 있다.
  • 동일한 애플리케이션 엔진과 상이한 메타데이터를 이용해 여러 다른 프로젝트를 진행 할 수 있게 된다..

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

UML 등을 사용해 요구사항을 분석하여 작업흐름을 기록한다.
작업흐름을 분석하면서 보틀넥이 걸리는 부분을 예상 할 수 있으며
의존성이 실제 어디로 존재하는지, 어느 부분을 최적화 하는것이 좋은지 알 수 있다

40. 서비스를 사용해서 설계하라

예를들어 중앙일정관리자 대신 여러개의 독립적인 태스크들과 중앙 집중식 작업큐를 사용한다.
이렇게 하면 어떤 작업하나가 버벅대더라도 다른 작업들이 계속 큐에 들어오는 일을 가져갈 수 있으며,
개발 컴포넌트들은 자기 속도에 맞추어 일을 진행 할 수 있다.
시간적으로 결합이 끊기는 것이다.

41. 언제나 동시성을 고려해 설계하라

 이제는 거의 모든 개발자들이 다중스레드 프로그래밍을 접하게 되었다.
순차적인 시스템과 동시성있는 시스템에서의 생각은 엄연히 틀리다.
시간순서, 객체 유효상태, 의존성등을 고려한다면 더 깔끔한 인터페이스를 설계할 수 있을 것이다

42. 모델에서 뷰를 분리하라

모델과/ 뷰 / 컨트롤러를 분리하면, 적은 비용으로 큰 유연성을 얻게 된다
자바의 트리위젯이 MVC 설계에 좋은 예이다.
아래 링크를 참조

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

어떤 사실을 칠판에 올려 적절한 규칙이 연결되도록만 하면 되며
어떤 결과에 대한 피드백도 쉽게 다룰 수 있다.
어떤 규칙 집합이든 그 결과를 다시 칠판에 올려서 다른 규칙들이 움직이게 하면 된다.

44. 우연에 맡기는 프로그래밍을 하지 말라

우연은 잘못된 길로 가게 할 수도 있으며 그 부분은 거짓과 우연이 결합 된 곳이다.
가정하기는 쉬우나 증명하긴 어렵다. 가정 하지 말고 증명한다.
확실한 사실에 증명하지 않은 가정은 결국 어느 프로젝트에서든 재앙의 근원이 된다

45. 알고리즘의 차수를 추정하라

 알고리즘 시간에 배운 O(n)등을 써서 자신의 알고리즘의 차수를 측정한다.
측정후 차수를 더 낮출수 있는지, 만약 외부요인에 따라 달라진다면
어떻게 최적화 할 것인지 잠시 고민해보는것도 좋다.

46. 추정을 테스트 하라

추정을 했더라도 실제 데이터를 입력받아 돌아가는 코드의 수행시간을 봤을때
비로소 추정의 의미가 있다.그 후 알고리즘을 선택한다
물론 가장 빠른 알고리즘이 가장 좋은것은 아니며, 성급한 최적화를 할 필요도 없다.

47. 일찍, 자주 리팩토링 하라

리팩토링 해야 할 것들의 명단을 만들고 유지하면서,
일정에 그것들을 리팩토링 할 시간을 확실히 포함시켜 둔다.
리팩토링에 본질은 재설계다.
아무부분이나 닥치고 삭제 해버리면서 분해하는것이 아니다
다음은 마틴 파울러가 손해 < 이득 이 되는 리팩토링에 관련한 조언이다
  • 리팩토링 + 새로운 기능 추가는 하지 말 것
  • 할 수 있는한 테스트들을 돌려본다 ( 변경으로 인한 오류를 빨리 찾을 수 있음)
  • 단계를 나누어 신중히 작업하며, 한 단계가 끝날때마다 테스트를 돌린다 ( 디버깅 작업을 피할 수 있음)


48. 테스트를 염두에 두고 설계하라

루틴하나를 설계하더라도 테스트하는 코드를 설계하는 것이 좋다.
테스트 통과 후 요구사항을 처리하는 코드를 설계하다보면
자연스럽게 생각나지 않았을 경계조건이나 다른 문제들을 고려하게 된다.
또한 해당 인터페이스가 고정되기 전에 미리 시험을  해볼 수도 있다


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

모든 소프트웨어는 언젠가는 테스트 한다.
따라서 우리팀이 하지 않는다면 사용자가 테스트를 하게 될 것이며 그것은 곧 사용자와의 신뢰와도 관계가 있다.
따라서 소프트웨어를 철저하게 테스트 할 계획을 세워야 한다.

50. 자신이 이해하지 못하는, 위저드가 만들어준 코드는 사용하지 말라

코드를 자동으로 생성하는 위저드 자체를 반대하는 것이다.
하지만 위저드를 사용했는데 위저드 코드를 모두 이해하지못한다면 
이미 애플리케이션은 내것이 아니다.
그 애플리케이션을 이후에 유지보수하지도 못할 것이고 디버깅해야 할 때가 오면 고생 할 것이다.


51. 요구사항을 수집하지 말고 채굴하라

요구사항은 어떤 것이 성취되어야 한다는 진술이다.
요구사항은 분명하기 주어지지 않으며 정책가은 수시로 바뀌는 것들도 요구사항속에 넣지 않는다.
따라서 어떻게 하느냐도 중요하지만 왜 하느냐라는 내재적 이유를 알고
요구사항을 분석하다보면 설계를 보다 자연스럽게 할 수 있을 것이다

52. 사용자처럼 생각하기 위해 사용자와 함께 일하라

사용자가 직접 되어보는것도 좋고 QA팀원들에게 자문을 얻는 것도 좋다
이러한 요구사항 채굴과정은 사용자층이 바라는 시스템이 무엇인지 배우면서 
사용자 층과 관계를 설정하기 시작하는 단계이다

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

Y2K 문제는 대략 2가지 요인에서 발생하는데 하나는 현 비즈니스 관행 너머를 보는데 실패,
또 DRY 원칙을 어겼기 때문이다.
일반적인 관행으로 2자리 숫자를 쓰게 되었는데,
자료 입력, 보고, 저장등을 위해 두자리 숫자 년도가 필요했을 지라도,
이 두자리 숫자가 실은 날짜를 줄여쓴 사실이라다라는 추상화가 있어야 했다

54. 프로젝트 용어사전을 사용하라

개발자(프로그래머, 아티스트, 기획, 디자이너 등등)과 사용자가 동일한 것을
다른 이름으로 가리키거나 같은 이름을 다른것으로 지칭하는 프로젝트는 성공하기 어렵다.
모든 참가자가 쉽게 접근할 수 있도록 프로젝트 문서(용어사전 포함)를 내부 웹사이트나
하이퍼텍스트 문서로 표현하면 다양한 사용자의 필요를 충족 시킬 수 있으며
원활한 의사소통을 할 수 있을 것이다


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

간단한 예를 들어보자
오직 직선 세개만으로 아래 그림에 나오는 모든 점을 연결하고 선을 긋기 시작한 지점으로 돌아오는 경로를 생각해보자
(단, 종이에서 펜을 떼거나 전에 그었던 직선을 다시 따라가면 안된다)

풀리지 않는 문제와 마주쳤다면, 생각해 볼 수 있는 모든 가능한 해결 경로를 눈앞에 나열해 본다.
아무리 쓸모없고 바보같이 보이는 경로라도 절대 버리지 않는다.
이 후 하나씩 목록을 점검하며 왜 그 경로가 불가능한지 설명한다.
그렇게 제약들을 범주로 나누거 우선순위를 매긴다.
목공은 어떤 일을 시작할때 그 일에서 가장 긴 조각을 자르고 남은 나무에서 작은 조각들을 잘라낸다
한번 잘 생각해보고 답은 포스트 가장 아래에 있다.


56. 준비가 되었을때 시작하라

지휘자는 오케스트라 앞에서서 연주를 시작하기 가장 좋은 순간이라고 느낄때까지 기다린다
마음속에서 "기다려" 라고 들려오는 목소리에 귀를 기울여야 한다.
우리들은 지금까지 개발자로서 경력을 쌓으며 이와 비슷한 일을 해오고 있다.
여러가지 일을 시험해보았고 어떤것이 잘됐고 어떤것이 그렇지 않았는지 보았다.
경험과 지혜를 축적해왔디.
소프트웨어 개발은 완벽히 과학이라고는 아직은 할 수 없다
수행능력에 직감이 일조하도록 놓아두자

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

 신발끈을 묶는 방식을 아이에게 설명한다고 했을 때,
대부분 "엄지손가락과 검지손가락을 둥글게 잡아서 한족 끝이 왼쪽 끈의 아래와 왼쪽을 지나가게...."
라고 말하는 시점에서 포기할 것이다
정말 설명이 경이적일 정도로 어렵다. 하지만 우리들 대부분은 의식적으로 생각하지 않고 신발끈을 묶을 수 있다

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

 형식적 방법이 나쁘다는 것이다.
그것을 맹목적으로 받아들이지 말라는 것이다.
형식적 방법에는 몇가지 단점들이 있다
  • 다이어그램+추가 설명을 이용해 요구사항을 포착한다 
  • 이런 그림은 최종 사용자는 설계자들의 그림을 전혀 이해하지 못하므로 설계자가 해석해주어야 한다 
  • 가능하면 프로토타입을 사용자에게 보여주고 직접 다루는 것이 좋다

  • 전문화를 권장하는 것 같이 한 집단은 데이터모델작업, 아키텍처를 보는 작업, 유스케이스를 모으는 작업을 한다.
  • 이러한 방식은 결국 의사소통의 부족과 노력의 낭비로 이어진다.
  • 작업중인 시스템을 전체적으로 이해하는 것이 좋다
  • 동적으로 연결해야 할 객체들 사이에 정적인 관계를 설정하도록 권장하는 것은 분명 문제가 있다

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

 사람들이 펼치면 몇백 평이 넘을 클래스 다이어그램 종이 뭉치와 유스케이스 150개를 들고 회의에 들어오더라도
그것 또한 여전히 틀릴 가능성이 있는 요구사항과 설계에 대한 그들의 해석일 분이다.
도구의 결과물을 볼때 비용따위는 생각하지 않도록 하는 것이 좋다

60. 팀을 기능 중심으로 조직하라

 팀을 또 다시 기능적으로 작은 팀으로 나누어 최종 시스템의 특정한 기능측면에 책임을 지도록 한다
팀이 개개인의 강점 위에 스스로 내부를 조직하게 한다.
이렇게 하면 팀들은 분리해서 어떤 변화가 생기더라도 전체가 영향 받는 일이 없게 된다
DB를 갑작스럽게 바꾸기를 사용자가 원한다면 영향 받는 것은 DB팀 뿐이어야 한다


61. 수작업 절차를 사용하지 말라

 셸 스크립트나 배치 파일들을 사용하거나 자동화 도구를 사용한다면 
사람들은 어느정도 동일한 환경에서 개발 할 수 있으며,일정을 세우는 것에도 많은 도움이 될 것이다

62. 일찍 테스트하라. 자주 테스트 하라. 자동으로 테스트 하라

 코드는 작성하자마자 테스트 해야 한다
그 작은 잔챙이들은 자라는 속도가 순식간이라 거대한 상어가 되는 성질이 있다.
상어를 잡는 일은 상당히 힘들다. 그 만큼 버그가 빨리 발견되면 고치는 비용이 적다


63. 모든 테스트가 통과하기 전엔 코딩이 다 된것이 아니다

 어떤 코드를 만들었다는 이유만으로 클라이언트나 상사에게 완료되었다고 할 수 없다
코드는 가능한 모든 테스트를 통과 한 후 높은 수준의 신뢰를 얻었을 때만이 완료된 것이다.
항상 무엇을 어떻게 언제 테스트 할지 고민해보자

64. 파괴자를 써서 테스트를 테스트 하라

 완벽한 소프트웨어는 없으므로 테스트 소프트웨어도 완벽하다고 할 수 없다
프로젝트 파괴자를 임명해서 테스트릍 테스트 한다.
파괴자의 역할은 소스트리의 카피를 별도로 만들어 취한뒤 고의로 버그를 심고 테스트가 잡아내는 지 검증하는 것이다

65. 코드 커버리지보다 상태 커버리지를 테스트하라

 커버리지 분석도구는 테스트 중에 코드를 지켜보고 코드의 어느라인이 실행되지 않았는지 기억한다
이러한 도구들 덕에 테스트가 얼마나 포괄적인지 대한 대체적인 느낌은 가질 수 있으나
100% 신뢰하지는 않아야 한다.
프로그램의 모든 상태를 분별해서 판단해야 할 것이다

int test (int a , int b)
{
    return a / (a + b);
}

위 코드는 이론상으로 1,000,000 가지의 논리적 상태를 갖지만 그 가운데 999,999개만 제대로 작동 할 것이다
제대로 작동하지 않는 논리도 ( a, b 모두가 0일때 ) 분명히 있다

철저한 테스트를 하자.

"아주 단순하게 만들어서 명백히 결함이 없도록 하는 것과 다른 하나는 아주 복잡하게 만들어서 명백한
결함이 없도록 하는 것이다" 라는 토니 호아의 명언 과
"테스팅은 버그의 존재만 보여줄수 있지 버그의 부재는 보여 줄수 없다" 라는 
다익스트라의 명언을 잘 생각해보자

66. 버그는 한 번만 잡아라

 테스터가 버그를 잡으면 그 순간이 그 버그를 찾는 마지막 순간이 되어야 한다.
그 이후는 해당 버그를 확인할 수 있게 자동화 테스트들을 수정해야 한다
어차피 버그는 또 다시 일어난다
자동화 테스트가 우리를 대신해 찾아 줄 버그를 추격할 시간은 없다
새 코드 ( 새 버그)를 작성하는데 시간을 보내야 한다

67. 한국어도 하나의 프로그래밍 언어인 것처럼 다루라

프로젝트에서 생산되는 문서에는 소스코드, 주석, 설계와 테스트 문서 에 내부문서
외부로 출간되는 매뉴얼 같은 외부문서로 나뉜다.

이러한 문서는 무엇인지 불문하고 잘 작성해야 한다.
모든 문서는 코드의 거울이기 때문이다 

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

 소스코드의 주석, 테스트 문서등 포매팅된 문서를 만들 되 
이들은 애초부터 전체의 일부가 되는 것이 좋다.
나중에 집어넣을 때는 고려해야 할 점이 너무 많다

69. 사용자의 기대를 부드럽게 넘어서라

 기대를 사용자와 개발자가 상호 소통한다.
사용자들이 기대하는 것보다 조금만 더 해준다면 사용자와 
개발자의 관계는 두고두고 좋아질 것이며 신뢰성도 두터워 질 것이다.
단, 기능팽창으로 시스템에 부담을 주지 않아야 한다 
그러한 예에는 아래와 같은 것들이 있다

  • 풍선 혹은 툴팁 도움말
  • 키보드 단축키
  • 사용자 매뉴얼의 부록으로 만든 빠른 참조
  • 하이라이팅
  • 로그 분석기
  • 자동 설치
  • 시스템 상태 체크 도구
  • 각 회사나 조직을 위해 만든 스플래시 스크린
  • 훈련 목적으로 여러버전의 시스템을 실행 시킬 수 있는 기능

70. 자신의 작품에 서명하라

 자신의 코드는 좋게 보고 동료들의 코드는 깎아 내리는 편견을 갖지 않도록 한다
같은 맥락에서 다른사람들의 코드를 존중 해주어야 한다.

또한 자신의 소유권에 대한 긍지를 가지도록 해야 한다
"내가 이걸 만들었으며, 내 작품의 품질을 보증합니다" 라는 것이 우리들의 서명으로 인식해야 한다
우리들의 서명이 곧 품질의 보증수표로인식 되게 해야 한다
코드에 붙여진 이름을 보고 이 사람이 만든 것은
튼튼하고 잘 작성되었으며 훌륭히 문서화 되었을 것이라고 기대되도록 만든다

("시드 마이어의 문명" 같은....)


실용주의 프로그램 - 1편


1. 자신의 기술에 관심과 애정을 가져라

 기술에 관심과 애정이 없다면 이미 일을 하고 있는것에 아무런 의미가 없다. 
 의미없는 일은 곧 지루함을 말하는 것이기에 목표가 없다는 말이기도 하다

2. 자신의 일에 대해 생각하면서 일하라

 일에 대해 생각하며 시간을 보낸다면 소중한 시간을 잡아먹는 것일 수도 있지만
 이러한 생각을 함으로써 받는 보상은 더 많을 것이다. (발전을 느끼는데서 오는 희열 등)


3. 어설픈 변명을 만들지 말고 대안을 제시하라

 고양이가 내 소스코드를 삼켰어요 라고 상사에게 말하는건 이미 도움이 안되며
 그 대신에 상황을 개선하기 위해 무엇을 할 수 있는지 대안을 제시한다

4. 깨진 창문을 내버려 두지 말라

 깨진창문(잘못된결정, 나쁜 설계, 형편없는 코드)을 고치지 않은 채 내버려 두지 말고  
 발견하자마자 바로 고친다. 시간이 안되면 코드를 주석처리를 해서라도 메시지를 표시한다
 조치를 취하고 현 상황을 언제나 잘 관리하고 있다는것을 보여준다

5. 변화의 촉매가 되라

 군인들이 하나의 촉매로 작용해서 마을사람들 스스로 재료를 모아 돌멩이 수프를 만들었던 것 처럼
 시너지의 결과로 모든 사람이 승리 할 수 있다는 걸 보여준다.
 팀원들에게 미래를 살짝이라도 보여준다면 팀원들은 원조를 위해 집결할 것이다
 계속되는 성공에 합류하는건 쉬운 것이다 

6. 커다란 그림을 기억하라

 물을 서서히 데우면 온도가 오르는걸 감지 못하고 삶아져 죽는 개구리가 되지 않는다.
 무엇을 하고 있는가에만 집중하지 말고  큰 그림에 늘 주의를 기울이며 주위의 변화를 지속적으로 살핀다. 

7. 품질을 요구사항으로 만들어라

 사용자들은 멀티미디어 버전을 위해 1년을 기다리느니 지금당장 좀 불편한 소프트웨어를 사용하고 싶어한다
 사용자들에게 뭔가 직접 만져 볼수 있는것을 일찍 준다면 그들은 자연스레 품질을 요구사항으로 변경하게 되어
 더 나은 솔루션으로 도달 하는 길이 될 것이다

8. 지식 포트 폴리오에 주기적으로 투자하라

 비록 소량일지라도 습관 자체가 금액의 합계만큼이나 중요하며 많이 알수록 자신의 가치는 더욱 높아진다
 게다가 컴퓨터 분야는 매우 변화가 빠르므로 더많은 기술에 익숙하다면 그만큼 변화에 적응하기는 쉬울 것이다
 또한, 새로운 것도 빨리 습득하려는 습관을 들이게 되면 얼리어답터들 처럼 많은 이득도 챙기며 
그 분야에 꼭대기에 서게 되는 기초가 될것이다
 (매년 새로운 언어를 최소 하나는 배워라기술서적을 분기마다 한권씩 읽어라. 비 기술서적도 읽어라. 수업을 들어라
  지역 사용자 모임에 참여하라. 다른 환경에서 실험해보라)

9. 읽고 듣는 것을 비판적으로 분석하라

 자신의 포트폴리오에 있는 지식이 정확하고, 벤더나 매체의 과대광고에 흔들림이 없도록 확실히 주의해야 할 것이다

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

 진공속에서 작업하지 않는 이상 의사소통을 해야한다. 그 소통이 효과적일 수록 많은 영향력을 갖게 될 것이다

11. DRY (Don't Repeat Yourself)

 모든 지식은 시스템 내에서 단일하고, 애매하지 않으며 믿을만한 표현 양식을 가져야 한다. 
 소프트웨어를 신뢰성 높게 개발하고, 개발을 이해하여 유지보수가 쉽게 만드는 길일 것이다.

12. 재사용하기 쉽게 만들라

 직접 만드는 것이 아닌 기존의 것을 찾아내고, 또 재사용하기 쉬운 환경을 조성해야 한다.
 그게 쉽지 않다면 사람들은 하지 않을것이며 그렇게 되면 지식 중복의 위험을 각오해야 한다

13. 관련 없는 것들 간에 서로 영향이 없도록하라

 독립적이며, 단일하고 잘 정의된 목적을 가진 컴포넌트를 설계한다.
 이렇게 직교적으로 시스템을 만들게 되면 생산성 향상과 리스크 감소라는 커다란 장점이 있다

14. 최종 결정이란 없다

 의사결정들은 해변가의 모래 위에 쓰인 글씨라 생각한다.
 언제든지 큰 파도가 글씨를 지워버릴 수 있다. 이것을 염두해 두고 하는것과 그렇지 않은것은
 분명 커다란 차이가 있을 것이다

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

 탄창의 일반탄환들 사이에 일정한 간격으로 끼어 총알을 맞은것과 총 사이에 빛의 궤적을 남기는 예광탄은
 좋은 예이다. 동일한 환경과 제약조건에서 발사되고 날아가며, 목표물에 도달하는 시간이 짧기 때문에
 즉각적인 반응을 얻을 수 있어 비용이 적게 드는 방법이다.
 즉, 코딩에서도 요구사항으로부터 최종시스템의 일부 측면에까지. 빨리. 눈에 보이게 반복적으로 도달해줄
 무언가를 만드는 것이 좋다


16. 프로토 타입을 통해 학습하라

 프로토타이밍은 학습 경험이며, 프로토타입의 가치는 생성된 코드에 있는 것이 아니라
 이를 통해 배우는 교훈에 이다. 이 핵심을 잘 생각하고 만든다면 커다란 도움이 될 것이다
 코드로 작성할 필요는 없다. 화이트보드도 좋고 노트도 좋다. 
 인터페이스만 그려도 그것은 좋은 프로토 타입이다

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

 현재 자신이 쓰고 있는 언어에 가깝게 프로그래밍 한다.
 같은 문제라도 Lisp으로 코딩할때와 C로 코딩할때는 엄연히 다른 해결책이 나오는 것과 같다
 도메인 언어에 가깝게 프로그래밍 한다면 사소한 구현의 세부사항 문제를 신경쓰지 않아도 될 것이다

18. 추정을 통해 놀람을 피하라

 추정에 대한 지식을 배운 후 경험을 통해 추정능력을 계발한다면
 무언가의 가능성을 가늠할 수 잇는 능력을 발휘하게 될 것이다. 
 그렇게 되면 직관적으로 문제가 가능한지 안한지 판단 할 수 있게 된다
    
19. 코드와 함께 일정도 반복하며 조성하라

 추정을 통해 필요한 일정등을 알았다면 당연히 코드는 물론 일정도 반복하며 조성해야 할 것이다
 이 것 또한 팀의 생산성의 높은 영향력을 미칠 것이다

20. 지식을 일반 텍스트로 저장하라

 당연히 코딩을 할때는 기계와 친해져야 하겠지만 지식을 저장할때는
 일반 텍스트로 저장해야 한다. 비 구조적이어야 하는 것만은 아니며
 XML, HTML 등은 잘 정의된 구조를 가진 좋은 일반텍스트의 예이다

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

 셸에 익숙해지는데는 시간이 걸리겠지만 익숙해진다면 프로젝트 생산성은 급 상승 할 것이다.

22. 하나의 에디터를 잘 사용하라

 에디터 하나를 골라서 완전히 마스터하고, 모든 편집 작업에 해당 에디터를 사용한다
 ( 텍스트를 조작하고 멈출때 필요한 키 입력은 이젠 거의 반사운동 수준이 될 것이다)

23. 언제나 소스코드 관리 시스템을 사용하라
    
 SVN,CVS같은 소스코드 관리 시스템은 프로젝트를 진행하는데 많은 도움을 준다
 한주짜리 프로젝트를 진행할지라도 소스코드 관리 아래있으면
 각종문서, 메모, 빌드 과정을 처리하는데 있어서도 안전하게 코드들은 보관될 것이다

24. 비난대신 문제를 해결하라

 버그가 내 잘못인지 남 잘못인지는 이미 중요한게 아니다.
 어쨋거나 그 버그는 우리들의 문제로 남을 것이다.

25. 디버깅을 할떄 당황하지마라

 버그 보고를 받고서 "그건 불가능해"라는 말은 틀렸다
 그런 일은 실제 일어났으며 일어날 가능성은 충분히 있다. 
 또한 증상만이 아닌 원인을 고쳐야 할 것이다

26. "select"는 망가지지않았다

 직접적이건 간접적이건 간에 코드를 수정했고 시스템이 작동을 멈춘다면 한가지 뭔가 책임이 있는 것이다

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

 불가능해 라고 말하는 시점에서 이미 지금까지 알고 있는 진실들을 재평가해야한다.
 놀라운 실패를 대면했을대 불가능하다는 생각 이전에 내가 세운 가정들에 대해서 잘못되었다는 것을
 깨닫고 그것을 맥락 안에 해당 데이터로 증명하는 것이 중요하다

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

 간단한 스크립트 언어들을 펄(Perl)같은 언어로 간단히 만들어 쓰게 된다면 생산성 향상에 크게 도움이 된다
 이러한 언어들은 재빨리 유틸리티를 만들어 낼 수 있고, 아이디어를 프로토타이핑 해볼수 있기 때문이다.
 (루비. 스몰토크. 펄) 등이 있다

29.  코드를 작성하는 코드를 작성하라

 목공이 지그를 만드는데에 시간을 투자하느것처럼 코드생성기를 만들기만 하면 프로젝트 기간 내내
 아무런 비용 없이 사용할 수 있을 것이다

30. 완벽한 소프트웨어는 만들수 없다

 길지않은 컴퓨터 역사속에 그 누구도 완벽한 소프트웨어는 만들지 못했다. 이후도 그렇다
 남을 믿지 않는 방어적 코딩을 해가면서 한 걸음 더 나아가 내 자신 역시 믿지 않게 되면
 자신의 실수에 대비해 방어적으로 코드를 짜게 될 것이다.

31. 계약에 따른 설계를 하라

 계약에 부응하지 못하는 것이 버그가 된다면 그그것은 이미 치명적이다..
 내가 계약에 부응하지 못하는 코드를 만든다면 그 역시 계약 불이행이나 마찬가지이다

32. 일찍 작동을 멈추게 하라

  가능한 빨리 문제를 발견하게 되면 좀 더 일찍 시스템을 멈추는것이 최선일 때가 많다
  자바언어와 라이브러리도 이러한 철학을 기반으로 RuntimeException을 던지게 설계했다

33. Assert를 사용해서 불가능한 상황을 미리 예방하라

 물론 일어나지 않을거야 라는 생각이 들어도 그걸 확인하는 코드를 추가 하는것이 좋다
 이것을 가장 간단하게 할 수 있는것이 Assert이다

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

 에러와 예외는 엄연한 차이가 있다.
 예외는 엄연히 예외적인 일만 처리를 해야 할 것이며, 수습이 불가능한 것은 에러처리를 해야 할 것이다

35. 시작한 것은 끝내라

 리소스를 할당하는 루틴이나 객체가 리소스를 해제하는 책임 역시 져야 한다는 의미이다
 해당 루틴에서 모든 리소스나 포인터를 책임지고 있다면, 해당 루틴에서 모든것을 끝낼 수 있다
 또한 , 예외 상황도 처리를 확실하게 해야 한다
 DRY 원칙이 깨지지 않도록 리소스 사용의 균형을 잡아야 한다 
 ( ex 동적할당을 하는 그 순간 예외처리를 여러개 해야하지만 객체로 처리하면 객체의 자동 파괴를 C++에 맡길수 있다
       그게 힘들다면 리소스 자체를 다른 클래스로감싸서 처리 하는 방식도 있다