All Articles

실용주의 프로그래머 pt. 4

읽기에 앞서…

실용주의 프로그래머를 읽고 느낀점을 써보려고 합니다. 제가 느낀바로는 이러한 내용이다 하는 방향으로 기술할 것 같습니다.

craftsman 이라면 연장 정도는 손에 익혀둬야하는게 맞다. 프로그래머도 자신의 툴을 손에 익혀야하는 것이 당연하다.

도구는 재능을 증폭시켜준다. 도구가 좋다는 가정하에 쓰는법만 알면 반드시 최고의 결과를 보장해준다. 생산성을 높히려면 경험을 통해 툴쓰는 법을 자꾸만 많이 익혀둬야 한다. 내 툴박스에는 자꾸만 뭔가 추가될거고 언젠간 빼게될 것들이 막 생길 것이다. 필요에 따라 어떤툴을 써야할지도 알게 될 것이다.

모양을 만들 재료는 어떤 것인가? (일반 텍스트의 힘)

IDE에만 익숙해지지 말고 간단한 쉘 프로그라밍 정도는 할 줄 알아야한다! (shell games)

(파워 에디팅) 장에서는 툴 어케쓰면 좋은지 알려준다.

(소스코드 관리) git 써라

(디버깅) 디버깅은 완벽한 프로그램을 만들기 위한 필수다. 디버깅을 못한다 = 좋은 프로그래머가 되긴 힘들지 않을까

(텍스트 처리) awk, perl, python을 소개

(코드 생성기)는 봐야 알듯.

14. 일반 텍스트의 힘

일반 텍스트(plain text)를 의미.

사람이 이해할 수 있는 텍스트를 쓰는게 좋다. 그냥 플레인텍스트 뿐 아니라 XML이나 HTML처럼 잘 정의된 구조를 가진거면 일반 텍스트 정도로 이해된다.

일반 텍스트를 쓰면 데이터가 어떻게 흘러가는지 보다 빠르게 이해할 수 있다.

단점)

  1. 이진포맷보다 데이터 크기가 더 클 수 있다
  2. 플레인 텍스트 처리엔 더 많은 시간이 들 수 있다.

그런데도 불구하고 쓸 필요가 있는 이유는?

  • 구식이 되는 것에 대한 보험
    • 끊임없이 변하는 애플리케이션의 내용에 대해 사람이 이해하기 편해진다
  • 호환성
    • 거의 어지간한 컴퓨터 세계의 도구들은 일반 텍스트를 다룰 수 있다. e.g. 설정파일 관련 데이터라 해도 git에 넣어서 변화를 감지하거나, 그게 아니면 diff나 fc같은거로 변화를 감지할 수 있다. sum으로 첵섬 만들어서 변화감지를 할 수도 있다.
  • 더 쉬운 테스트
    • 테스트 시에 써먹을 값으로 테스트 데이터를 쉽게 업뎃,추가,수정이 가능하다.
    • 스크립트로 더 빨리도 가능하다.

알아보기: yaml은 뭐임?

15. 조개 놀이(shell games)

텍스트를 다루는 프로그래머라면 쉘에서 주로 놀게될 것이다. 파이프, 매크로 등…

GUI도 존나 좋은거다. 대놓고 직관적이니까. 근데 텍스트에서의 장점은 따로 있다. 그것은 ‘자동화’, ‘매크로’가 그것이다. 이건 미쳤다. 파일 이름 일일이 변경이나 필요한 작업들은 쉘이 더 빠를 때가 있다.

e.g. Makefile보다 더 최근에 바뀐 모든 c 파일을 찾아라

$ find . -name '*.c' -newer Makefile -print

소스의 zip/tar 아카이브를 떠라

$ zip archive.zip *.h *.c
$ tar cvf archive.tar *.h *.c

지난주에 바뀌지 않은 자바파일은 무엇인가?

$ find . -name '*.java' -mtime +7 -print

그 중에 어느 파일이 awt 라이브러리를 쓰고있나?

$ find . -name '*.java' -mtime +7 -print | xargs grep 'java.awt'

(args는 -exec같은 식으로 쓰이는데 더 효과적인듯 보인다. xargs란?)

쉘은 잘 드는 칼 같은거라서 겉보기엔 무서워보이는데 매우 좋다.

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

자바에서 명시적으로 import하는 패키지 이름의 합집합 목록을 만들어서 list란 파일에 저장하기

$ grep '^import ' *.java |
	sed -e 's/.*import *//' -e 's/;.*$//' |
	sort -u > list

이런식으로 매우 좋다!

16. 파워 에디팅

세상에 에디터는 널렸다. 근데 내가 쓰는거에 대해선 좀 능숙해질 필요가 있다. 정말 남이봐도 잘쓴다 싶을정도로… 하나를 쓴다해도 무슨 기능이 있는지 통달할 필요가 있다!

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

에디터 하나를 잘 골라서 잘 쓸 수 있도록 만들고 모든 편집작업에 그걸 사용하도록 하라! 무엇을 쓰든간에 정말 효율적으로 바로바로 필요한 기능이 나오도록 하게 하는 것이 베스트다. 또한 그 에디터가 어지간한 플랫폼에서 다 쓸 수 있는지도 파악하면 도움이 된다. (무슨 작업환경에서든 다 쓸 수 있도록 해두라는 말)

책에서 추천하는 에디터의 기능: 그럴싸한 에디터라면 갖추고있는 몇가지 기능은 다음과 같다.

  • 설정변경 가능

    • 폰트, 색깔, 윈도우 크기, 키 입력 바인딩 등을 바꿀 수 있는가?는 다시말해 내가 필요한 기능을 모두 키보드로 조질 수 있는가? 의 의미가 된다.
  • 확장 가능:

    • 새 프로그래밍 언어를 즉각 대응할 수 있는가? 새 컴파일러에 대응할 수 있는가? 또한 고려요소중의 하나다. 혹은 이런것들을 ‘가르칠’ 수 있어야 한다.
  • 프로그램 가능:

    • 복잡하고 다단계의 작업을 수행할 수 있도록 에디터를 ‘프로그래밍’ 할 수 있어야 한다. 매크로나 내장 스트립트가 있는가?

많은 에디터들은 다음과 같은 특정 고유기능들이 있다:

• 구문 강조(syntax highlighting)
• 자동 완성
• 자동 들여쓰기
• 코드나 문서 상용어구 지원
• 관련 도움말 시스템
• IDE 기능(컴파일, 디버그 등)

메모장으로 잘라붙이기 할 수도 있다. 그런데 예를들어 소스코드를 내가 원하는 내용으로 정렬할 필요가 있을 때는 어떻게 하면 좋을까?

vi기준 :.,+3!sort 하면 알파벳 순으로 라인 정렬이 된다.

또는 프로그래밍할 때 처음 내가 입력할 필요가 없는 것들을 파일 생성과 동시에 대신 입력해주기도 한다. 예를 들어 이런것들…

• 클래스와 모듈 이름(파일 이름에서 도출된것)을 자동입력
• 소스코드 작성자 이름, 저작권 선언
• 특정 언어의 스켈레톤 코드(생성자, 소멸자 같은것들 자동작성)

책에서는 내가 쓰는 에디터가 무엇인지, 어느정도 쓸 수 있는지에 따라 다음 행동을 제시한다.

나의 실력 앞으로 어떻게 하면 좋을까요?
나는 여러 에디터 중 기본 기능만 쓴다 강력한 에디터 하나를 골라잡아서 제대로 익혀보세요
선호하는 에디터가 있긴 한데, 기능을 다 쓰지는 않는다 그걸 제대로 배워서 입력하는 키 갯수를 최대한으로 줄여보세요
선호하는 에디터가 있고 가능하면 그걸 쓴다 지금 하는 작업 이외에 다 많은 작업에 쓰도록 확장해보세요

17. 소스코드 관리

Git 씁시다! 형상관리를 SE시간에 배웠고 그 예시로 Git이 당당히 나왔다. 필요하다면 SVN도 알아둬야할 것 같다.

소스코드 관리 시스템(SCCS: Source Code Control System) 은 누가 소스를 바꿨고 주간 소스코드 버전차이, 어느 릴리즈에 몇줄 바뀌었는지? 어느 파일이 자주 바뀌었는지? 등을 다 파악할 수 있다. 이는 추후에 버그트래킹, 퍼포먼스/품질 관리 등에 쓰이기 좋은 정보들이다.

브랜치를 나누어서 특점 시점에서 개발 로그를 다르게 남길 수도 있다.

여러사람이 동시에 작업할 수도 있다.

이는 작은 프로젝트든 큰 프로젝트든 어디든 다 쓰일 수 있다.

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

전체 프로젝트를 제품 빌드를 자동화하고 반복작업을 가능하게 한다.

갓-깃 씁시다.

18. 디버깅

프로그램은 완벽하게 짤 수 없다. 그렇다면 디버깅에 관련한 문제를 알아보고 찾기 힘든 버그를 찾아내는 일반적인 전략 몇가지를 알아보자. 피할 수 없으면 효율적으로 격파해야지!

안되는 코드는 풀어내면 된다. 그 방법중에 하나가 디버깅이다. 못짠 코드는 누구나 만들어낼 수 있다. 절대로 다른 팀원을 비난하면 안 된다!

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

디버깅하면 내 코드가 틀릴 수 있다는 걸 염두에 두고 해야한다. 디버깅 때는 프로젝트의 압박이 있다하더라도 다음 철칙을 항상 염두에 두자!

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

뭐 때문에 버그가 생겼는지, 인과관계가 어떻게 되어있는지 생각해보는게 정말 중요하다. 버그가 터져도 ‘와 말도 안돼’, ‘버그 터질리가 없는데’ 같은 소리는 의미가 없다. 왜냐고? 진짜 터졌으니까.

디버깅할 때는 ‘근시’를 조심해야 한다. 바로 눈에 터지는 것만 없애려 하지말고 문제의 근본적인 원인을 분석해서 어떻게 터지는지 분석해야 한다. 특정 증상만 고치지 마라!

  • 어디에서부터 디버깅해야되나?

사실 버그 리포트는 정확한 과학이 못 된다… 우연히 어떻게 터졌는지 모르는 것들이기 때문이다. 자세한 사항을 보기 위해 실제 버그가 어떤 상황에 정확히 어떻게하면 터지는지를 알아야한다.

  • 가능하다면 처음 받은 자료 이상을 얻기 위해서 버그 리포트한 사용자를 인터뷰할 필요가 있다.
  • 경계 조건, 실제 최종 사용자 패턴 모두를 철저히 테스트해야한다.
  • 디버깅 전략
  • 데이터를 가시화하라!

    • 프로그램이 다루는 데이터가 어떤거인지 살펴보자. GUI라면 대화상자 필드, 변수이름 = 자료값 이정도일 것.
    • 데이터와 데이터가 어떻게 데이터를 주고받는지 시각적으로 보여주는 디버거를 쓰면 보다 쉽게 오류를 찾아낼 수 있다!
  • 트레이싱(tracing)

    • 트레이싱 구문은 디버거를 쓸 때 ‘여기까지 도달’, ‘x값 = 2’등 파일에 뿌려주는 진단용 메시지를 말한다. call tree를 타고 내려갈 때도 쓴다. 이런 구문은 규칙적이고 일관적이어야 분석하기 편하다.
  • 고무오리

    • 문제를 그냥 쭉 설명해보다보면 ‘아차’하고 실수한 부분을 체크할 수 있다. 그런 통찰을 가끔씩 할 수 있다.
  • 제거 과정: 내 코드가 문제냐, OS가 문제냐?

    • OS의 코드가 고장날 확률이 높을까, 내 코드가 고장날 확률이 높을까? 아래의 팁은 이런 문제와 관련해서 관련 일화를 하나 소개한다.
    • 해당 일화를 요약하자면 코드의 어디가 망가졌는지 문서를 정독해서 원인을 찾았다는 말. 문제는 바로 본인의 select 관련 코드였던 것이다.

Tip 26. ‘select’는 망가지지 않았다.

  • 놀람의 요소
    • 버그가 터지면 내가 제대로 짰다 하는걸 처음부터 다시 생각하라. 버그가 안터지겠다 싶은 곳에서부터 경계조건을 테스트하고 몇번 돌려써도 안터질 코드인가 다시 생각해야한다. 납득하기 싫지만 내 가정이 잘못되었을 수 있다. 뭘 어떻게 가정하고 돌렸을지를 파악하고 데이터로 경계조건으로 코드가 옳음을 ‘증명’하라!

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

버그를 고쳤다면, 이 버그가 왜 일찍 보이지 않았을까? 생각할 필요가 있다. 이 버그를 일찍 잡을 수 있도록 단위 테스트나 다른 테스트를 수정할 필요가 있는지도 고려하는 것이 좋다. 이거 비슷한 오류가 터질 코드가 있을 것 같으면 지금 같이 수정하면 된다.

위 글을 통해 디버깅 체크리스트를 책에서는 제시한다.

  • 보고된 문제가 내재하는 버그의 직접적인 결과인가, 아니면 단순히 증상인가?
  • 버그가 정말로 컴파일러, OS코드에 있나? 아니면 내 코드에 있나?
  • 이 버그를 팀원에게 설명한다 하면 어떻게 말할 것인가?
  • 의심되는 코드가 단위 테스트를 통과한다면, 테스트는 충분히 완전한 것인가? 이 데이터로 단위 테스트를 돌린다면 무슨일이 일어나는가?
  • 이 버그를 일으킨 조건이 다른 곳에도 존재하는가?

19. 텍스트 처리

텍스트 처리를 위해 awk, sed같은툴이나 쉘 뿐 아니라 파이썬이나 펄도 배울 필요가 있다!

어떤걸 처리하는데는 다른 특정 언어가 더 나을 수도 있다. 다른언어들로 구현해봤을 때 얼마나 짧고 빠르게 구현할 수 있는가를 논했을 때 C가 150줄일 때 펄은 17줄이면 끝일 정도니까(책피셜)

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

텍스트 처리 언어의 적용범위는 상당히 넓다:

  • DB스키마 관리: 스크립트로 스키마 정의 파일을 읽고 다음의 요소들을 생성해낼 수 있다.
  • 자바 속성 액세스: 파일 내 각 property를 파악하고 getter/setter를 만들어낼 수 있다.
  • 테스트 데이터 생성: 파일에 다른 포맷으로 분리된 데이터를 재조립해서 DB에 넣기 편하게 개조가능하다.
  • C에서 Object Pascal 인터페이스로: C헤더파일을 해석해서 모든 함수와 그것들이 사용하는 데이터 구조의 정의를 추출시켜주는 툴 제작 가능. 이게 빌드의 일부분이 되면 바뀔 때마다 자동적용…
  • 웹문서 생성: 각종 DB스키마, 소스파일, makefile, 등 기타 프로젝트 소스들을 읽어서 자동으로 HTML문서화 가능. 이런 것을 말하는 것 같음.

20. 코드 생성기

똑같은걸 만들 때는 템플릿을 써먹으면 된다. 잘만든 템플릿은 두고두고 써먹는다. 반복되는 작업을 통한 실수를 대폭 줄여주고 실제로 해야할 구현에만 집중할 수 있게 해준다.

코드 생성기는 그래서 중요하다. 잘 만든 코드 생성기는 프로젝트 전 기간에 그냥 거저로 써먹을 수 있다!

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

코드 생성기는 다음 두가지로 분류된다.

  • 수동적 코드 생성기

    • 결과수행을 위해 한번만 실행됨; 그 다음부터의 결과물은 독립적인 것
    • 타이핑을 줄여줌
      • 새 소스파일 생성(스켈레톤 코드)
      • 프로그래밍 언어간 일회용 변환 수행
      • 런타임이 계산하기엔 비용이 많이 드는 참조 테이블과 여타 자원 생성
  • 능동적 코드 생성기:

    • 코드 생성이 필요할 때마다 작동됨
    • DRY 원칙을 따르는 요소.
      • 어떤 형태의 스크립트나 컨트롤 파일을 읽어서 자동으로 변경을 감지하는 것을 의미

Published Feb 24, 2018

Non scholæ sed vitæ discimus.

his/him