[3주 완독 Daily 서평] 실용주의 프로그래머 - 8

이건우·2022년 4월 2일
0

책 서평 시리즈

목록 보기
8/20

범위 : [7장 코딩하는 동안]

태그 - TIL, nomadcoder, 개발자북클럽, 노개북, 서평, 책

코딩하는 동안

코딩에 들어가면 우리는 대부분 설계 내용을 컴퓨터가 실행 할 수 있는 문장으로 바꾸는 일만 하면 된다고들 생각한다. 하지만 이런 태도는 소프트웨어 프로젝트가 실패하는 가장 큰 원인이다. 이렇게 된 태도로 시스템 이 너저분해지고, 비효율적이며, 구조가 망가지고, 유지보수가 힘들어 지는등 한마디로 완전히 잘못되고 만다. 그렇다면 우리는 어떤 태도로 코딩에 임하는것이 좋을까?

실용주의 프로그래머는 모든 코드를 비판적인 시각으로 바라본다. 자기 자신의 코드 또한 예외가 아니다. 우리가 만든 프로그램설계와 언제나 개선의 여지를 찾아 낸다. '리팩토링'을 진행하면서 프로젝트를 진행하면 끊임없이 기본 코드를 개선할수있는 기법들을 살펴볼수있다.

또한 테스트는 버그를 찾는 작업이 아니며, 코드의 피드백을 받는 작업이다. 대부분 코드의 긍정적인 반응은 테스트를 작성할때, 생각할때 나타나는것이다. 테스트 할땐 고정관념을 떨치기 매우 어렵고 어떻게 넓은 범위에 테스트를 시킬지, 당버그가 나타났을때 어떻게 대처 해야할지 생각해봐야한다.

코딩은 대부분 반복적인 일이지만, 잠재적인 문제들을 점검하며, 예상치 못한일이 생기더라도 정신을 늘 기민하게 유지하면 재앙을 막을 수 있다.

Topic 37 파충류의 뇌에 귀 기울이기

우리는 동물적인 부분, 즉 '파충류의 뇌'를 무시하라고 배웠다. 본능은 우리의 뇌 무의식속에 세워져있는 단순한 패턴들의 반응이다. 일부는 선천적, 일부는 학습효과인데 '프로그래머'로서의 경험이 늘어갈 수록 뇌에는 암묵적인 지식이 쌓인다. (잘되는 방법, 안되는 것, 오류) 모든 본능은 어디서 왔는지 공통적으로 말로 표현할 수 없는것. 생각이 아니라 느끼는 것 이다.

이럴떄의 해결책은 본능이 일단 반응하고 있음을 인지하고 , 왜 그런느낌이 드는지 알아야 한다. 이런 '파충류의 뇌'가 프로그래밍 과정 중에 우리에게 무언가를 말하려고 할때의 상황을 살펴볼것이다.

백지의 공포

"아.. 눈앞이 캄캄하다.. 아무것도 보이지 않는다."

누구나 텅 빈 화면을 두려워한다. 프로젝트에 새로운 모듈을 추가하는 일도 마찬가지다. 많은 사람이 일을 시작하는 첫 발짝을 미루고 싶어한다.

첫번째 원인

파충류의 뇌가 우리에게 무언가 할말이 있다.! 어떤 작업을 앞두고 마음속에 의심이 계속 남아 있거나 웬지 꺼림직하다면, 우리의 경험이 우리에게 말을 거는 중일지도 모른다.! 그 느낌에 따르자.! 정확히 무엇이 문제인지는 짚지는 못하더라도 시간을 좀 주면 아마 실체가있고 대응책있는 무엇으로 구체화 될것이다.

두번째 원인

혹은, 단지 우리가 실수 할까봐 두려운 것일 수가 있다. 이것은 합리적인 두려움이다. 그래서 코드의 오류를 자신의 부족한 능력으로 받아들일수 있다.

자신과 싸우기

어떤날엔 코딩이 잘되는날이, 어떤날엔 코딩이 잘 안되는 날이 있을것이다. 하지만 프로라면 계속 나아가야 하지않을까? 그리고 또 한발 내디어 맡겨진 일을 해야하지않을까?

이것 또한 '파충류의 뇌'가 우리에게 말을 걸고 있는것이다. "작업이 필요이상으로 힘들어요." 라고 말이다. 이유야 어찌되었든 파충류의 뇌가 느끼고있다 . 그래서 우리의 주의를 끌기위해 필사적으로 노력하는것이다.

파충류와 이야기 하는법

우리는 본능,무의식, 내면에 귀를 귀울여야한다. 일단 하고있는 일을 멈추도록하자. 뇌가 정리할 수 있도록 약간의 시간과 공간을 확보해보자. 그리고 코드에 생각하지말고 키보드에 떨어져 잠시 머리를 비운채로 할 수 있는 일을 해보자. 생각이 저절로 우리의 뇌 층층이 스며들도록 놔두도록 하자. 그렇다면 언젠가 생각의 의식 영역으로 "아하!" 하는 순간이 찾아올것이다.

혹은 작성한 코드를 그림으로 그리고, 동료에게 설명해 보는방법도 좋다. 이러한 방법은 뇌에서 다른 부위에 문제를 노출하여 어려움을 겪는 부분을 뇌의 다른부분이 해결해줄것이다. 다른사람과 대화를 하다보니, 문득 더 좋은 아이디어가 생각날때가 많지 않았을까 ?

놀이시간이다.!

이젠 우리가 직접 행동할 떄다. 프로토 타이핑 해야한다. 이미 존재하는 코드위에 작업하고 있어서 기존 코드 때문에 문제해결이 여의치 않다면, 기존 코드를 잠시 다른곳으로 밀어두고 비슷한 것을 대신 프로토 타이핑으로 만들어라.

  1. 포스트 잇으로 '프로토 타이핑 중' 이라 써서 모니터 옆에 붙여라
  2. 프로토타이핑은 원래 실패한다고 자신에게 상기하자. 실패하지않더라도 상기해야한다. 버리는 것이라는점도 함께!! 손해볼 일은 전혀 없다.
  3. 텅 빈 에디터 화면에 배우고 싶은 것 혹은 하고싶은 것을 한문장의 주석으로 표현하자
  4. 코딩을 시작하자

중간 도중에 의심이 든다면 포스트잇을 다시 살펴보자. 그리고 문제로 구체화 된다면 즉각 해결하자. 실험을 마쳤는데도 여전히 불안하다면 다시 처음부터 시작한다. 첫단계는 산책과 수다, 그리고 휴식이다.

하지만, 우리 경험에 비추어 보면 우리는 이미 콧노래를 흥얼거리며 첫번째 프로토타입을 만들것이다. 코드를 만드는 느낌을 즐기고 있는것이다.!

빨리 해치우고 싶다. 빨리 이자리를 뜨고싶다. 이 일을 끝내자!!

'여러분'의 코드뿐이 아니다.

다른사람이 작성한 코드를 다루는 경우도 많다. 저마다 다른 본능을 가지고 있으므로 우리와 다른 결정을 내렸을것이다. 꼭 더 나쁜것은 아니고 그저 '다를뿐'이다.

다른사람의 코드를 기계적으로 읽으면서 중요해 보이는 대목은 메모해 가면서 묵묵히 시간을 투자 할 수도있다. 아니면 실험을 해 볼 수도 있다. 처리방식이 이상해보이는 부분이 눈에 띄면 적어놓자. 계속 작업하면서 패턴을 찾아보자. 만약 그런식으로 코드를 작성해야만 했던 원인을 찾아낼 수 있다면 코드를 이해하는 일이 훨씬 더 쉬워질지도 모른다. 그리고 은연중 다른사람의 적용한 패턴을 우리가 의식적으로 적용할 수도 있다. 그와중에 우리는 새로운 것을 배울 수도 있다 . 사실 코드 뿐만 아니라 이렇게 직감에 귀를 기울이는 방법은 계속 갈고 닦아야 한다. 그리고 이런 것들을 코드 외적으로 많은 기술에 적용 할 수있다. 하던일을 멈추고 느낌을 분석하라. 목소리에 귀를 기울여 주는 환경에 있다면 적극적으로 표현하라. 탐험하라. 어두운 출입구에 무언가가 숨어있을 것이다. 본능에 귀를 기울이고 문제가 우리앞에 튀어나오기 전에 미리 대처해라

Topic 38 우연에 맡기는 프로그래밍

우리는 우연에 맡기는 프로그래밍, 병사가 '지뢰밭'을 운좋게 탈출하는 것 처럼 '행운에 의존하는' 프로그래밍을 하지 말아야한다. 대신 '의도적으로 프로그래밍'해야한다.

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

코드가 잘 돌아간다 , 잘 돌아간다고 해서 방치하지 말자. 코드가 망가질 경우 애초에 왜 잘 돌아가는지도 모르기 때문에, 우리는 코드를 수정하고 고칠수가 없기때문이다. 그것은 단지 운이 좋았을 뿐이다. 우리도 물론 운에 맡길때가 있다. 우연한 행운과 주도 면밀한 계획을 착각한 경우가 종종있다.

구현에서 생기는 우연

작성된 방식이 그렇기 때문에 생기는 우연한 일들이 있다. 이런 우연에 기대다 보면 결국 문서화 되지않은 에러와 예외적인 경우의 동작에 의존하게된다. 루틴을 만든 사람의 의도는 그 루틴이 그런식으로 작동하는 것이 아닐 수도있다. 가장 극단적인 경우에는 우리가 호출한 루틴이 실제로 그렇게 설계된 루틴이 아님에도 우리가 원하는 효과를 내는것 처럼 보일수 있다는 것이다. 잘못된 순서로 호출하거나, 잘못된 맥락에 호출하는것도 이와 관련된 문제다.

만약 구현이 되었는데 불필요한 호출을 제거하지 않는다면, "이대로 돌아가니 불필요한 호출을 제거하지 않는다. 그대로 두는 편이 좋을거야.." 라는 함정에 쉽게 빠질 것이다. 하지만 짚고 넘어가야할 이유가 있다.

  1. 그냥 돌아가는듯 보이는 것일수도있다.
  2. 의존하는 조건이 단지 우연인 경우도 있다. 하드웨어적으로 CPU의 코어가 많거나 혹은 기타 다른 상황에선 이상하게 작동할지도 모른다.
  3. 문서화 되지않은 동작은 라이브러리 다음 릴리스에 변경될 수있다.
  4. 불필요한 추가 호출은 더 느리게 만든다
  5. 추가로 호출한 루틴에 새로운 버그가 생길 수도 있다.

다른 사람이 호출할 코드를 작성하고있다면 모듈화를 잘하는것, 잘 문서화한 적은 수의 인터페이스아래 구현을 숨기는것 같은 기본원칙들이 모두 도움이된다. 잘 정의된 계약도 오해를 막는데 도움이 될것이다. 문서화된 동작에만 의존하라 어떤 이유로든 그럴수 없다면 추측을 문서로 상세히 남기자.

비슷하다고 괜찮을 리는 없다

(시간 -1,+1 비슷함의 차이로 인한 프로젝트의 폐기 사례, 285Page, 뷰어기준 310Page )

유형패턴

실재로 존재하고 인식할수 없는 패턴보다 우연으로 가득하다. 통계적으로 모두 독립적인 사건임에도 불구하고 말이다. 테스트가 현재 장비에서 통과할수는 있어도 서버에선 통과하지 못하는 이유는 환경의 차이일 수도 있지만 그저 우연일 수도 있다. 가정하지 말아야한다. 증명 해야한다.

상황에서 생기는 우연

특정 상황에서 빚어지는 우연도있다.

(예시 GUI 애플리케이션 모듈 , 286Page, 뷰어기준 311Page)

암묵적인 가정

우연은 여러단계에서 우리를 오도할 수 있다. 요구사항을 만들어내는 단계부터 테스팅에 이르기까지 모든단계에서 그렇다. 모든 차원에서 사람들은 마음속 많은 가정을 품고 작업한다. 이런 가정을 문서화 하는 경우는 개발자마다 드물고 가정이 다를때도 많다. 확고한 사실에 근거하지않는 가정은 어떤 프로젝트에서든 재앙의 근원이 된다.

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

  1. 우리가 무엇을 하고있는지 알아야한다.
  2. 더 경험이 적은 프로그래머에게 코드를 상세히 설명가능한가 ? 그렇지 않다면 우연에 기대어 하는것이다
  3. 자신도 잘모르는 코드를 만들지 말아야한다.
  4. 계획을 세우고 그것을 바탕으로 진행해야한다.
  5. 신뢰할 수있는 것에만 기대라
  6. 가정을 기록으로 남겨라. 자신의 마음속에서 가정을 명확하게 하는데 도움이 될 뿐더라, 다른사람과 그에 대해 소통하는 데에도 도움이된다.
  7. 코드뿐만 아니라 우리가 세운 가정도 테스트해 보아야한다. 어떠닐이든 추측만 하지말고 실제로 시험해봐야한다.
  8. 노력을 기울일 대상의 우선순위를 정해라. 중요한것에 먼저 시간을 투자하자
  9. 과거의 노예가 되지말아야 한다. 기존코드가 앞으로 짤 코드를 지배하도록 두면 안된다. 어떠한 코드든 지배하도록 놓아두지 말아야한다.

Topic 39 알고리즘의 속도

실용주의 프로그래머가 거의 날마다 하는 또다른 종류의 추정이 있다. 바로 알고리즘이 사용하는 자원, 곧 시간 , 프로세서, 메모리등을 추정하는 것이다.

얼마나 걸리는지 알고 있다고 하더라도, 몇백만개라면 어떨까 ? 코드의 어느 부분을 최적화 해야할까 ?

알고리즘을 추정한다는 말의 의미

일반적으로 입력의 크기는 알고리즘에 영향을 준다. 입력의 크기가 클수록 알고리즘의 수행시간이 길어지거나 사용하는 메모리양이 늘어난다.

대문자 O 표기법

알고리즘은 주어진 환경에서 우리가 하는일이 말이되는지 가볍게 확인하는 정도에 가깝다. 하지만 훨씬 상세한 분석을 요구하는 경우 대문자 O표기법이 유용하다. 이 표기법은 근삿값을 다루는 수학적 방법으로 O()와 같이 표기한다. (자세한 알고리즘 설명 , 293Page, 뷰어 318Page)

상식으로 추정하기

상식을 이용해서 간단한 알고리즘들의 차수를 대부분 추정할 수 있다.

  1. 단순 반복문
  2. 중첩반복문
  3. 반씩 자르기
  4. 분할 정복
  5. 조합적

실전에서의 알고리즘 속도

회사에서는 대개 정렬 루틴을 작성하느라 시간을 소비하지 않는다. 라이브러리에 나와있는 정렬루틴을 주로 사용한다. 하지만 기본적인 알고리즘들은 계속해서 나타난다. 단순한 반복문을 작성할떄 우리는 그것이 알고리즘이란 사실을 안다.

Topic 40 리팩터링

프로그램이 발전함에 따라 점점 초기에 내린 결정을 다시 고려하고 코드의 일부분을 다시 작성할 일이 생긴다. 이것은 지극히 자연스러운 과정이다 코드는 정적인 존재가 아니다. 코드는 발전해야한다.

소프트웨어 개발은 건축보다 정원 가꾸기에 더 가깝다. 어떤 루틴이 너무 크게 자라거나 너무 많은것을 하려고 한다면 가지치기를 하는것 처럼 말이다. 계획되지않는 것들은 잡초제거 하듯 뽑아낸다.

코드를 고쳐쓰기,다시작업하기,아키텍처 만들기는 모두 아울러서 '리팩토링'이라 부른다. 핵심적인 부분은 아래와같이 정의한다.

  1. 활동은 체계적이다. 아무렇게나 하는것은 아니다
  2. 밖으로 드러나는 동작은 바뀌지않는다.

리팩터링을 한다고 해서 모든 정원을 갈아엎듯 해서는 안된다. 정확하는 목적을 가지고정밀하게 접근하는 활동이다. 무질서로 다시 쓰는 것이 아니다.

리팩터링은 언제할까?

작년이나 혹은 10분이지난뒤 더많은것을 알게 되었을때 '리팩토링'을 한다. 무엇이든 잘못되었다는 생각이 들 때가 있다. 주저하지말고 리팩토링을 해야한다.

(리팩토링의 과정 303Page, 뷰어 328 Page)

많은 개발자들이 코드에 조금 개선할 부분이 있다는 이유로 다시돌아가서 코드열기를 주저한다. 일정의 압박은 리팩터링을 하지않은 단골 핑계다. 이는 설득력이 떨어지며, 지금 리팩터링을 하지않으면 일이 더 진척되었을때 훨씬더 긴 시간을 투자해야한다. 일정의 여유가있을까 ? 과연..

"일찍 리팩터링하고, 자주 리팩터링해라!"

코드의 부수효과도 시간이 지남에 따라 더욱 심화될 수도 있다. 리팩터링도 문제가 작을때 코딩하는 동안 함께 진행해야 좋다. 리팩토링할 시간을 확실히 포함시켜 두도록해라. 코드를 사용하는 사람들이 코드가 조만간 재작성 될것이란 사실과 재작성이 그들의 코드에 미칠 영향을 인지하도록 해야한다.

리팩터링은 어떻게 하는가?

리팩터링의 본질은 재설계다. 요구사항이 바뀐다면 언제래도 재설계의 대상이 될수 있다. 하지만 그렇다고 거대한 규모의 코드를 닥치는대로 헤집어 놓으면 나중에는 리팩터링보다 더 않좋은 처지에 놓을지도 모른다.

  1. 리팩터링과 기능 추가를 동시에 하지말자
  2. 리팩터링을 시작하기전 든든한 테스트가 있는지 먼저 확인하자. 할수 있는한 자주 테스트를 해보자. 망가졌을경우 그 사실을 재빨리알 수가있다.
  3. 단계를 작게 나누어 신중하게 작업하자. 클래스 필드 하나를 다른 클래스로 옮기기, 메서드를 쪼개기, 변수를 바꾸기 같이 작은단위로 작업해야한다.

고통을 관리하라. 고쳐라. 지금은 고통스러울 지라도 앞으로 더욱 고통스러워질것 같으면 지금 고치는 것이 낫다. 깨진 창문을 그대로 놓아둬서는 안된다.

Topic 41 테스트로 코딩하기

"우리 코드가 잘 작동하는지 확인하려는 거죠"

과연 이것이 전부일까 ? 우리는 이 대답이 틀렸다고 생각한다. 과연 우리가 생각하는 테스트의 중요한 가치는 무엇일까 ? 우리는 왜 테스트를 해야한다고 생각하는것일까 ?

테스트가 코딩을 주도한다

테스트에 대해 생각함으로 써 코드의 결합도는 낮추고 유연성은 올릴 수 있었다. (전역 데이터 베이스 연결을 쓰지않고, 데이터 베이스의 연결을 넘겨줌. 그리고 우리가 테스트 하는 필드의 이름을 매개변수로 지정함으로 유연성 향상)

우리는 메서드의 테스트 작성에 대해 생각함으로써, 코드 작성자가 아니라 사용자인것처럼 외부의 시선으로 보게되었다. 이것이 바로 테스트가 주는 가장 큰 이득 일지도 모른다. 테스트는 코딩을 인도하는 필수의 피드백이다.

무언가 테스트를 하기좋게 만들면 결합도도 낮아진다.

테스트 주도 개발

  1. 추가하고 싶은 작은 기능 하나를 결정한다

  2. 그 기능이 구현되었을떄 통과하게 될 테스트를 하나 작성한다

  3. 테스트를 실행한다. 다른 테스트는 통과하고 방금 추가한 테스트 딱 하나만 실패해야한다.

  4. 실패하는 테스트를 통과시킬수 있는 최소한의 코드만 작성한다.

    그리고 모두 통과하는지 확인.

  5. 코드를 리팩터링한다. 방금 작성한 테스트나 함수를 개선할 수 있는 부분이 없는지 살펴본다. 개선한 후 테스트가 계속 통과하느니 확인한다.

핵심은 이 반복주기가 몇분정도로 매우 짧아야 한다는 것이다. 이제 막 배우기 시작한사람에게 테스트주도개발(TDD)는 매우 효과가있다. 하지만 TDD의 노예가 된 사람들도 있다. 다음과같은 행동징후 (Page 311, 뷰어기준 336Page)

TDD:목표가 어디인지 알아야 한다.

"한번에 한입씩!"

TDD 장점으로 늘 언급된다. 전체문제를 완전히 파악하기 힘들때 한번에 한번 테스트 하나씩 작은 단계를 밟는 것이다. 하지만 이런 접근 방법이 우리를 잘못된 길로 인도할 수도 있다. 코딩을 하는 진짜 이유는 무시한체 계속해서 쉬운 문제들만 만지작 하도록 유도하는 것이다.

상향식 하향식이 아닌 끝에서 끝까지 만들어라

개발을 처음 시작할때 우리가 무엇을 하고있는지 모른다. 하향식 설계는 전체요구사항을 시작할때 다알고 있다고 가정하지만, 사실은 알 수없다. 반면에 상향식 설계는 추상화계층을 쌓다보면 결국 하나의 최상위 해결 계층에 도착할것이라 가정하지만, 그 목표가 어딘지 모르는데 어떻게 각 계층의 기능을 결정할 수 있단 말인가 ?

한쪽 끝과 다른 쪽 끝을 잇는 조그만 기능 조각들을 만들고, 그과정에서 문제에 대하여 배워야한다.

다시 코드로

컴포넌트 기반 개발은 오랫동안 소프트웨어 개발이 추구해온 고귀한 목표였다. 소프트웨어들을 만들때 맨 처음부터 테스트가 가능하도록 만들고, 코드들을 서로 연결하기전에 코드를 하나하나 철저하게 테스트해야한다.

단위테스트

하드웨어 칩 차원 테스트는 대체로 소프트웨어 '단위테스트'에 해당한다고 할수 있다. 두 경우 모두 각 모듈의 동작을 검증하기위해 다른것 들로부터 분리시켜놓고 테스트를 수행한다.

소프트웨어 단위 테스트란 어떤 모듈에게 이것저것 시켜보는 코드를 가리킨다. 일종의 인위적인 환경을 구축한 다음 테스트할 모듈의 루틴을 호출한다. 그런 다음 반환된 결과들일 이미알고 있는 값과 비교해 보거나 똑같은 테스트를 이전에 돌렸을 때 나온값과 비교하여 올바른지 검사한다. 동일한 테스트를 코드 수정후 다시 돌려보는것을 희귀 테스트 라고 한다.

계약을 지키는지 테스트하기

우리는 어떤 코드단위가 자신이 맺은 계약을 잘 지키는지 확인하는 테스트 케이스를 작성하고자 한다. 이런 테스트는 우리에게 두가지를 알려준다. 하나는 코드가 계약을 지키는지의 여부, 둘은 코드로 표현된 계약의 의미가 우리가 생각하는것과 일치하는지의 여부이다.

(실전 사례 예시 책 316Page, 뷰어 341Page)

임시테스트

디버깅 작업이 끝나면 이런 임시테스트를 정식 테스트의 형태로 만들어 둬야한다. 한번 잘못된 코드라면 다시 잘못될 가능성이 높다. 우리가 만든 테스트를 그냥 버리지 말고 기존단위 테스트 군단에 합류해라

Topic 42 속성기반 테스트

함수를 작성할때 단위테스트도 함께 작성하기를 추천한다. 단위 테스트를 추가하기 위해 테스트 대상에 대한 지식을 바탕으로 일반적으로 문제가 될만한 상황을 떠올릴 것이다.

함수의 코드를 쓰고, 우리가 테스트를 작성한다면 우리의 가정이 둘 다에 들어갈 수도 있지 않을까? (둘다 잘못된경우)

계약, 불변식, 속성

계약을 코드에 포함하고, 선행조건에 맞추어 입력을 넣으면 코드가 생산하는 출력이 주어진 후행조건에 맞음을 보장해준다. 불변식 이라는것도 있는데 함수 실행 전후로 계속 어떤 부분의 상태에 대하여 참이 되는 조건을 말한다. 이렇게 코드에 존재하는 계약불변식을 뭉뜽그러 속성이라고 부른다. 이것을 테스트자동화에 사용할 수 있는데 이것을 '속성기반 테스트' 라고 한다.

속성기반 테스트는 우리를 자주 놀래킨다

속성기반 테스트가 강력한 까닭은 그저 입력을 생성하는 규칙과 출력을 검증하는 단정문만 설정한 채 제멋대로 작동하도록 놔두기 때문이다. 정확히 어떤일이 일어날지 알 수 없다. 테스트가 통과 할 수도, 단정문이 실패할 수도 있다. 아니면 코드가 주어진 입력을 제대로 처리하지못하고 중간에 멈춰버릴수도 있다.

좌절감이란, 정확히 무엇이 실패했는지 찾아내기 까다로울수도 있다는 것이다. 단위 테스트는 두가지 역할을 한다.

첫번째, 속성기반 테스트의 여러가지 다른 수행 결과와 상관없이 문제가 발생하는 상황에 집중할 수 있게 해준다.

두번째, 단위테스트가 희귀테스트 역할을 한다. 속성 기반 테스트는 임의의 값을 생성하여 사용하기 때문에 다음번에 실행했을때 똑같은 값을 테스트 함수에 넘긴다는 보장이없다. 문제를 일으켰던 값을 사용하는 단위 테스트를 만들어 두면 버그가 완전히 해결되었음을 보장할 수 있다.

속성기반테스트는 설계에도 도움을 준다

단위 테스트의 주요 장점중에 코드에 대해 생각하게 만드는것이 있다고 설명했다. 속성기반 테스트는 우리의 코드를 '불변식'과 '계약'이라는 관점으로 바라보게한다. 무엇이 변하지않아야하고 어떤 조건을 만족해야 하는지 생각하게 된다. 이런 관점으로 보면 코드에 마법과 같은 효과가 일어난다. 경계조건은 줄어들고, 데이터의 일관성을 해치는 함수는 더 도드라진다. 그리고 속성기반 테스트가 단위테스트를 보완한다고 믿는다.

Topic 43 바깥에서는 안전에 주의하라

나머지 90%

"완성되었다!"

우리는 90%완성한 것이다 하지만 이제는 나머지 90%를 고려해야한다. 코드가 잘못될 수 있는 경우를 찾아보고, 각 경우에 대한 단위 테스트를 추가하는것이다. 잘못된 매개변수를 넘기거나 리소스를 흘리거나 리소스가 모자라는 경우 따위를 생각해 보아야한다.

패치를 적용하지않는 구식 시스템이 맨몸으로 인터넷에서 생존할 수 있는 시간은 겨우 몇분 정도다. 그보다 짧을 수도 있다.

조용히 숨어있는 것으로 보안을 대신하려는 생각은 통하지 않는다.

기본보안원칙

실용주의 프로그래머는 건전한 정도의 편집증을 갖고있다 우리는 우리가 실수도 하고 한계도 있다는 것을 안다. 외부공격자가 우리가 남겨놓은 어떤 틈이든 벌리고 들어와 시스템을 망가트리려 할 것도 안다. 개발하고 배포하는 환경에 따라 제각각 보안을 위해 해야할 일들이 있겠지만 우리가 언제나 명심해야 하는 기본 원칙 몇가지 있다.

  1. 공격 표면을 최소화 하라
    • 코드의 복잡성은 공격매개체를 유발한다.
    • 입력 데이터는 공격 매개체이다.
    • 인증이 없는 서비스는 공격 매개체이다.
    • 인증을 요구하는 서비스도 공격매개체다.
    • 출력데이터는 공격 매개체다.
    • 디버깅 정보는 공격매개체다.
  2. 최소권한원칙
  3. 안전한 기본값
  4. 민감 정보를 암호화하라
  5. 보안 업데이트를 적용하라

(책 페이지 332 ~ 338 Page, 뷰어기준 357~363 Page)

상식 대 암호

암호학에 있어서 상식이 맞지않을수 있다는 점을 명심해야한다. 암호화에 있어서 첫번째 규칙이자 가장 중요한 규칙은 절대 직접 만들지 말라. 는 것이다. 암호세계에서는 엄청나게 작고 아주 사소해 보이는 오류가 전체 암호화를 무용지물로 만들어 버릴 수 있다. 신뢰할 수있는곳에 의지해야한다. 많이 검토하고, 철저하게 검사하고, 잘 유지 보수되며 자주업데이트 되는 라이브러리와 프레임워크를 사용해야한다. 가급적 '오픈소스'가 좋다.

Topic 44 이름짓기

이름이라는게 무슨 의미가 있을까? 프로그래밍에서는 이름이 '모든것'이다. 이름은 아주아주 중요하다. 이름은 우리의 의도와 믿음을 잔뜩 드러내기 때문이다. 우리는 코드에서 하는 역할에 따라 이름을 지어야 한다고 생각한다. 이말은 무언가를 만들때마다 잠시 멈춰서 '내가 이것을 왜 만드는 거지?' 하고 생각해야 한다는 뜻이다.

스투프 효과?

술술 읽히지만 색깔을 말하려 하면 훨씬 힘들다. 우리의 뇌는 단어를 꼭 지켜야 한다는 것으로 인식한다. 그렇다면 우리는 그것에 맞게 이름을 잘지어야한다.

일관성

랄프왈도에머슨은 "어리석은 일관성은 소인배의 말썽꾸러기 도깨비다" 라는 말을 한것으로 유명하다. 에머슨은 19세기 사람으로 당연히 프로그래밍 팀에 속하지는 않았지만 말이다.

반드시 팀의 모든 사람들이 각 단어의 뜻을 알고 일관성 있게 사용해야한다. 한가지 방법은 많은 의사소통을 장려하는 것이다. 모든 사람이 짝 프로그래밍을 하고 자주 짝을 바꾼다면 용어의 의미는 자연스럽게 퍼져나갈것이다.

혹은 팀에게 특별한 의미가 있는 단어를 모두 모은 프로젝트 용어사전을 만드는 방법도있다.

이름바꾸기는 더 어렵다

아무리 좋은이름을 짓기위해 노력한다 하더라도 모든것은 변한다. 코드는 리팩터링 되고 사용방식은 바뀌고 의미는 미묘하게 달라진다. 부지런히 이름을 계속 바꾸지 않으면 악몽같은 상황에 빠지게된다. 무의미한 이름보다 더 고약한 잘못된 이름을 사용하는 코드가 되는것이다. 잘못된이름을 바꿀수 없는 상황이라면 더 큰 문제가 되는것이다. 이름을 잘 지어야한다. 문제를 고치고 나서 이름을 바꿔야한다.

이름을 바꾸기쉽게 만들고 자주 이름을 바꿔라. 그렇지않으면 새로운 사람이 올때마다 매번 설명해줘야할것이다.

profile
내가 느낌만알고 한줄도 설명할줄 모른다면 '모르는 것'이다.

0개의 댓글