실용주의 프로그래머를 읽으며(wip)

다용도리모콘·2022년 4월 10일
1

개발 책 읽기

목록 보기
18/18

실용주의 철학

당신의 인생이다

당신에게는 스스로의 행동을 직접 결정할 수 있는 힘이 있다. ..."당신은 당신의 조직을 바꾸거나, 당신의 조직을 바꿀 수 있다."

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

다른 사람 혹은 다른 무언가를 비닌하거나 변명을 만들어 내지 말라. 모든 문제를 외부 업체나 프로그래밍 언어, 경여진, 동료 때문이라고 떠넘기지 말라. 이들이 모두 한몫씩 했을 수 있겠지만 필요한 것은 변명이 아니다. 해결책을 찾아내야 하는 사람은 여러분이다.

소프트웨어 엔트로피

'깨진 창문'을 고치지 않은 채로 내버려 두지 말라.

돌멩이 수프와 삶은 개구리

변화를 촉진하려고 할 때 여러분이 돌멩이 수프를 만드는지 아니면 개구리 수프를 만드는지 어떻게 판단할 수 있을까?

적당히 괜찮은 소프트웨어

오늘의 훌륭한 소프트웨어는 많은 경우 환상에 불과한 내일의 완벽한 소프트웨어보다 낫다. 사용자에게 뭔가 직접 만져볼 수 있는 것을 일찍 준다면, 피드백을 통해 종국에는 더 나은 해결책에 도달할 수 있을 것이다.

지식 포트폴리오

  • 매년 새로운 언어를 최소 한가지 배우기
  • 기술 서적을 한 달에 한 권씩 읽기
  • 기술 서적이 아닌 책도 읽기
  • 기술 세미나나 콘퍼런스 수업 듣기
  • 소셜 그룹에 참여하기
  • 다른 환경에서 실험해 보기(ex 윈도우 -> 리눅스)
  • 트렌드 놓치지 않기

소통하라!

  • 청중을 알기
  • 말하고 싶은게 무엇인지 알기
  • 때를 고르기
  • 스타일을 고르기
  • 멋져 보이게 하기
  • 청중을 참여시키기
  • 경청하기
  • 응답하기
  • 코스와 문서를 함께 두기(문서화)

실용주의 접근법

(2022.04.23)

좋은 설계의 핵심: ETC

바꾸기 더 쉽게(Easier to Change). ETC. 이게 전부다. 우리가 아는 한 세상의 모든 설계 원칙은 ETC의 특수한 경우다.

  • 결합도를 줄이면 좋은 이유 -> 관심사를 분리해 바꾸기 쉬워짐
  • SRP가 유용한 이유 -> 모듈 하나만 바꿔도 됨
  • 이름 짓기가 중요한 이유 -> 코드가 읽기 쉬워지고 코드를 바꾸려면 코드를 읽어야함

미래의 변경을 예측해 코드를 작성하기 어려울 때

  • 작성하는 코드 자체를 교체하기 쉽도록 작성
  • 나름의 예측을 통해 코드를 작성하되 히스토리를 정리해 두기(직관을 발전시키는 기회로 삼기)

Do Not Repeat: DRY

모든 지식은 시스템 내에서 단 한 번만, 애매하지 않고, 권위 있게 표현되어야 한다.

코드의 어떤 측면 하나를 바꿔야 할 때 여러 곳을 바꾸고 있나? 그것도 여러 가지 다른 형태를? 코드를 바꾸고 문서도 바꾸는가? 데이터베이스 스키마와 스키마를 담고 있는 구조 등도? 그렇다면 여러분의 코드는 DRY하지 않다.

중복의 종류

  • 코드의 중복
  • 문서화 중복 -> 코드의 내용을 주석으로 한 번 더 표현하는 경우
  • 데이터의 DRY 위반
    class Line {
    	Point start;
      	Point end;
      	double length; //start와 end를 가지고 있으면 length는 언제든 계산할 수 있다.
      	double length() { return start.distanceTo(end); } //이렇게 하자.
      
      public Line(Point start, Point end) {
        this.start = start;
        this.end = end;
        calculateLength();
      }
      
      private void calculateLength() {
      	this.length = start.distanceTo(end);
    }
    
    //더 나은 방법(매번 length를 계산하지 않아도 됨)
    class Line {
    	private Point start;
      	private Point end;
      	private double length;
        
        Point getStart() { return start; }
        Point getEnd() { return end; }
      	double getLength() { return length; }
      
      public Line(Point start, Point end) {
        this.start = start;
        this.end = end;
        calculateLength(); //생성자에서 한 번만 length를 계산하면 된다.
      }
      
      private void calculateLength() {
      	this.length = start.distanceTo(end);
    }
  • 표현상의 중복
    • 내부 API에서 생기는 중복 -> 언어나 기술에 중립정인 도구 사용(예: 스웨거, 프로토콜 버퍼)
    • 외부 API에서 생기는 중복 -> OpenAPI 같은 형식으로 엄밀하게 문서화
    • 데이터 저장소와의 중복 -> 외부 데이터를 한 번 감싼 key-value 형식의 데이터로 구조(like map, hash)로 사용
  • 개발자간의 중복
    왕도가 없다. 개발자 간에 적극적이고 빈번하게 소통하기.

직교성

직교성: 하나가 바뀌어도 나머지에 어떤 영향도 주지 않으면 서로 직교한다고 할 수 있다.

툴킷과 라이브러리

툴킷이나 라이브러리를 도입할 때에는 심지어 같은 팀의 다른 멤버가 작성한 것이더라도 이것이 여러분의 코드에 수용해서는 안 될 변화를 강요하지 않는지 검토해 보라.

직교성을 유지하는 코딩

  • 코드의 결합도 줄이기
  • 전역 데이터 피하기 -> 싱글턴 패턴 주의
  • 유사한 함수 피하기 -> 전략패턴 사용하기

가역성

결정이 바뀌지 않을 것이라 가정하고서 발생할지도 모를 우연한 사건에 대비하지 않는 데에서 실수가 나온다. 결정이 돌에 새겨진 것이 아니라 바닷가의 모래 위에 쓰인 글씨라 생각하라. 언제든지 큰 파도가 글시를 지워버릴 수 있다.

(2022.05.04)

예광탄

예광탄: 일반 탄환 사이에 섞여 발사되어 총과 탄착지점 사이의 궤적을 볼 수 있게 해주는 총알.
예광탄 개발: 실제 조건하에서 즉각적인 피드백을 받을 수 있도록 개발하는 것.

시스템을 정의하는 중요한 요구 사항을 찾아라. 의문이 드는 부분이나 가장 위험이 커 보이는 곳을 찾아라. 이런 부분의 코드를 가장 먼저 작성하도록 개발 우선순위를 정하라.
... 전체 애플리케이션에서 불확실한 곳이 어디인지 찾아보고 해당 부분을 작동시키는 데 필요한 뼈대를 추가한다.

예광탄 개발의 장점

  • 사용자가 뭔가 작동하는 것을 일찍부터 보게 된다
  • 개발자가 들어가서 일할 수 있는 구조를 얻는다
  • 통합 작업을 수행할 기반이 생긴다
  • 보여줄 것이 생긴다(윗사람들에게...)
  • 진행 상황에 대해 더 정확하게 감을 잡을 수 있다.

예광탄과 프로토타입의 차이

프로토타입은 나중에 버리는 코드, 예광탄 코드는 완결된 코드이며 프로젝트의 일부이다.
순서로는 프로토타입으로 정찰, 수집 후 예광탄 개발을 진행한다.

프로토타입과 포스트잇

  • 프로토타입을 통해 위험요소를 분석하고 노출시킨 후, 저렴한 비용으로 수정할 수 있다.
  • 프로토타입을 꼭 코드로 작성할 필요는 없다.
  • 세부사항을 포기할 수 없다면 프로토타입보다 예광탄이 적절하다.
  • 프로토타입의 가치는 코드가 아니라 이를 통해 배우는 교훈에 있다.

도메인언어

내부 도메인 언어

기존의 프로그래밍 언어를 확장해 사용하는 방식의 도메인 언어. 사용하는 프로그래밍 언어의 문법에 종속된다.

외부 도메인 언어

자체의 언어를 사용하는 도메인 언어. 별도의 파서가 필요하다.

추정

초기 기능의 구현과 테스트를 마친 후, 이를 첫 번째 반복 주기의 끝으로 삼아라. 첫 반복 주기의 경험을 바탕으로 반복 주기의 수와 각 반복 주기에서 무엇을 할지에 대한 처음의 추측을 다듬을 수 있을 것이다.

여러분은 팀, 팀의 생산성 그리고 환경이 일정을 결정한다는 사실을 경영진에게 이해시켜야 한다.

기본 도구

(2022.05.14)

일반 텍스트의 힘

  • 지원 중단에 대한 보험

    사람이 읽을 수 있는 형태의 데이터와 그 자체만으로 의미가 드러나는 데이터는 다른 어떤 형태의 데이터보다, 심지어 그 데이터를 생성한 애플리케이션보다 더 오래 살아남을 것이다.

  • 기존 도구의 활용

    버전 관리 시스템에서 에디터, 명령 줄 도구에 이르기까지 컴퓨터 세계의 거의 모든 도구는 일반 텍스르를 다룰 수 있다.

  • 더 쉬운 테스트
    테스트에 사용할 데이터나 테스트 결과를 일반 텍스트로 표현하면 쉽게 이해할 수 있다.
  • 최소 공통 분모

    여러분은 모든 참가자가 하나의 공통 표준을 사용해서 소통하도록 해야 한다. 일반 텍스트가 바로 그 표준이다.

셸 가지고 놀기

WYSIWYG(What You See Is What You Get) but WYSIAYG(What You See Is All You Get.)

셸에 익숙해지면 여러분의 생산성이 급상승할 것이다.

자신만의 셸

  • 색깔 조합(스타일) 설정하기
  • 프롬프트 설정하기
  • 별칭(alias)와 셸 함수 만들기
  • 명령어 자동 완성 확장하기

파워 에디팅

에디터 챌린지(마수으나 트랙패드 없이 수행)

  • 문자, 단어, 줄, 문단 단위로 커서를 이동하거나 내용 선택하기
  • 반대쪽 괄호로 이동하거나, 함수, 모듈 등 다양한 문법 단위로 커서 이동하기
  • 자동 정렬
  • 여러줄을 한번에 주석 처리했다가 해제하기
  • 식행 취소를 여러 번 했다가 취소한 명령을 재실행 기능으로 다시 수행하기
  • 에디터 창을 여러 구역으로 쪼개고 각 구역 사이를 이동하기
  • 특정 줄 번호로 이동하기
  • 여러 줄을 선택한 후 가나다순으로 정렬하기
  • 문자열 또는 정규식으로 검색하고 이전에 검색한 내용 다시 검색하기
  • 선택 영역이나 패턴 검색을 이용하여 일시적으로 여러개의 커서를 만든 다음, 동시에 여러 곳의 텍스트를 편집하기
  • 현재 프로젝트의 컴파일 오류 표시하기
  • 현재 프로젝트의 테스트 실행하기

버전관리

  • 프로젝트 이외의 것에도 버전관리 사용하기

디버깅

(2022.05.22)

디버깅의 심리

버그가 여러분의 잘못인지 다른 사람의 잘못인지는 중요치 않다. 어쨌거나 그 버그를 해결해야 하는 사람은 여러분이다.

디버깅 사고방식

  • 디버깅 제 1 법칙: 당황하지 말라
  • 문제의 근본 원인을 찾자

실마리 찾기

  • 특정 인물에게만 발생하는 버그라면 보고한 사용자를 인터뷰할 필요도 있다
  • 경계 조건과 실제 최종 사용자의 사용 패턴 모두를 철저히 테스트해야 한다

디버깅 전략

  • 버그 재현하기: 명령하나로 재현할 수 있게

버그 유형

  • 이상한 결과
  • 입력값에 따라 바뀜
  • 릴리스 사이에서 발생한 문제

버그 해결 방법

  • 이진분할: 문제를 해결할 때 이진분할 방식으로 문제가 발생하는 지점을 신속하게 찾을 수 있다
  • 로깅과 트레이싱: 특정 지점마다 규칙적으로 로그를 남기는 것은 원시적이지만 효과적이다
  • 고무오리: 막힐 때는 누군가에게 설명을 하며 원인을 찾아보자. 사람이 없다면 고무오리나 화분에게...

놀라운 구석

"그건 불가능해."라고 중얼거릴 정도로 놀라운 버그를 만나게 된다면 버그를 고치는 것 이상을 해야 한다. 버그가 일찍 발견되지 않은 원인을 찾아 해결하고 유사한 버그가 있을 법한 코드들도 미리 고치자. 다음번에는 놀라지 않도록!

텍스트 처리

텍스트 처리 언어를 익혀라

텍스트 언어를 제대로 사용할 수 있다면 유틸리티나 프로토타입을 빠르게 만들어 볼 수 있다.

  • YAML 파일을 Json 파일로 바꾸는 스크립트 작성해보기
  • camelCase를 snake_case로 바꾸는 스크립트 작성해보기
  • 변수이름을 여러 파일에서 자동으로 바꿔주는 기능 스크립트 작성해보기

엔지니어링 일지

장점

  • 기억보다 더 믿을 만하다
  • 진행 중인 작업과 직접적인 관계가 없는 발상을 일단 쌓아 놓을 수 있다
  • 고무오리의 역할을 하 수 있다
  • 회고록을 쓰는데 도움이 된다

실용주의 편집증

(2022.06.08)

계약에 의한 설계

DBC(Design By Contract)

  • 선행 조건: 루틴이 실행될 수 있는 요구 사항.
  • 후행 조건: 루틴이 보장하는 상태.
  • 클래스 불변: 루틴이 끝나는 시점에는 불변식이 참이 되어야 한다.

만약 호출자가 루틴의 모든 선행 조건을 충족한다면 해당 루틴은 종료 시 모든 후행 조건과 불변식이 참이 되는 것을 보장한다.

DBC 구현

코드에서 DBC를 지원하지 않는 언어에서는 다음과 같은 것들을 미리 정의해 보자.

  • 유효한 입력 범위
  • 경계 조건
  • 선행 조건
  • 단정문

DBC와 일찍 멈추기

DBC를 사용하면 더 일찍 멈추고 문제에 대한 보다 정확한 정보를 알려줄 수 있다.
문제를 찾고 원인을 밝히기 위해서는 사고가 난 지점에서 일찍 멈추는 것이 유리하다.

의미론적 불변식

  • 의미론적 불변식: 절대 어겨서는 안되는 요구사항 e.g.) __오류 발생 시 소비자의 입장을 우선하라

    이것은 시스템의 여러 다른 부분에 적용할 수 있는 분명하고 간략하며 명확한 선언이다. 이는 모든 시스템 사용자와 맺는 계약이며 동작에 대한 우리의 보증이다.

(2022.08.07)

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

  • 오류 케이스에 대해 방어적으로 코드를 작성하라.
  • 로그만 찍고 예외를 흘려보낼 바에는 그냥 전파하는 것이 낫다
  • 문제가 발생했을 때에는 빨리 프로그램을 멈추는 것이 최선인 경우가 많다.

단정적 프로그래밍

  • 절대로 일어날 리 없는 일은 없다.
  • 그럼에도 그런 생각이 든다면 단정문(assertion)을 사용하라.
  • 단정은 결코 일어나면 안 되는 것들을 검사할 때 사용해야 하며 오류 처리를 해야하는 곳에 사용해서는 안된다.
  • 성능 이슈가 큰 경우를 제외하고 단정 기능을 켜 둬라.

리소스 사용의 균형

  • 리소스를 할당하는 함수나 객체가 리소스를 해제하는 책임 역시 져야한다.
  • 리소스를 할당한 순서의 역 순으로 해제하라.
  • 코드의 여러 곳에서 동일한 구성의 리소스들을 할당하는 경우에는 언제나 같은 순서로 할당해야 교착(deadlock) 가능성을 줄일 수 있다.
  • 실용주의 프로그래머는 자신을 포함해서 아무도 믿지 않는다.
  • 리소스 별로 레퍼(wrapper)를 만들고 모든 할당과 해제 기록을 점검할 수 있게 하는 것이 좋다.

헤드라이트를 앞서가지 말라

우리는 너무 먼 미래는 내다볼 수 없고, 정면에서 벗어난 곳일수록 더 어둡다.

  • 신중하게 작은 단계들을 밟아라
  • 더 많이 예측하려 할수록 틀릴 가능성은 높아진다.

구부러지거나 부러지거나

(2022.08.14)

결합도 줄이기

열차사고

  • 묻지 말고 말하라: 다른 객체의 내부 상태에 따라 판단을 내리고 그 객체를 갱신해서는 안 된다.
  • 메서드 호출을 엮지 말라: 무언가에 접근할 때 "."을 하나만 쓰려고 노력해 보라. (파이프라인 제외)

글로벌화의 해악

전역 데이터를 피하라: 싱글턴, 외부 리소스
전역적이어야 할 만큼 중요하다면 API로 감싸라.

실세계를 갖고 저글링하기

  • 유한 상태 기계
  • 감시자 패턴(Observer Pattern)
  • 게시-구독(PubSub)
  • 반응형 프로그래밍과 스트림

변환 프로그래밍(파이프라인)

프로그래밍은 코드에 관한 것이지만, 프로그램은 데이터에 관한 것이다.

  • 연결된 변환들로만 코드가 표현되기 때문에 읽기 쉽다.
  • 상태를 쌓아놓지 않기 때문에 결합을 줄일 수 있다.

0개의 댓글