/* 이 책의 한국어판 저작권은 인사이트에게 있습니다. 본 내용이 저작권 문제가 생길 시 즉시 삭제하겠습니다.
*/
서문
1장 실용주의 철학
2장 실용주의 접근법
3장 기본적인 도구
새내기 목수가 기본 도구를 숙달 할 뿐더러 장인이 되어서도 그 기본 도구를 베이스로 추가 도구를 사용하듯이 프로그래머 또한 기본 도구를 자유자제로 다룰 수 있어야 한다. 그것들은 손의 연장이 된다. 그리고 특별한 요구사항을 만나면서 다른 도구를 추가해라. 더 나은 방법을 고민해라.
14. 일반 텍스트의 힘프로그래머에게 도구가 다룰 재료는 '지식'이다. 지식은 설계, 구현, 테스트, 문서에 표현하는데 그 지식을 저장하는 최고의 포맷은 일반 텍스트라고 믿는다. 일반 텍스트는 우리가 사용하는 거의 모든 도구를 이용해서 지식을 조작할 수 있다. 1) 일반 텍스트란? 사람이 직접 읽고 이해할 수 있는 형태의 인쇄 가능한 문자로 이루어진 텍스트 (ex : Field19-456abd는 의미가 없다.) 비구조적인 텍스트뿐만 아니라 구조적인 XML, HTML, SGML도 일반 텍스트의 예이다. Tip.20 : 지식을 일반 텍스트로 저장하라. 2) 단점 더 많은 공간을 차지하거나 해석하고 처리하는데 더 많은 계산이 필요할 수 있다. 3) 텍스트의 힘(장점) ① 시간이 오래 지나도 이해할 수 있다. ② 호환성이 좋다. 컴퓨팅 세계의 거의 모든 도구들이 일반 텍스트를 다룰 수 있다. ③ 테스트 데이터 생성이 쉽다. 테스트 결과를 분석하기 쉽다. 4) 최소 공통분모이다. 이질적인 환경에서의 일반 텍스트는 표준이나 마찬가지이다.
15. 조개놀이(shell games) - 명령어 쉘텍스트 파일을 다루는 프로그래머에게 작업대는 쉘이다. 쉘 프롬포트에서는 모든 종류의 도구를 불러 쓸 수 있다. IDE툴이나 GUI툴에서 작업하기 어려운 것들은 쉘에선 손쉽게 처리할 수 있다. 예를 들면 아래와 같다.
Tip.21 : 명령어 쉘의 힘을 사용하라. 자주 사용하거나 반복적으로 사용하는 내용을 셸 명령어의 조합으로 스크립트화 해라 1) 셸 유틸리티와 윈도우 시스템 윈도우에서도 명령어 셸을 제공하는 유틸들이 많다. Cygwin, UWIN Perl Power Tools 등
16. 파워 에디팅가능하면 텍스트를 별로 힘들이지 않고 조작하라. 1) 하나의 에디터 능숙함 : 하나의 에디터에 대해 매우 잘 알고, 코드, 문서화, 메모, 시스템 관리 등 모든 편집 작업을 하나로 하라. Tip. 22 : 하나의 에디터를 잘 사용하라. 필요한 키 입력이 반사운동 수준이 될 정도로 마스터하라. 단, 모든 플랫폼에서 사용 가능한 에디터를 선택하라. 2) 에디터의 기능 - 설정 변경 가능 : 에디터의 모든 요소는 기호에 맞게 설정 가능해야 한다. - 확장 가능 : 새로운 언어나 텍스트 포맷의 뉘앙스를 '가르칠' 수 있어야 한다. - 프로그램 가능 : 매크로나 내장 스크립팅 프로그래밍을 할 수 있어야 한다. - 구문 강조, 자동 완성, 자동 들여 쓰기, 코드나 문서 상용어구 지원, 관련 도움말 시스템, IDE기능(컴파일/디버그 등) 3) 생산성 - 커서 이동 : 10번 누를 것인가 1번 누를 것인가 - 정렬 : 직접 보고할 것인가 명령어를 쓸 것인가 - 자동 템플릿, 자동 들여 쓰기 4) 여기에서 어디로 가나 본인의 상황에 맞춰서 고려하라 - 여러 개 에디터에서 기본적인 기능만 사용 -> 에디터 하나를 제대로 익힌다. - 하나만 쓰는데 기능을 모두 사용하진 않는다 -> 모든 기능을 배워라. 입력하는 키 개수를 줄여라 - 선호하는 에디터가 있고 가능하면 그걸 사용 -> 좀 더 많은 작업에 사용하도록 확장 5) 어떤 에디터가 있나? Emacs, XEmacs, vi, vim, elvis, Emacs Viper
17. 소스코드 관리형상관리 시스템은 모든 변화를 기억한다. Tip.23 : 언제나 소스코드 관리 시스템을 사용하라. 소스코드뿐만 아니라 각종 문서, 전화번호 목록, 메모도 관리 가능하다. 1) 소스코드 관리와 빌드 소스코드를 형상 관리 시스템 안에 둠으로써 빌드가 자동화되고 반복 가능하다. 자동화는 일관성을 보장한다. 수작업이 없고, 특정 빌드 영역으로 코드를 복사할 필요도 없다. 2) 설마, 아직도 사용하지 않는다면 꼭 소스코드 관리 시스템을 사용하라. 회사가 안 쓰면 개인적으로라도.
18. 디버깅1) 디버깅의 심리 디버깅은 단지 문제 해결이다. 문제를 고치는데 집중하라. 누구의 잘못인지 중요하지 않다. Tip. 24 : 비난 대신 문제를 해결하라. 2) 디버깅 사고방식 Tip. 25 : 디버깅을 할 때 당황하지 마라. - 한 발짝 뒤로 물러나라. 어디에 버그가 있을지, 원인은 무엇일지 생각하라. - "그럴 리가 없다."라는 생각을 버려라. 그런 일은 일어날 수 있으며, 실제로도 일어났다. - 근시를 조심하라. 증상만 고치지 마라. 문제의 근본적인 원인을 찾고 해결하라. 3) 어디에서 시작할까? - 깨끗이 컴파일된(경고문 없는) 코드로 작업하라. (.......담당 제품 경고문 엄청 뜨고 있다.ㄷㄷ) - 컴파일러 경고 레벨을 최고로 높여라 - 버그를 보고한 사용자가 실제로 시연하는 것을 지켜봐라. ( 이건 거의 힘들죠.. 고객사) (담당자가 버그를 발견한 특정 동작이 내가 생각하는 순서대로 진행됐을 거라는 생각을 말자.) ① 버그를 보고한 사용자를 인터뷰할 필요가 있다. ② 경계 조건과 실제 최종 사용자 사용 패턴 모두를 철저히 테스트해라. 4) 디버깅 전략 ① 데이터 가시화 : 데이터들의 모든 상호관계를 시각화하면 훨씬 더 깊은 통찰을 얻는다. ex) DDD 디버거, 손그림 등 ② 트레이싱 : 원시적인 기법이지만 시간 자체가 중요한 요소가 되는 시스템에 탁월하다. ex) 동시 프로세스, 실시간 시스템, 이벤트 기반 애플리케이션 등 - 트레이싱 구문 : 작은 진단용(diagnostic) 메시지를 일컫는다. ex) '여기까지 도달', 'x 값 = 2' 등 - 트레이스 메시지는 규칙적이고 일관된 형식이어야 한다. (자동으로 해석하기 위해) ③ 누군가에게 코드를 설명하라. 당연하게 넘어갔던 것을 명시적으로 이야기해야 한다. 이는 새로운 통찰을 얻을 수 있다. ④ 써드파티나 플랫폼 환경을 먼저 의심하지 말라. 당신의 애플리케이션 코드에 버그가 있을 가능성이 훨씬 더 크다. Tip. 26 : 'select(시스템 콜)'는 망가지지 않았다. 5) 놀람의 요소 - 예상 못한 '놀라운' 실패를 대면했을 때 자신이 세운 가정들이 잘못되었다는 것을 깨달아라. Tip. 27 : 가정하지 마라. 증명하라. - 놀라운 버그는 단순히 고치는 것을 넘어서, 왜 이 실패가 더 일찍 발견되지 않았을까 생각해 볼 필요가 있다. - 단위 테스트나, 다른 테스트를 확인하라. 혹은 로그 파일 분석기를 작성하라. - 버그가 몇 단계를 거쳐 전파된 불량 데이터의 결과였다면, 루틴의 매개 변수 검사를 검토하라. - 비슷한 버그가 발생할 만한 곳이 있다면 '지금' 고쳐라. - 누군가 내린 잘못된 결정이라면 전체 팀과 토론하라. 한 사람의 오해는 여러 사람이 그럴 수 있다는 얘기다. 6) 디버깅 체크리스트 - 보고된 문제가 내재하는 버그의 직접적 결과인가 아니면 단순히 증상일 뿐인가? - 버그가 정말로 컴파일러에 있나? OS에? 혹은 여러분 코드에 있나? - 이 문제를 동료에게 상세히 설명한다면 어떻게 말하겠는가? - 의심 가는 코드가 단위 테스트를 통과한다면, 테스트는 충분히 완전한 것인가? 이 데이터로 단위 테스트를 돌린다면 무슨 일이 생기는가? - 이 버그를 야기한 조건이 시스템의 다른 곳에도 존재하는가?
19. 텍스트 처리Tip. 28 : 텍스트 처리 언어를 하나 익혀라. - 셸의 awk, sed. 파이썬. Tcl, Perl, 루비 등 - 빠른 유틸리티 작성, 아이디어 프로토타이핑 - 엉뚱한 아이디어를 실험하는 등의 작업을 전통적인 언어를 사용하면 5배~10배 오래 걸린다. 즉, 텍스트 처리 언어를 통해 빠르고 쉽게 놀아라.
20. 코드 생성기Tip. 29 : 코드를 작성하는 코드를 작성하라. 1) 수동적 코드 생성기 - 몇 개의 입력에서 주어진 출력을 생성하는 매개 변수화된 템플릿이다. - 새 소스 파일 생성 : 템플릿, 소스코드 제어 지시자, 지적 재산권 문구, 주석 등을 자동으로 생성 - 프로그래밍 언어 간 일회용 변환을 수행 - 런타임에 계산하기엔 비용이 많이 드는 참조 테이블과 여타 자원을 생성 2) 능동적 코드 생성기 - DRY 원칙을 따른다. - 어떤 지식을 단 하나의 형태로만 만들어놓고 애플리케이션이 필요로 하는 온갖 형식으로 변환할 수 있다. 3) 코드 생성기가 꼭 복잡할 필요는 없다. (파서가 일을 쉽게 하게 하라) 4) 코드 생성기가 꼭 코드를 생성해야 할 필요는 없다. (HTML, XMl, 일반 텍스트 등의 생성에도 쓰일 수 있다.) |
4장 실용주의 편집증
Tip. 30 : 완벽한 소프트웨어는 만들 수 없다. 이를 장점으로 바꿔라! 21. 계약에 의한 설계1) DBC(Design By Contract) - 버트란드 마이어가 아이펠(Eiffel)이라는 언어를 만들면서 '계약에 의한 설계' 개념을 개발. - 프로그램 정확성 보장 -> 소프트웨어 모듈들의 권리와 책임을 문서화. - 선행 조건(precondition) : 루틴 호출 전에 참이어야 하는 것. 즉, 루틴의 요구사항(전달되는 데이터) - 후행 조건(postcondition) : 루틴 완료 후 프로그램 상태(후행 조건의 존재는 종료됨을 암시, 무한 반복 허용 x) - 클래스 불변식(class invariant) : 호출자의 입장에서 볼 때는 이 조건이 언제나 참이라고 클래스가 보장한다. 루틴이 종료하고 호출자로 제어권이 반환되는 때에는 불변식이 참이 되어야 한다. (불변식에 관여하는 어떤 데이터 멤버에게도 클래스가 무제한적인 쓰기 접근권을 줄 수 없다는 것을 기억하라.) Tip. 31 : 계약에 따른 설계를 하라. (위 내용들은 사실 이해가 잘 되지 않는다.) 2) DBC 구현 - DBC를 사용하는 최고의 장점은 요구사항과 보증의 문제를 전면으로 내세운다는 것. - 입력 도메인 범위가 무엇인지, 경계 조건이 무엇인지, 루틴이 뭘 전달한다고 약속하는지를 나열함으로써 '우연에 맡기는 프로그래밍'을 지양한다. - 단정문을 사용하여 DBC를 부분적으로 흉내 낼 수 있다. - 언어 지원 : DBC 자체지원(Eiffel, Sather), C나 C++(Nana), Java(iContract) 3) DBC와 일찍 멈추기 : 문제를 찾고 원인을 밝히기 위해서는, 사고가 났을 때 일찍 멈추는 것이 유리하다. 4) 불변식의 다른 용도 - 루프 불변식 : 루프의 최종 목적에 대한 진술문이지만, 일반화되어 있기 때문에 루프가 시작하기 전과 루프 진행 중 매 반복 시 적용된다. a.k.a. 축소된 계약 - 의미론적 불변식 : 이를 사용하면 일종의 '철학적 계약'인 불변의 요구사항을 표현할 수 있다. 일시적인 정책에 영향을 받으면 안 된다. 5) 동적 계약과 에이전트 : 자동화해라. 계약 역시 설계하라.
21. 죽은 프로그램은 거짓말을 하지 않는다.Tip. 32 일찍 작동을 멈추게 하라. - '그런 일은 절대 일어날 리 없어'라는 사고에 빠지지 마라. 정상 동작하는 조건에서는 실패하지 않았을 것이다. - 모든 에러는 정보를 준다. 1) 망치지 말고 멈추라 - 가능한 한 빨리 문제를 발견하게 되면, 좀 더 일찍 시스템을 멈출 수 있다는 이득이 있다. - 죽은 프로그램이 입히는 피해는 절름발이 프로그램이 끼치는 것보다 훨씬 덜한 법이다.
22. 단정적 프로그래밍Tip. 33 단정문을 사용해서 불가능한 상황을 예방하라. - 이런 일은 절대 일어날 리 없다는 생각이 든다면, 그걸 확인하는 코드를 추가해라. - 단정문(assertion)을 사용해라 - 단정문에 전달된 조건은 부작용이 있으면 안 된다. - 컴파일 중에 단정 기능이 꺼져 있을 수도 있다는 걸 기억해라. - 실행되어야만 하는 코드는 절대 assert 속에 두지 마라. - 진짜 에러 처리 대신으로 단정을 사용하지는 마라. 1) 단정 기능을 켜 두라 - 단정문에 대한 오해 : 단정은 코드에 과부하를 준다. 단정은 디버깅 도구일 뿐이다. 잘못된 가정 : 테스트가 모든 버그를 발견한다는 가정 : 낙관주의자들은 프로그램이 험한 세상에서 돌아간다는 것을 잊는다. - 모든 가능한 에러를 체크하고 놓친 것들을 잡아내기 위해 단정문을 써라. 2) 단정과 그 부작용(side effect) - 하이젠버그(Heisenbug) : 디버깅 행위가 디버깅되는 시스템의 행동을 바꿔버리는 문제
24. 언제 예외를 사용할까모든 가능한 에러를 체크하는 것이 좋으나, 코드가 꽤 지저분해져 정상 로직이 잘 안 보일 수 있다. (다행스럽게도 해당 프로그래밍 언어가 예외를 지원하면, 훨씬 더 깨끗하게 재작성할 수 있다.) 1) 무엇이 예외적인가 - 예외는 언제 사용할 것인가? - 예외가 프로그램의 정상 흐름의 일부로 사용되어서는 안 된다. - '모든 예외 처리기를 제거해도 이 코드가 여전히 실행될까' 자문해 보자. '아니오'일 경우 예외가 비예외적인 상황에서 사용되고 있는 것이다. Tip. 34 예외는 예외적인 문제에 사용하라. - 왜 이런 접근을 제안하는가? 예외가 있다는 것은 컨트롤의 이동이 즉각적이고 로컬 하지 않다는 것을 말한다. 일종의 연쇄 goto 같은 것이다. 예외를 정상적인 처리 과정의 일부로 사용할 경우 코드의 가독성 문제와 관리성 문제를 떠안는다. 캡슐화 역시 깨트리며, 루틴과 그 호출자들 사이의 결합도가 높아진다. 2) 에러 처리기는 또 다른 대안이다. - 특정 부류의 에러를 처리하기 위해 어떤 루틴을 등록하라. - Java의 RMI 기능에 대한 예외 처리 시 원격이 아닌 클래스로 원격 객체를 감싸는 우회방법도 있다.
25. 리소스 사용의 균형메모리, 트랜잭션, 쓰레드, 파일, 타이머 등을 관리한다. 일반적인 패턴은 할당, 사용, 해제이다. - 많은 개발자들이 리소스 할당과 해제를 다루는 일관된 계획을 갖고 있지 않다. Tip. 35 시작한 것을 끝내라. - 리소스를 할당하는 루틴이나 객체가 리소스를 해제하는 책임을 져야 한다는 걸 의미한다. - 중첩 할당 : 리소스를 할당한 순서의 반대로 해제하라. 코드의 여러 곳에서 동일한 리소스 집합을 할당하는 경우, 할당 순서를 언제나 같게 하라. 1) 객체와 예외 - 할당과 해제의 균형은 클래스의 생성자와 소멸자를 생각나게 한다. - 클래스는 하나의 리소스를 대표, 생성자는 그 리소스 타입의 특정 객체를 제공, 소멸자는 그것을 현 스코프에서 제거 - 만약 객체지향 언어로 프로그래밍한다면, 리소스를 클래스 안에 캡슐화하는 것이 유용. 특정 리소스 타입이 필요한 때마다 그 클래스의 객체를 생성, 소멸자가 리소스를 해제 (이 접근법은 C++과 같이 예외 때문에 리소스 해제가 방해받을 수 있는 언어로 작업을 할 때에 효과) 2) 균형과 예외 - 예외 발생 시, 이전에 할당된 모든 것이 깨끗이 청소된다고 보장이 가능한가? ① C++에서 예외와 리소스 사용의 균형 - try-catch문 사용 시 해제가 두 곳 - DRY원칙 위반 - C++ 작동 방식 이용 -> 지역 객체들은 블록에서 나갈 때 자동으로 파괴. 즉, 포인터를 객체로 바꾼다. 불가능하다면 포인터를 클래스로 감싸면 동일한 효과 - 표준 C++ 라이브러리 템플릿 클래스 auto_ptr 도 있다. ② 자바에서의 리소스 사용과 균형 - 게으른 방식의 자동 객체 삭제를 사용 - finalize 메서드 호출됨 - try블록에 finally절 사용 3) 리소스 사용의 균형을 잡을 수 없는 경우 - 집합적인 자료구조 안의 자료에 대해 책임을 지는 게 누구인지 정해 놓아야 한다. - 최상위 구조의 할당을 해제할 경우 어떤 일이 일어나는가? ① 최상위 구조 자신이 자기 안에 들어있는 하위 구조들의 할당을 해제할 책임이 있다. 하위 구조들은 또다시 재귀적으로 자기 안에 들어있는 자료들을 해제할 책임이 있다. ② 최상위 구조에서 그냥 할당이 해제. 그 안에서 참조하던(다른 곳에서 참조하지 않는 구조들은 모두 연결이 끊어져 고아가 된다. ③ 최상위 구조는 하나라도 하위 구조를 가지고 있을 경우 자기의 할당 해제를 거부 - 선택은 각 데이터 구조의 상황에 따라 달라진다. - C와 같은 절차형 언어에서는 3가지 모두 어려울 것이다. 방법은 중요한 구조마다 표준적인 할당과 해제 기능을 제공하는 모듈을 하나씩 작성. - 리소스 사용의 기록을 남기는 것이 까다로워진다면 동적으로 할당된 객체에 참조 숫자 세기 방식(reference counting)을 구현해 자신만의 자동 쓰레기 수집(garbage collection)기능을 작성 4) 균형을 점검하기 - 정말로 리소스가 적절하게 해제되었는지 실제로 점검하는 코드를 늘 작성하라. - 리소스 종류마다 래퍼를 만들고 그 래퍼들이 모든 할당과 해제의 기록을 유지하는 것 - 메모리 점검 도구를 사용하라. |
5장 구부러지거나 부러지거나(BEND, OR BREAK)
26. 결합도 줄이기(decoupling)와 디미터 법칙: 서로 다른 개념들을 분리하여 결합도를 줄이는 방법 - shy코드 : 자신을 남에게 속속들이 드러내지 말고, 너무 많은 사람과 상호작용하지 말라. 1) 결합도 줄이기 - 상호인지하는 것이 나쁘다는 건 아니다. 그들이 어떻게 상호작용을 하는지에 대해 주의를 기울여야 한다. - 리모델링을 예를 들면, 이를 도맡아 진행할 '주 계약자'와 계약을 하면, 그는 각각의 역할을 맡을 하도급자와 다시 계약하는 것이 일반적이다. 따라서 주계약자가 하도급자들을 관리하기 때문에 이와 관련된 신경을 쓸 필요가 없다. - 시스템 어딘가의 무관한 변화가 코드에 영향을 미칠 수 있다. 유지보수가 어려워진다. 2) 디미터 함수 법칙 - 프로그램에서 모듈 간 결합도를 최소화하려 시도한다. 이 법칙은 한 객체가 제공하는 메서드에 접근하기 위해 또 다른 객체들을 통하는 것을 허용하지 않는다. Tip. 36 모듈 간의 결합도를 최소화하라. - 응답집합(response set)이 큰 클래스는 작은 클래스보다 에러를 발생시키기 쉽다. 응답집합은 클래스의 메서드가 직접 호출하는 함수의 수를 의미 - 디미터 법칙을 따르면 함수를 호출하는 클래스의 응답집합 크기를 줄일 수 있다. - 단, 성능 저하와 메모리 과부하 문제를 야기할 수 있다. - 물리적 결합도 : 시스템을 구성하는 파일, 디렉터리, 라이브러리 간의 관계에 대한 문제도 고려하라. 27. 메타 프로그래밍: 세부사항을 완전히 코드 밖으로 옮기는 방법 1) 동적 설정 - 모든 것을 설정가능하게 만들어라. (배경 색, 알고리즘의 선택, 데이터베이스 제품, 스타일 등) - 통합하거나 엔지니어링하지 말고 설정 옵션으로 구현하라. (통합? 엔지니어링?) Tip. 37 통합하지 말고 설정하라. - 책에서의 메타데이터란? : 애플리케이션을 기술하는 모든 데이터(애플리케이션이 어떻게 실행되어야하고, 어떤 자원을 이용해야 하는지 등) -> 런타임에 접근, 사용된다. 2) 메타데이터 주도 어플리케이션 - 어떻게가 아닌 무엇을 해야하는지 명시함으로써 선언적(declarative)으로 생각하라. -> 더 동적이고 적용 가능한 프로그램을 만들어라 Tip. 38 코드는 추상적으로 메타데이터에는 세부 내용을. - 메타 데이터 사용의 이점 5가지 ① 설계의 결합도를 줄여 좀 더 유연하고 적응성 있는 프로그램을 만들 수 있다. ② 세부사항을 코드 밖으로 몰아냄으로써 보다 강하고 추상적인 디자인을 만들 수 있다. ③ 애플리케이션을 커스터마이징하기 위해 다시 컴파일할 필요가 없다. ④ 메타데이터는 범용 프로그래밍 언어보다 문제 도메인에 가까운 방식으로 표현될 수 있다. ⑤ 동일한 애플리케이션 엔진과 상이한 메타데이터를 이용해 여러 다른 프로젝트를 진행할 수 있게 된다. - 세부 사항을 변화하기 쉽게 납겨 두라. (가역성) - 비지니스로직 : 메타데이터 사용의 심화 ① 비지니스 정책이나 룰에 적용하라 ② 반복되는, 수정되는 것들에 대해 일반화할 기회를 놓치지 마라. ③ 복잡할수록 복잡한 비지니스 룰에 따라 액션을 시작하고 멈추어야 한다. ④ 덜 복잡한 로직은 소형언어로 표현할 수 있다. - 언제 설정할 것인가? 설정정보를 읽을 것인가? 좀 더 유연한 접근 방식은 프로그램 실행 중에도 설정 정보를 리로딩 할 수 있게 만들어라. 단, 프로그램 성격에 따라 데몬이냐 일회성이냐에 따라 반영하라 - 협동적 설정 ① 사용자와 개발자가 아닌 어플리캐이션이 서로를 설정하게 하라. ② 소프트웨어가 스스로 환경에 적응하도록 만들어라. ③ 그때그때 맞게 설정되는 시스템(프로그램)을 만들어라. (ex : 운영체제, 웹브라우져) 3) 도도 코드를 작성하지 말라. - 환경에 적응하지 못하는 종은 멸종한다.
28. 시간적 결합(temporal coupling): 시간상의 결합을 피하는 방법 - 소프트웨어의 설계 요소 자체로서의 시간의 역할 : 동시성과 순서 - 직선적 사고방식은 시간적 결합을 만든다 - 동시성을 허용하고 시간이나 순서에 따른 의존성의 결합을 끊어라. 1) 작업흐름 - 사용자들의 작업흐름을 모델화하고 분석하라. ex) UML 활동 다이어그램(UML activity diagram) TIP. 39 작업흐름 분석을 통해 동시성을 개선하라. 2) 아키텍처 - 예제 : db작업은 오래걸린다. - 잘짜여진 아키택쳐로 시간적 결합을 줄인다. TIP. 40 서비스를 사용해서 설계하라. 3) 동시성을 고려한 설계 - 쓰레드를 쓰는 프로그래밍은 몇가지 설계상의 제약을 받는다. - 여러 일이 '동시에' 일어날 수 있기 때문에, 의존성이 보이기 시작한다. ① 모든 전역 변수나 정적 변수들을 동시 접근으로부터 보호 ② 호출될 가능성이 있는 모든 시간에 언제나 객체는 유효한 상태에 있어야 한다. - 더 깔끔한 인터페이스 설계가 가능 - ex : c의 strtok() 와 java의 StringTokenizer()의 차이 TIP. 41 언제나 동시성을 고려해 설계하라. 4) 배치 - 동시성 요소가 포함된 아키텍쳐를 설계한 다음엔 애플리케이션을 어떻게 배치할지 유연한 대응이 가능 29. 단지 뷰일 뿐이야: 뷰와 모델의 결합도를 줄이는 방법 - 모듈(클래스)에 대한 좋은 정의 : 잘 정의된 단 하나의 책임만 가지는 것 - 여러 다른 객체들의 상태 변화(또는 갱신된 데이터 값)를 어떻게 동기화 해야 할까? - 이벤트 : 뭔가 흥미로운 일이 방금 일어났다 1) 출판/구독 - 객체가 자기가 필요한 이벤트들만 구독해서 받아보고 필요하지 않은 이벤트들은 받아오지 않도록 해야 한다. - '출판자'가 보내는 이벤트들 가운데 흥미로운 것이 있다면, 출판자에게 등록 - '출판자'는 자기에게 흥미를 보인 '구독자'들의 목록을 유지 - 출판자가 이벤트를 발생시키면, 출판자는 차례대로 '구독자'를 호출해서 이벤트가 일어났다고 알려줌 - 비슷하지만 변형된 형태들 : P2P기반, 중앙 객체를 활용한 '소프트웨어 버스' 운영, 또는 모든 수신자에게 전송 2) 모델-뷰-컨트롤러 - 이디엄(idiom) : 모델을 표시하는 뷰 그리고 뷰를 관리하는 컨트롤러에서 모델을 분리해 내는 것. TIP. 42 모델에서 뷰를 분리하라. 3) GUI를 넘어서 - MVC는 보통 GUI 개발이라는 맥락에서 가르치지만 일반적으로도 쓸 수 있는 프로그래밍 기법 - 모델 : 대상 객체를 나타내는 추상 데이터 모델. 모델은 어떤 뷰나 컨트롤러에 대해서도 직접적인 지식을 지니지 않는다. - 뷰 : 모델을 해석하는 방법. 뷰는 모델의 변화 그리고 컨트롤러가 보내는 논리적 사건을 구독한다. - 컨트롤러 : 뷰를 제어하고 모델에 새로운 데이터를 제공하는 방법. 모델과 뷰 둘 모두에 이벤트를 보낸다. - 모델-뷰 네트워크 설계 기법 4) (그렇게 세월이 흘러도) 여전히 결합 중 - 청취자와 이벤트 생성자(구독자와 출판자)는 아직도 서로에 대한 약간의 지식이 남아있다.
30. 칠판(blackboard): 데이터를 동기적, 비동기적으로 교환함으로써 모듈 간 결합도를 획기적으로 줄이는 기술 - 칠판 접근방법의 중요한 몇 가지 특징 ① 어떤 형사도 다른 형사들의 존재를 알 필요가 없다. 형사들은 칠판을 보며 새로운 정보를 얻으며 자기가 발견한 것을 추가해 쓴다. ② 형사들은 저마다 서로 다른 종류의 훈련을 받았거나, 다른 수준의 교육과 경험을 지녔을 수 있으며, 아예 같은 관할구역에 속하지 않을 수도 있다. 사건을 해결하고 싶은 마음은 모두에게 있지만, 공통점은 그뿐이다. ③ 수사 과정에서 여러 형사들이 들어오거나 나갈 수 있고, 임무 교대 시간도 제각기 다를 수 있다. ④ 무엇을 칠판에 올려도 되는지에 대한 제한이 없다. 사진, 증언, 물리적 증거 등등 어떤 것이라도 상관없다. - 칠판 시스템을 이용하면, 지식의 소비자와 생산자들이 익명으로 그리고 비동기적으로 데이터를 주고받는 공간이 생긴다. 그 덕분에 객체들 사이의 결합을 완전히 끊을 수 있다.(코드의 양도 줄어든다.) 1) 칠판 구현 - 컴퓨터 기반의 칠판 시스템은 원래 음성 인식, 지식 기반 추론 시스템 등등 해결해야 할 문제의 규모가 크고 복잡한 인공 지능 애플리케이션에서 사용할 목적으로 발명되었다. - 최근에 등장한 분산 칠판 유형의 시스템(JavaSpaces, T Spaces)들은 키/값 쌍의 모델에 기반을 두고 있다. - 이런 시스템을 이용하면, 객체의 데이터뿐만 아니라 자바 객체 전체를 칠판에 저장한 후 필드의 부분일치 또는 유형별 검색을 통해 다시 가져올 수 있다. - 두 시스템 모두 데이터 무결성을 보장하기 위해 원자적 동작과 분산 트랜잭션을 지원하는 등 데이터베이스 제품처럼 만들어져 있다. - 활용 : 단지 데이터가 아니라 객체의 흐름에 기반한 알고리즘을 설계하는 데 칠판을 이용할 수도 있다. - 장점 : 칠판에 대한 일관성 있는 인터페이스 하나만 있으면 됨 2) 애플리캐이션 예제 - 칠판 정리하기 : 칠판이 난잡해져서 그 위에서 자료를 찾아보기 힘들때에는 칠판을 여러 구획으로 나누고 정리하라. - 끔찍하게 복잡한 현실 문제를 작업흐름 시스템으로 처리할 수도 있겠으나 복잡할 뿐더러 노력도 많이 들어간다. Tip. 43 칠판을 사용해 작업흐름을 조율하라.
|
6장 코딩하는 동안 해야 할 일들
7장 프로젝트 전에(BEFORE THE PROJECT)
36. 요구사항의 구렁텅이: 사용자의 이야기를 잘 듣는 것만으로는 충분치 않다. Tip. 51 요구사항을 수집하지 말고 채굴하라. 1) 요구사항 채굴하기 - 요구사항이란? 어떤 것이 성취되어야 한다는 진술 - 사용자들이 어떤 작업을 현재 어떻게 하느냐는 것을 알아내느 것보다, 왜 그걸 하는지 그 내재적 이유를 알아내는 것이 더 중요하다. 그들의 실질적 비즈니스 문제를 해결해야 하는 것이다. - 요구사항 이면의 이유들을 문서화해 놓아라. Tip. 52 사용자처럼 생각하기 위해 사용자와 함께 일하라. 2) 요구사항 문서화 - 요구사항 문서에 대한 독자층은 정말로 폭이 넓다. - 유스케이스를 보는 하나의 관점은 목적 지향성을 강조하는 것 - 작업흐름은 UML활동 다이어그램으로 갈무리할 수 있다. 3) 지나치게 자세한 명세 - 좋은 요구사항 문서는 추상적이다. 4) 더 멀리 보기 - 예제 : Y2K문제 Tip. 53 구체적인 것보다 추상적인 것이 더 오래간다. 5) 딱 하나만 더... - 프로젝트 범위의 증가를 막아라.(요구사항의 추가) - 요구사항을 적극적으로 추적하라. - 범위의 변화 : 누가 기능을 요청, 누가 승인, 승인된 요구사항은 몇개인가? - 요구사항 증가 관리의 핵심 : 언제 어떻게 늘어났는지에 대해 정확하고 완전한 그림을 갖고 있어라. - '기능 하나만 더'가 실은 이번 달에 추가된 15번째 새 기능이었다는 사실을 분명히 알 수 있을 것 6) 용어사전 유지하기 Tip. 54 프로젝트 용어사전을 사용하라. - 프로젝트 용어사전은 프로젝트에 사용되는 모든 용어와 어휘를 모아 놓은 단일한 장소여야 한다. - 모든 사람이 일관성을 가져야 하며, 접근하기 쉬워야 한다. ex) 웹 기반 문서를 사용 7) 말을 끄집어내라 - 요구사항을 하이퍼텍스트 문서로 표현함으로써, 다양한 청중의 필요를 더 잘 충족시킬 수 있다. - 아무도 읽지 않는 종이에 잉크를 칠하지 말고 웹 기반 배포를 이용하자. - 웹에 올려져 있다면, 제 아무리 프로그래머들이라도 읽는다.
37. 불가능한 퍼즐 풀기: 상식적인 지혜와 제약조건 관리(Constraint Management) - 실제로도 정말 그렇게 어려울까?(엔지니어링 문제거나, 작성하기 어려운 코드거나, 불가능해 보이는 것 등) - 불가능한 퍼즐을 푸는 방법은 (상상이 아닌) 실제의 제약 조건을 알아내고, 그 속에서 해법을 찾는 것 - 단순히 지례 짐작한 제약 조건들은 실질적 제약 조건이 아닐 수도 있다. 1) 자유의 정도 - '생각의 틀을 벗어나라' - 틀을 벗어나고 않고의 문제가 아닌 틀을 찾는 것, 제약인 것들을 찾는 일 Tip. 55 생각의 틀을 벗어나지 말고, 틀을 찾아라. - 퍼즐을 해결하는 열쇠 : 제약을 인식, 주어진 자유의 정도가 얼마나 되는지 깨닫는 것 - 모든 선입견을 의심해보고 그것이 명백한 진짜 제약인지 가늠해 봐야 한다. - 제약들을 범주별로 나누고 우선순위를 매겨라. 2) 분명히 더 쉬운 방법이 있을 거야! - 뭔가 잘못됬다는 생각이 든다면 아래 질문들에 스스로 대답해 보아라. ① 더 쉬운 방법이 존재하는가? ② 진짜 문제를 풀려고 노력하고 있나. 그렇지 않다면 중요하지 않은 기술적 문제에 정신이 팔려 있는 것인가? ③ 왜 이것이 문제인가? ④ 문제를 이렇게 풀기 어렵게 만드는 것이 무엇인가? ⑤ 반드시 이 방법으로 해야 하는가? ⑥ 반드시 해야 하는 일이긴 한가?
38. 준비가 되어야만: 머릿속에서 들리는 경고의 목소리를 언제 경청하는 것이 좋은지 조언 Tip. 56 준비가 되었을 때 시작하라. - 경험과 지혜를 믿고, 작업을 앞두고 마음 속에 어떤 의심이 계속 거슬리거나 왠지 꺼림칙하다면 그 느낌을 따르라. 1) 좋은 판단이냐 늑장 부림이냐? - 모든 사람이 백지를 두려워한다. (많은 사람들이 일을 시작하는 최초 행위를 미루기 좋아한다.) - 프로토타이핑 기법을 시작하라. ① 시간을 낭비하고 있다는 느낌이 들기 시작한다면 프로토타이핑을 그만 두고 진짜 개발에 뛰어들어라. ② 기본적인 몇몇 전제가 틀렸다는 것을 깨달을 수도 있다. 어떻게 해야 할지도 보인다면 정식 프로젝트를 시작하라.
39. 명세의 함정: 명세의 장점 - 프로그램 명세화란? 어떤 요구사항을 가져와 프로그래머가 자기 기술로 작업을 시작할 수 있는 시점까지 정리하는 과정 - 어떤 명세서가 어떤 시스템이나 그 시스템에 대한 요구사항의 모든 세부사항과 미묘한 차이점들을 모조리 잡아낼 수는 없다. - 언어 자체의 표현 능력에도 문제가 있다. (신발끈을 리본 모양으로 매는 방법을 설명하기) Tip. 57 어떤 일들을 설명하기보다 실제로 하는 것이 쉽다. - 구속복(straightjacket) 효과 : 코딩하는 사람에게 해석의 여지를 전혀 남기지 않는 설계는 프로그래밍 노력으로부터 모든 수완과 기술을 빼앗아버린다. - 명세와 구현은 단지 동일한 과정, 즉 요구사항을 포착해서 명문화하는 노력의 다른 측면일 뿐이다.
40. 동그라미와 화살표: 형식적 개발 프로세스와 방법론의 몇 가지 위험 Tip. 58 형식적 방법의 노예가 되지 마라. - 어떤 기법이든 개발 실천방법과 개발 능력의 맥락 안에 그것을 넣어보지도 않고 맹목적으로 받아들이지 말 것. - 형식적 방법의 심각한 단점들 ① 최종 사용자는 다이어그램 전혀 이해하지 못한다. 결국 설계자가 해석해 줘야한다. ② 전문화를 권장하는 것처럼 보인다. '우리 대 저들'식의 사고방식이 생기기도 한다. (설계자 vs 개발자) ③ 런타임에도 애플리케이션의 성격을 변화시키는 일이 가능하도록 메타데이터를 이용해서 적응가능성이 높고 동적인 시스템을 선호하는데 형식적인 방법은 이를 잘 표현하지 못했다. 1) 방법론이 제값을 하는가? - 새로운 도구와 방법론을 채택하는 데 들어가는 비용을 절대 과소평가하지 말라. 2) 우리가 형식적 방법을 사용해야 할까? - 물론이다. 단지 도구 상자 속의 또 다른 도구일 뿐이라는 사실을 늘 기억해라. - 방법론의 노예가 되지 말라. - 방법론을 비판적인 시각으로 바라본 다음, 각각의 방법론에서 가장 좋은 것만 뽑아 매달 점점 좋아지는 자신의 작업 실천방법의 집합 속에 녹여 넣어라. -> 자신의 공정을 개선하고 다듬기 위해 끊임없이 노력해라. Tip. 59 비싼 도구가 더 좋은 설계를 낳지는 않는다. |
8장 실용주의 프로젝트(PRAGMATIC PROJECTS)
41. 실용주의 팀: 실용주의 철학을 살리면서 프로젝트의 각 부분을 위임하기 1) 깨진 창문을 없애라 - 팀 전체가 깨진 창문(사소한 결점)을 용납하지 않아야 한다. - 팀은 상품의 품질에 대해 책임을 져야만 한다. - 품질은 팀원 '전체'가 개인적으로 기여할 때만 보장 된다. 2) 삶은 개구리 - 모든 사람이 적극적으로 환경 변화를 감시해야 한다. - 범위의 확장, 시간 척도의 감소, 추가 기능, 새로운 환경 등 애초 합의사항에 있지 않았던 것들을 항상 점검 - 변화를 거부할 필요는 없다. 단지 그런 일이 벌어지고 있다는 것을 알면 된다. 3) 소통하라 - 팀은 나머지 세상과 명확히 의사소통해야 할 필요가 있는 존재이다. - 프로젝트 또는 팀에 이름을 지어라. 그리고 언제 어디서든 사용해라. 팀은 정체성 확립의 기반을 얻고 세상은 기억할 것이다. 4) 반복하지 마라 - 팀원 한명을 프로젝트 사서로 임명하여 문서와 코드 저장고를 관리하는 책무를 맡겨라. - 프로젝트가 클 경우 작업의 다양한 기능적 측면의 핵심 사안별로 사람을 임명하라. 5) 직교성 - 프로젝트의 여러 활동(분석, 설계, 코딩, 테스팅)이 독립적으로 이루어진다는 생각은 잘못이다. 불가능 하다. Tip. 60 팀을 기능 중심으로 조직하라. - 팀을 기능적으로 분리하고 각 팀은 최종 시스템의 특정한 기능 측면에 대해 책임지도록 한다. - 어떤 변화가 생기더라도 전체가 영향받는 일이 없게 된다. - 단, 이 기법은 책임감 있는 개발자들과 강력한 프로젝트 관리가 있을 경우에만 효과가 있다. - 기술 담당 수석과 관리 담당 수석을 두어라. 6) 자동화 - 일관성과 정확성을 보장하는 훌륭한 방법은, 팀이 하는 모든 일을 자동화하는 것 - 자동화는 모든 프로젝트팀에게 필요불가결한 요소다. 7) 덧칠을 언제 멈출지 알아라 - 팀은 개인들로 이루어진다는 사실을 명심하라. 그들을 지원하기에, 프로젝트가 요구사항에 맞게 이루어지기에 딱 좋을 만큼의 구조를 제공해라. 계속 덧칠하려는 욕구를 참아라. 42. 유비쿼터스 자동화: 자동화가 왜 가장 중요한 요소인가 - 여러 과정을 직접해서 동작하는 것과 자동으로 동작하는것의 차이는 실수가 없다이다. - 프로젝트에서 일관성과 반복가능성을 확보하기 위해서라도 자동화하라. 1) 전자동 Tip. 61 수작업 절차를 사용하지 말라. - 셸 스크립트나 배치 파일을 사용하라. 소스코드 관리도 가능하기 때문에 절차의 변화도 조사 가능하다. 2) 프로젝트 컴파일 - IDE 말고 makefile를 사용해라. 더 높은 수준의 자동화가 가능하다. 3) 코드 생성 - makefile을 사용해서 소스를 생성하라. - 소스코드, 헤더파일, 문서까지도 다른 형태의 자료에서 자동으로 생성해 낼 수 있다. 4) 빌드 자동화 - 자동으로 최종 선적품을 생산하고 전체 빌드가 모든 테스트를 거치도록 하라. - 매일 밤, 코드변화시 빌드 실행 - 최종빌드는 매일 밤 빌드와는 다른 추가 작업이 필요할 수 있다. 5) 자동화된 관리 - 웹사이트 생성은 좋은 생각이나, 웹 콘텐트(content)도 자동으로 생성되어 웹에 올라가야한다. - 코드에서 추출된 문서나 요구사항 분석, 설계 문서, 그림, 차트, 그래프 등 정기적으로 웹에 올라가야한다. - 야밤의 빌드에서 생성된 정보는 모두 웹에서 접근 가능해야한다. 빌드 자체 결과, 회귀테스트, 성능 통계 등 - 코드 검토의 일정잡기와 승인을 자동화하라. (각 파일들에 특별한 표식) - 웹을 이용해 검토자들의 승인 혹은 불승인을 선택/등록할 수 있게 할 수있다. 6) 중 머리 - 중이 제 머리 못 깍는다.( 원문 : 구두장이 자식이 신발이 없다.) - 반복적이고 지루한 작업은 컴퓨터에게 시키자.
43. 가차 없는 테스트: 프로젝트 차원의 테스트 철학과 도구들 Tip. 62 일찍 테스트하고, 자주 테스트하고, 자동으로 테스트하라. Tip. 63 모든 테스트가 통과하기 전엔 코딩이 다 된 게 아니다. 1) 무엇을 테스트할지 - 단위테스트, 통합테스트, 유효성 평가와 검증, 자원 고갈/에러/복구 테스트, 성능테스트, 사용편의성 테스트 2) 어떻게 테스트할까 - 회귀 테스트, 테스트 데이터, GUI 시스템 구동, 테스트를 테스트하기, 철저히 테스트하기 Tip. 64 파괴자를 써서 테스트를 테스트하라. Tip. 65 코드 커버리지보다 상태 커버리지를 테스트하라. 3) 언제 테스트할까 - 테스트는 대부분 자동화 되어야하며, 테스트 결과의 해석도 자동화되어야 한다. 4) 그물 조이기 - 현존하는 테스트의 그물을 빠져 나가는 버그가 있으면, 다음번에는 그걸 잡아낼 수 있도록 새 테스트를 추가해라. Tip. 66 버그는 한번만 잡아라.
44. 결국은 모두 글쓰기: 문서화라는 허드렛일을 덜 힘들고 더욱 생산적으로 만드는 방법 Tip. 67 한국어(원문은 영어)도 하나의 프로그래밍 언어인 것처럼 다루라. Tip. 68 문서(document)가 애초부터 전체의 일부가 되게 하고, 나중에 집어넣으려고 하지 말라. 1) 코드 내의 주석 - 2) 실행 가능한 문서 3) 테크니컬 라이터 4) 찍기나 짜기 5) 마크업 언어
45. 위대한 유산: 모든 프로젝트의 후원자를 기쁘게 하는 비결 1) 기대를 상호 소통하기 2) 한 계단 더
46. 오만과 편견: 자신의 작업에 자부심을 가져라. feat.낙관 |
'책을 읽.쓰. > IT' 카테고리의 다른 글
[#1][리뷰]<실용주의 프로그래머> 앤드류 헌트, 데이비드 토머스 (0) | 2019.06.09 |
---|---|
(6/3 ~ 6/9) 1주차 후기 (0) | 2019.06.09 |
[제 0 장. 운영체제 이야기] 운영체제(OS), 테스크(task) (0) | 2018.11.08 |
<리눅스 커널 내부구조> 백승재, 최종무 (0) | 2018.11.07 |
들어가며... (0) | 2018.11.05 |