BOOKS

Pragmatic Programmer 실용주의 프로그래머

파란실버라이트 2018. 2. 9. 12:10
  • ㄴ서문
    • 프로그래밍은 기예(Craft)다. 컴퓨터에게 여러분이 시키고 싶은 일을 하게끔 난드는 것이다. 
    • 특정한 환경 조건의 집합마다 각 집합에 가장 적절한 시스템이 있을 뿐이다. 이것이 실용주의가 뜻하는 바다. 
      • 어떤 특정 기술에 메이면 안되며, 개별 상황마다 그 상황에서 좋은 해결방안을 고를 수 있도록 충분한 배경지식과 경험이 필요
      • 배경지식 - 컴퓨터 과학의 기본 원리들을 이해하는 것
      • 경험 - 다양한 프로젝트를 수행해보는 것
    • 더 효율적이고 생산성 높은 프로그래머가 되고 싶어하는 사람들 대상
  1. 실용주의 철학
    • 문제를 항상 더 큰 맥락에 놓으려 하고, 항상 더 큰 그림을 보려한다.
    • 자신이 하는 모든 일에 책임을 진다.
    • 소프트웨어 엔트로피
      • '깨진창문'(나쁜 설계, 잘못된 결정, 형편없는 코드)을 고치지 않을 채로 내버려두지 마라, 발련하자마자 바로 고처라 
      • 고칠 시간이 충분하지 않다면 판자로 덮는 것만이라도 하라. 불쾌한 코드를 주석처리하거나, Not implemented라는 메시지 표시 , Dummy 데이타로 대치해 놓아라. 더 이상의 손상을 예방하기 위해 어떤 조치든취하고 현 상황을 잘 관리하고 있다는 것으 보이라
    • 적당히 괜찮을 소프트웨어
      • 완벽하게 훌륭한 프로그램을 과도하게 장식하거나 지나칠 정도로 다듬느라 망치지 말라. 그냥 넘어가고 코드가 현재 상태에서 한동안은 그대로 있도록 놓아두라. 완벽하지 않을 수도 있다. 걱정하지마라. 완벽해지기란 불가능하다. 
    • 지식 포트폴리오
      • 주기적인 투자 / 공부
      • 다각화 - 더 많은 기술에 익숙하다면 , 변화에 더 잘 적응
      • 리스크 관리 - 여러분의 기술 달걀을 한 바구니에 모두 담지 마라
      • 싸게 사서 비싸게 팔기 - 새롭게 떠오르는 기술을 학습
      • 검토 및 재조정 - 인기 있는 기술 습득 or 낡은 기술 복습  
  2. 실용주의 접근법
    • 반복하지 마라 / 실용 주의 프로그래머의 가장 중요한 도구 중 하나
    • 직교성 - 독립성(Independence) or decoupling
      • 프로젝트 팀 구조 직교성 확인 - 요청된 개별 변화에 대한 토론에 참여할 필요가 있는 사람이 몇인가를 보라, 숫자가 클 수록 직교성은 낮다. 
      • 직교 적인 설계를 테스트 - 특정 기능에 대한 요구사항을 극적으로 변경했을 경우 몇 개의 모듈이 영향을 받는가?
      • 단위 테스트를 만드는 것 자체가 직교성을 테스트 
      • 버그를 수정하고 테스트를 마친 뒤 버그 수정에 대한 테그를 붙여라. 각 버그 수정에 의해 영향 받는 소스 파일의 개수에 대한 월 단위 리포트를 받아볼 수 있다. 
    • 가역성 
      • 많은 사람들이 코드를 유연하게 유지하려고 노력한다. 하지만 아키텍처, 배포, 벤더 통합 영역의 유연성에 대해서고 관심 필요
      • 벤더 의존적인 수행문들이 코드 전반에 흩어져 있을 것이고 , 이는 유지 보수성, 유연성을 극도로 떨어뜨리게 된다. 요구사항을 메타데이터에넣고, 필요한 수행문을 코드에 넣을 떄 AOP or Perl을 이요하여 메커니즘을 자동화 시켜라. 
    • 예광탄
      • 프로토타입 - 나중에 버릴 수 있는 코드를 만든다.
      • 예광탄 코드 - 기능은 별로 없지만 완견된 코드이면, 최종 시스템의 골격의 일부를 이룬다. 
      • 프로토타입을 예광탄이 하나라도 발사되기 전에 번저 일어나는 정찰과 정보 수집으로 생각
    • 프로토 타입
      • 프로토타입을 코드로 만들 때는 시작하기 전에 항상 모든 사람에게 여러분이 폐기처분할 코드를 작성하고 있다는 사실을 이해시켜야 한다. 
    • 도메인 언어
      • 데이터 언어- 애플리케이션이 사용할 어떤 형식의 데이터 구조를 만든다. 환경설정 정보를 표현하기 위해 쓰이는 경우
      • 명령형 언어 - 실제로 실행되며, 문자, 제어 구조체를 가진다. 
      • 도전? 한 프로젝트를 위해 개발한 프레임워크를 다른 프로젝트에서 재사용할 수 있는 방법들을 생각해 낼 수 있는가?
  3. 기본적인 도구
    • 디버깅
      • 버그를 목격하거나 혹은 버그 보고서를 보는 순간 첫 반응이 "그건 불가능"라면 여러분은 두말할 필요 없이 틀렸다. 
      • OS, 컴파일러, 혹은 써드파티 제품에 버그가 있을 수도 있다. 하지만 처음부터 그런생각을 하진 말라. 개발하고 있는 어플리케이션 코드에 버그가 존재할 가능성이 훨씬 더 크다.
  4. 실용주의 편집증
    • 계약에 의한 설계 (Design by Contract , DBC)
      • 선행조건 - 루틴이 호출되기 위해 참이어야 하는 것, 루틴의 요구사항
      • 후행 조건 - 루틴이 자기갈 할 것이라고 보장하는 것, 루틴이 완료되었을 때 세상의 상태 
      • 클래스 불변식 - 호출자의 입장에서 이 조건이 언제나 참이라고 클래스가 보장

      • 부끄럼 타는 , 게으른 ,Shy, Lazy code
        • 시작하기 전에 자신이 수용할 것에 대해서 엄격하고
        • 내어줄 것에 대해서는 최소한도를 약속 
        • 상속과 다향성에서 이런 계약이 빛을 발한다. 
    • 단정적 프로그래밍 (Assert)
      • 두 가지 공공연한 잘못된 가정 
        • 테스트가 모든 버그를 발견한다 
        • 프로그램이 험한 세상에서 (로그파일이 하드를 full ) 도는 것을 잊는다.
      • 첫째 방어선은 가능한 에러를 체크
      • 놓친 것들을 잡아내기 위해 단정문을 쓰는 것이다. 
      • void writeString(char *string) { assert(string != NULL); 
    • 언제 예외를 사용할까?
      • 예외가 프로그램의 정상 흐름의 일부로 사용되는 일은 거의 없어야 한다고 밑는다. 
      • 예외를 정상적인 처리과정의 일부로 사용하는 프로그램은 고전적인 스파게티 코드의 가독성 문제와 관리성 문제를 전부 떠안게 된다. 이런 프로그램은 캡슐화 역시 깨트린다. 예외처리를 통해 루틴과 그 호출자들 사이의 결합도가 높아져 버린다.
  5. 구부러지거나 부러지거나
    • 유연함으 유지하는 한 가지 좋은 방법은 가능한 적은 양의 코드 작성
    • 뷰에서 데이터 모델을 분리
    • 모듈들이 데이터를 동기적, 비동기적으로 교환할 수 있는 만남의 장소 마련 => 칠판 Blackboard design pattern 
    • https://en.wikipedia.org/wiki/Blackboard_(design_pattern)
    • 결합도 줄이기와 디미터 법칙
      • 부끄럼 타는 코드를 작성 / 자신을 드러내지 말고, 많은 사람과 상호작용하지 말라. 

      • 디미터 법칙은 코드를 더 적응성 있고 강하게 만들어 주지만 '주계약자'로서 대가를 치러야 한다. 
        • 주계약자(Station Class)는 모든 하부 계약자(Order manager, part manager를 직접 관리하고 , 이들에게 위임해주어야한다. 
        • 실제로 이는 위임자에게 단순히 요청을 전달하는 역활만을 하는 간단한 위임 메서드를 상당수 만들어야 함을 의미
        • 위임 메서드는 성능 저하, 메모리 과부하와 같은 문제 야기
      • 메타프로그래밍 
        • 동적 설정 : 파일.ini
        • 메타 데이터 주도 애플리케이션 (Java Hibernate framework?)
          • 가능한 마지막 순간까지 세부 정의를 피하고, 세부사항을 소프트하게 , 변화하기 쉽게 남겨두라 
        • 언제 설정 정보를 읽어야 할까? 프로그램이 시작 될때?
          • 실행되는 동안 메타데이터를 리로딩하고 적용할 수 있는 방법을 제공하는 것이 옳다. 
      • 동시성을 고려한 설계
        • 더 깔끔한 인터페이스를 설계하는 방향으로 이끌기도 한다.  
      • 모듈(잘 정의된 단 하나의 책임만 가지는 것) 프로그래밍
        • 런타임에 객체들이 어떻게 서로 이야기하게 만들어야 하나?
        • 모듈 사이의 논리적 의존성은 어떻게 관리해야 하나?
        • 즉 다른 객체들의 상태변화(갱신된 값)을 어떻게 동기화?
        • 유연하고 깔끔한 방식으로 이루어져야 한다. 우리는 객체가 서로에 대해 너무 많이 알기를 원하지 않는다. 자기가 보고 싶은 것만 보도록 만들고 싶다. => 이벤트라는 개념에서 시작. 
      • 출판/구독

  6. 코딩하는 동안 해야할 일들
    • 우연에 맡기는 프로그래밍, 행운과 어쩌다 오는 성곡에 의족하는 프로그래밍을 하지 말하야 한다. 대신 의도적 프로그래밍을 해야한다. 
      • 언제나 자기가 지금 무엇을 하고 있는지 알아야한다.
      • 맹목적으로 코딩하지 마라. 완전하게 이해하지 못한 애플리케이션을 빌드하려 하거나, 익숙하지 않은 기술을 사용하려고 시도하지 마라 => 그런데 새로운 프로젝트는 해야한다. ^^;
      • 계획을 세우고 그것을 바탕으로 진행하라 => 칸반 툴을 사용
      • 신뢰할 수 있는 것에만 기대라=> 테스팅
      • 여러분의 가정을 문서로 남겨라 => 사용자와 소통
      • 코드 뿐만 아니라 가정도 테스트 해야한다.
      • 노력을 기울일 대상의 우선순위를 정하라
      • 과거의 노예가 되지 마라/ 기존 코드가 앞으로 짤 코드를 지배하도록 놓지 말라. 적절하지 않으면 어떤 코드도 교체 가능 
        • 단 일정이 늦어져 발생하는 비용이 필요한 변화를 만들지 않을 경우의 비용보다 적어야 한다. 
    • 리펙토링
      • 리펙터링과 새로운 기능 추가를 동시에 하지 말라
      • 리펙터링을 시작하기 전 든든한 테스트 집합이 있는지 먼저 확인
      • 단계를 나누어서 신중하게 작업 / 작은 단위에서 큰단위로 
    • 계약을 잘 지키는지 테스트해보기
      • 어떤 단위가 자기가 맺는 계약을 존중하는지 확실하게 보여주는 테스트 케이스를 작성
        • 코드가 계약을 지키는지 확인
        • 코드로 표현된 계약의 의미가 우리가 생각한 것과 일치하는지. 

  7. 프로젝트 전에
  8. 실용주의 프로젝트
    • 자동화 - Testing , CI, CD  - 이런 환경에서 구축해야 한다. 
    • 가차 없는 데스트