"프로그래밍의 정석" 서평

프로그래밍의 정석 표지

서평 목적

이 글은 성장하는 프로그래머가 되고 싶은 사람들에게 추천하기 위해 쓴다. 그리고 높임말로 썼다가 내용이 너무 딱딱해지고 지루해져서 쓰기 쉬운 반말투로 다시 변경했다. 말투가 거슬린다면 이해 부탁 드린다.

책 간략 소개

"프로그래밍의 정석" [1]책은 부제가 프로그래머가 반드시 알아야 할 101가지 원리 원칙으로 좋은 프로그래머가 되기 위한 보편적인 지식을 모아서 가이드라인을 제시하는 책이다. 2016년에 발행되었으며 2017년에 번역본이 발행되었다. 저자는 우에다 이사오이고 이며 800권 이상의 기술서를 독파한 독서광이라고 한다. 번역자는 류두진이다.

책을 읽게 된 배경

이 책은 내가 참여하는 "개발자 한 달에 책 한 권 읽기"[2] 페북 독서모임에서 9월에 읽을 책으로 선정하여 읽게 되었다. 간단하게 모임 설명을 하면 개발자들의 성장을 돕기 위해 기술서적을 읽고 매월 말에 모여 읽은 내용을 토의하는 모임이다. 이 모임의 장점은 트렌디한 최신 기술 위주보다 기초를 다지기 위한 기본서를 위주로 책을 선정한다는 점이다.

책에 대한 첫 느낌

"정석"이라는 단어는 중. 고등학교 시절 수학 정석이 주던 부담감이 아직도 남아 있어서 인지 책 제목에서는 거리를 두고 싶어 진다. 왠지 빡빡하게 내용이 채워져 있고 유제와 연습문제들이 들어있을 것만 같은 느낌이다. 하지만, 도입부를 읽고 나니 저자의 말에 공감을 느끼게 되고 설명 방식, 용어 정리 등의 공감대 형성 노력에 경계심이 없어졌다. 저자의 노력에 공감하게 된 후 이후 내용을 읽을 때는 마치 좋은 선배가 설명해 주는 느낌을 받았다.

특히 이 책은 각각의 정석을 그것은 무엇이고(=what, 무슨 뜻), 그것은 왜 그렇고 왜 필요하며(=why, 어째서), 그렇다면 어떻게 해야 하는지(=how, 어떻게)와 같이 구성으로 표시하였다. 이런 논리적 구성이 내용 이해를 더욱 도와준다. 이 책을 읽는 다면 저자의 집필 목적과 설명 구성에 대한 도입부를 읽어보라고 꼭 추천하고 싶다. 내가 읽으면서 공감하게 된 내용을 일부 발췌한다.

프로그래밍 언어 문법을 익혀 코드는 작성할 수 있는데, 좋은 코드라고 보기에 어딘가 조금 아쉽다고 느껴본 경험이 있을 것이다.

...중략...

이런 수준에서 실력을 한 단계 올리기란 그리 쉽지만은 않다.

마침 좋은 시기에 좋은 시기에 좋은 업무, 훌륭한 선배, 잘 작성된 코드를 접할 수만 있다면야 성장할 수 있겠지만 이는 운에 좌우되므로 확률이 높지 않다.

...중략...

프로그래머로 성장해야만 하고 성장하고 싶다는 생각은 굴뚝같지만, 방법이나 가이드라인을 알지 못해 헤매고 있는 사람이 많은 것 같다. 나부터가 그럼 사람 중의 한 명이었다. 이 책은 바로 그런 고민을 해결해주고자 집필했다.

본문 요약

1. 전제: 프로그래밍 불변의 사실

전제 편에서는 거의 진리처럼 변하지 않는 사실을 소개한다. 소개된 사실들은 "프로그래밍에 은제 탄환은 없다", "코드는 설계서다", "코드는 반드시 변경된다"이다. 이 중 나에게 와닿은 "프로그래밍에 은제 탄환은 없다"를 소개한다. 나는 한 번만 고생하고 나머지는 편안히 살고 싶다고 생각할 때가 종종 있다. 프로그래밍할 때도 마찬가지이며 객체지향만 잘 안다면 디자인 패턴만 잘 공부한다면 나에게 닥친 문제를 잘 해결해 주지 않을까 라고 말이다. 저자는 그런 것은 없다고 제일 첫 번째에 이 사실을 두면서 얘기하고 있다.

프로그래밍에 특효약은 없다. 소프트웨어가 본질적으로 난해성을 가지고 있어 하나로 간단히 해결할 수 없다고 한다. 난해성을 더 살펴보면 복잡성, 동조성(호환성), 가변성(변경 가능성), 비가시성이라는 4가지 성질이 있다. 복잡성은 소프트웨어 구성요소의 종속관계가 규모가 커질수록 비선형적으로 증가하여 관계가 복잡해는 성질을 의미한다. 동조성은 소프트웨어가 단독으로 존재하지 않고 하드웨어나 네트워크, 다른 소프트웨어, 인간의 행동 등 실세계의 다양한 요소와 지속적으로 관계 맺음을 말하며 실세계는 소프트웨어에 비할 수 없이 복잡 하기에 소프트웨어도 이에 맞춰 복잡해진다라고 한다. 가변성은 한번 완성되더라도 사용자는 다른 요구사항을 떠올리게 되며 완성된 소프트웨어가 세상을 바꾸고 사람의 인식을 재차 바꾸면서 다시 새로운 요구사항을 생기게 하여 결국 소프트웨어를 다시 변경하게 함을 의미한다. 마지막 비가시성은 소프트웨어 자체나 프로세스, 의사결정의 과정 등이 눈에 보이지 않는 개념이라 볼 수 없으며 단순화하여 도면으로 만들 수 있지만 추상화된 내용이라 모든 정보를 표현할 수 없다는 것이다. 결국 눈에 보이지 않기 때문에 난이도가 높아진다.

이러한 것을 보면 본질은 제거할 수 없는 성질이고 본질이 난해하니 결과물도 역시 난해해질 수밖에 없다는 것이다. 은탄환처럼 한 방에 해결할 것 같은 특효약을 찾거나 기다리지 말고 착실하고 과학적인 접근법에 근거하여 개선해야 한다. "코딩을 지탱하는 기술"에서도 보여 주 듯이 소프트웨어 개발은 복잡함을 줄이기 위한 역사라고 해도 과언이 아니다. 저자의 조언대로 역사를 배우고 다양한 기법이나 사고방식을 익혀서 착실하게 복잡함을 줄여 나가도록 하자.

2. 원칙: 프로그래밍의 가이드라인

이 장에서는 프로그래밍의 기본 규칙이라고 말할 수 있는 원칙들을 제시한다. 원칙이 철칙이 아니기에 그대로 적용하지 않고 상황에 따라 조정하기를 바란다고 저자는 말한다. 이 원칙들은 책상에 붙여 놓고 항상 볼 만큼 간략하면서도 중요하다고 생각되어 아래에 책의 설명방식대로 '무슨뜻’, ’어째서’, '어떻게’와 함께 간략하게 정리하였다.

"KISS" (간단하게 해라, 어리석은 녀석아 / 간결하고 단순하게 해라)

무슨뜻?:

...코드는 단순하게 유지한다

어째서?:

...코드는 무질서로 향한다

어떻게?:

...코드에 불필요한 것을 하지 않는다

"DRY" (중복하지 마라)

무슨뜻?:

...코드 복사는 금물

어째서?:

...코드를 개선할 수 없다

어떻게?:

...코드를 추상화한다

"YAGNI" (그것은 분명 필요 없어진다)

무슨뜻?:

...코드는 필요할 때 최소한으로

어째서?:

...코드의 예측은 빗나간다

어떻게?:

...코드는 지금 필요한 것만

"PIE" (의도를 표현해서 프로그래밍하라)

무슨뜻?:

...코드의 의도를 전한다

어째서?:

...코드가 유일한 실마리

어떻게?:

...코드는 읽기 쉬운 것이 최우선

"SLAP" (추상화 수준의 통일)

무슨뜻?:

...코드 수준을 맞춘다

어째서?:

...코드에 요약성과 열람성을 가져다준다

어떻게?:

...함수를 구조화한다

"OCP" (개방-폐쇄의 원칙)

무슨뜻?:

...코드의 변경을 파급시키지 않는다

어째서?:

...코드의 변경에 유연하게 대응한다

어떻게?:

...코드에 인터페이스를 사용한다

"명명(이름 짓기)이 중요하다"

무슨뜻?:

...코드에서 명명은 가장 중요한 과제

어째서?:

...코드를 읽는 사람에 대한 사용자 인터페이스

어떻게?:

...코드는 우선 이름을 정한다

원칙을 적용하려면 단순한 마음가짐만으로 안 된다. 이 원칙을 나에게 적용하기 위해 이제부터 고민, 학습, 연습 순으로 따르려고 한다. 먼저 내가 하지 못한 일이나 해야 할 일이 무엇인지 종이에 써서 사고의 늪에 빠지지 않게 할 것이다. 종이에 쓰고 나면 객관화할 수 있어 고민할 거리가 어느 정도 명확히 정리될 것이다. 이러다가 해결책이 나오면 좋고 그렇지 않다면 많은 사람들이 이미 고민하여 만든 해결책을 공부하고 이해해 보는 것이다. 마지막으로 코드를 작성하면서 이를 적용하는 연습을 통해 내 것으로 하는 것이다.

해결책 힌트로는 각주의 참고 서적이 좋은 방법이 될 것 같다. 내가 본 책으로 "읽기 쉬운 코드가 좋은 코드다"가 얇고 내용도 잘 번역되어 첫 도전에 좋다. 그다음은 "Clean Code"이다.

3. 사상: 프로그래밍의 이데올로기

성공한 소프트웨어에는 보이지 않는 곳에서 성공을 뒷받침하는 문화, 철학, 가치관과 같은 사상이 존재한다. 그런 사상적 기반 덕분에 흔들림 없이 성공할 수 있었던 셈이다.

저자의 말대로 난 프로그래밍할 때마다 머릿속에 항상 흔들림이 있었다. 변수명은 이게 맞을까, 어떤 구조가 좋을까 등의 고민들이다. 이럴 때 나는 그때그때마다의 목표를 달리 설정하였다. 어떤 때는 단순성만을 추구하였으며, 어떤 때는 가독성만 지키려 작업을 했었다. 나중에 코드를 돌이켜보니 일관성이 없고 들쭉날쭉한 코드가 되어 있었다. 책에는 이런 나를 뒷받침해 줄 것이라 생각된 가치, 원리, 기법, 정리가 무려 64개나 된다. 한번에 다 익히긴 무리니 짧게 요약한 정리본을 출력하여 옆에 두고 하나씩 지켜야겠다.

저자는 크게 6개 사상으로 "프로그래밍 이론", "아키텍처 기본 기법", "아키텍처 비기능 요구사항", "7가지 설계 원리", "UNIX사상", "UNIX철학"를 소개하고, 각각 세부 정석으로 나뉘어서 총 64개를 설명하였다. 이 중 처음에 있는 "프로그래밍 이론" 사상을 소개한다. '의사소통', '단순함', 유연성'이라는 3가지 가치가 프로그래밍 이론을 지탱한다고 말한다. 다른 책에서도 이 가치들이 자주 언급되는 걸 보면 보편적이면서도 중요한 것 같다. "코딩을 지탱하는 기술"에서는 의사소통과 단순함을 위해 프로그래밍 언어가 발전하는 역사를 잘 보여줬다. "읽기 좋은 코드가 좋은 코드다"에서는 제목에서 보이듯이 코드를 읽는 사람과 의사소통을 강조한다. 특히 코드 사례로 설명을 하여 나처럼 초보자에게 확실한 이해를 도와주었다. "Clean Code"는 3가지 가치를 위해 더 자세하게 설명해준다. "GOF 디자인 패턴"에서도 이 가치를 추구한다고 패턴별 목적에 설명되어 있다.

난 3가지 가치 중 '의사소통'을 우선하려 한다. 책에서 얘기한 것처럼 코드를 읽는 사람은 타인일 수도 있지만 자신의 코드를 자신이 디버깅, 검토를 하면서 자기 자신도 코드를 읽는 사람이 된다. 그래서 코드를 읽는 사람과 잘 의사소통하기 위해 읽기 좋게 작성하는 건 결국은 나를 위한 일이기도 하다. 코드에는 2가지 측면이 있는데 컴퓨터의 직접적인 측면인 '컴파일러나 인터프리터에 대한 입력'과 '남에게 보여주는 문장'이라는 측면이 있다. 저자는 후자 측면을 의사소통의 가치로 두자고 한다. 코드를 단순하게 만들면 읽고 사용하고 수정하기를 예전보다 빠르게 할 수 있다. 저자는 불필요한 복잡성을 제거하여 코드를 단순하게 하자고 한다. 여기의 복잡성은 목적이 복잡하여 이를 부합한 코드의 복잡성이 아닌 어떻게든 동작하게 하려고 만든 코드에서의 복잡성을 말한다. 단순함과 의사소통은 서로 좋은 영향을 주고받는다. 의사소통을 중시하고 다른 사람의 관점으로 살펴보면 어떤 복잡성을 버려야 할지가 명확해진다고 한다. 너무 단순하게 만들어서 정보가 적어 이해하기 어려워진 경우라면 다소 장황해지더라도 의사소통을 우선시하라고 조언한다.

유연성은 코드 변경이 용이함을 뜻한다. 코드는 반드시 변경이 된다는 사실에 따라 변경하기 쉽고 유연한 코드를 작성하는 것이 추후 오류 수정, 기능 변경, 기능 추가 작업을 원활하게 한다. 확장하기 쉬우면서도 확장에 따른 영향이 다른 부분에 미치지 않도록 설계하라고 한다. 하지만 유연성은 변경 용이를 맞추기 위해 복잡해 지기 쉽다. 복잡성을 갖지 않고 유연성을 갖게 하기 위해 즉시 효과가 나타나는 코드만 유지하고 이외는 작성하지 않도록 하라고 한다. 미리 예측하여 만든 하향식 설계보다 단순함을 시작으로 상향식으로 얻어는 유연성이 실제로 효과적이라고 한다.

4. 관점: 프로그래머가 보는 시각

프로그래밍할 때마다 문득문득 떠오른 선택의 기로에서 자신만의 기준으로 결정하게 된다. 이 챕터에서 저자는 프로그래머의 판단에 도움을 줄 수 있는 관점을 소개한다. 저자는 함수 단위보다 넓은 모듈 단위에서 개념들을 조망하여 설명하고 있다. "응집도", "결합도", "직교성", "가역성", "코드의 구린내", "기술적 부채" 이렇게 6개 관점을 소개한다. "응집도"와 "결합도"의 상세 단계는 이번 책에서 처음 보았다. 단계를 보면 내가 어느 단계인지를 미루어 보고 내 위치를 확인할 수 있다. 재미있는 시도라서 응집도와 결합도의 각 단계를 소개한다.

응집도:

...* 모듈 내 기능 간의 친밀함을 보여주는 강도

...* 7단계로 높은 단계로 올라갈수록 바람직한 것

1단계: 암합적 강도

...우연히 발견된 중복 명령을 모은 것

...A모듈 a, b기능이 B모듈에서도 우연하게(암합) 명령 패턴이 발견되어 하나의 모듈로 모음

2단계: 논리적 강도

...모든 입출력 조작, 여러 데이터 편집과 같은 기능을 단순히 추상적으로 모은 것

3단계: 시간적 강도

...특정 시점에 연속해서 실행되는 기능을 모은 것

...초기화 처리를 하나로 묶는 게 대표적 사례

4단계: 순서적 강도

...작업 처리를 위해 관계된 기능들을 순서적으로 모은 것

...커다란 기능의 일부 순서를 하나의 모듈로 만든 것

5단계: 연락적 강도

...모듈 내 기능 사이에서 데이터를 교환 또는 참조하는 기능들을 모은 것

...모듈 진입점이 하나이며, 파라미터에 의해 모듈 내 기능을 선택

6단계: 정보적 강도

...특정 자료구조를 다루는 여러 개의 기능을 하나의 모듈에 모은 것

...모듈 진입점이 여러 개, 각 진입점이 고유한 기능을 수행

7단계: 기능적 강도

...모듈 내 모든 명령이 하나의 역할을 실행하기 위해 모은 것

결합도:

...* 모듈끼리 갖는 관계의 밀접함을 나타내는 강도

...* 6단계로 높은 단계로 갈수록 바람직한 것

1단계: 내용 결합

...다른 모듈 내에서 외부에 선언되지 않은 데이터를 직접 참조하거나 명령의 일부를 공유하는 방식

...어셈블리 언어 등 저수준 언어를 사용하는 모듈에서 자주 발견

2단계: 공통 결합

...공통영역에 정의된 데이터를 몇 개 모듈이 공동으로 사용하는 방식

...공통영역에 정의된 데이터를 전역 변수라 함

3단계: 외부 결합

...모듈에서 public 지시자처럼 외부로 노출한 데이터를 다른 모듈이 공유하는 방식

4단계: 제어 결합

...호출하는 모듈이 제어를 지시하는 데이터를 파라미터로 전달하여 받는 모듈이 제어를 수행하는 방식

5단계: 스탬프 결합

...공통영역에는 없는 자료구조를 2개의 모듈에서 교환하는 방식

...기능들이 전달된 자료구조의 일부 데이터를 사용하지 않음

6단계: 데이터 결합

...명확히 정의된 파라미터로 데이터를 교환하는 방식

...스탬프 결합 방식에서 모듈 들이 전달되는 자료구조 내의 모든 데이터를 처리하면 데이터 결합으로 간주

내가 했던 작업을 돌이켜보면 응집도는 4, 5단계가 자주 보이며 결합도는 3,4,5 단계가 보였다. 1단계에서 한 단계씩 오르는 과정이 초보자가 경험을 쌓아 시행착오를 거치는 과정처럼 보였다. 나는 좋은 코드를 보고 해당 코드에서 보여지는 패턴을 내 코드에 적용해 보면서 응집도와 결합도를 올리려고 노력하고 있다. 저자는 응집도에 대해서는 가능한 7단계(기능적 응집도 강도)를 지향하자고 한다. 불가피하게 하위 강도에 이르렀다 하면 명확한 평가 기준하에 대체안을 검토하는 과정이 중요하다고 말한다. 결합도에 대해서는 6단계(데이터 결합)를 맹목적으로 지향하기보다는 결합하려는 대상과의 친밀도에 따라 단계를 결정하라고 조언한다.

그 외 관점들은 간단히 소개한다. "직교성"은 2개 이상의 코드 덩어리가 있으면서 한쪽을 변경해도 다른 쪽에 영향을 주지 않는 것을 말한다. 직교 성이 있는 코드는 생산성 향상과 위험 경감의 장점을 누릴 수 있다고 한다.

"가역성"은 어떤 방침을 정해 놓고 추진하더라고 문제가 생겼을 때는 초기화가 가능하도록 해둠으로써 위험을 최소화하라는 것이다. 유일하고 최종적인 결정은 없으며 변경이 존재할 수 있음을 인지하라는 것이다. "코드의 구린내"는 코드 중에서 이해하기 어렵고, 수정하기 어렵고, 확장하기 어렵다고 느껴지는 부분을 뜻한다. 이런 구린내를 식별해 내서 적절한 코드로 개선하라고 당부한다. 여기의 개선은 외부 동작은 바꾸지 않고 코드 내부 구조를 개선하는 것으로 이 방법을 '리팩터링’, '코드의 체질 개선'이라고 한다.

마지막으로 "기술적 부채"는 시간이 없거나 수정이 긴급하게 이루어져야 하는 상황에서 신속하지만 지저분한 코드를 선택하는 것을 말한다. 부채라고 부정만 할 것이 아니라 부채의 존재를 인지하고 신속하게 부채를 갚고 재앙을 피했으면 즉시 부채 이전의 상황으로 돌려 본래 있어야 할 깨끗한 수준의 코드로 수정하라고 한다.

5. 습관: 프로그래머의 일상

"습관도 좋은 것이다. 습관이 몸에 붙으면 선천적인 것이나 마찬가지이기 때문이다" - 아리스토텔레스 -

매 챕터마다 명언이 있는데 습관편 명언은 내용을 읽다가도 왠지 모르게 다시 쳐다보게 하였다. 나에게 명언이 잊히지 않는 건 좋은 프로그래머들의 습관과 마음가짐을 내 습관으로 만들고 나도 좋은 프로그래머가 되고 싶다는 바람 때문인 것 같다. 저자가 소개한 6개의 습관은 "프로그래머의 3대 미덕(태만, 성급, 오만)", "보이스카우트 규칙(코드를 청소하고 돌아간다)", "성능 튜닝에 관한 금언", "비자아적 프로그래밍", "한 걸음씩 조금씩", "TMTOWTDI(방법은 하나가 아니다)"이다. 여기선 내가 먼저 따라 하고 싶은 습관인 프로그래밍의 3대 미덕을 소개한다.

Perl 설계자인 Larry Wall이 "Programming Perl"에서 제안한 3대 미덕인 태만, 성급, 오만은 말 자체는 부정적인 느낌이 있지만 쿨한 반전이 있는 해석이 있어 더 따라 해보고 싶어 진다.

태만: 나중에 모두 편해지도록 지금 유용한 코드를 작성한다

성급: 컴퓨터가 놀고 있는 것에 분노를 느끼는 기질이다.

오만: 높은 자존심을 갖고 남에게 내놓아도 부끄럽지 않은 코드를 작성한다.

나는 나중을 위해 주석과 가급적 간결한 코드를 작성하려고 노력한다. 하지만 코드의 간결성이 잘 되지 않는 경우가 있다. 이럴 땐 동료에게 세미나 같은 형식으로라도 설명하고 이해를 시키며 위키에 문서를 남기는 편이다. 설명하고 문서를 작성하는 당시는 번거롭고 시간이 더 걸린다. 그렇지만 시간이 지난 뒤에 동료들이 문서를 보면 코드의 목적 등을 빨리 떠올릴 수 있어 일이 수월하게 되는 경우가 있었다. 전체적으로는 효율적이었다고 생각된다. 하지만 근본적으로는 애초에 코드 자체를 이해하기 쉽게 하는 게 번거로운 일을 줄일 수 있기에 간결한 코드를 만들기 위해 노력해야 겠다.

나에 대한 '성급' 습관은 더 노력해야 할 습관이다. 작업 정의부터 반복 작업이거나 수작업으로 수십 차례 반복을 하면 그제서야 해당 작업을 자동화하여 컴퓨터를 고생시킨다. 그러나 손에 익은 작은 작업들은 아예 바꿀 생각을 안 하고 그냥 수작업으로 하기도 한다. 아직은 몸이 고생이다. 손발을 덜 고생시키고 컴퓨터를 더 고생시킬 수 있는 여러 툴을 배워서 효율성을 높여야 겠다.

내가 느끼기에 '오만’은 거만한 것보다 자기가 열심히 만든 것을 남에게 잘 소개하고 싶다는 마음으로 이해되었다. 남들도 당연히 알고 있을 것이라는 "지식의 저주"에 빠지지 않게 하는 것도 이에 포함된다. 내 것이 남부끄럽지 않게 하려면 아무래도 코드만으론 부족하니 문서와 함께 잘 갖추도록 해야겠다.

6. 기법: 프로그래머의 도구 상자

도구 상자는 실제 사용하는 툴이 아니라 사고의 프레임워크이자 설계 기법 혹은 문제 해결 방식을 말한다. 프로그래밍 할 때 수많은 고민과 선택이 필요하게 된다. 달인들은 이러한 상황에 흔들려 쓸모없는 소프트웨어가 만들어지는 것을 방지하기 위해 자신만의 기법을 활용한다. 소개된 기법은 "예광탄", "계약에 의한 설계", "방어적 프로그래밍", "개밥 먹기", "콘텍스트", "고무 오리"이다. 이 중 내가 이용해본 방법은 고무 오리 기법이다. 고무 오리 기법은 일종의 설명하는 디버깅이다. 동료에게 내 코드의 목적, 배경 등을 차분하게 말한다. 그리고나서 코드를 설명하다 보면 스스로 원인을 깨닫고 해결까지 하는 경우가 있다. 말하다 보면 목적과 맞지 않는 코드를 발견하기도 하고 중복된 코드가 여기저기에서 발견되기도 한다. 이 기법이 모든 문제를 해결할 순 없지만 생각의 늪에 빠져 나오지 못할 때 만든 것이랑 떨어져 객관적으로 볼 수 있는 좋은 기법이다.

나머지들은 정리 해놓고 하나씩 실천해 봐야겠다. '예광탄’ 기법은 우선 토대를 만들고 서서히 살을 붙여 나가는 기법이다. 소프트웨어 최종 형태에도 골격의 일부가 되는 코드를 초기 단계에서 작성하는 것이다. 프로토 타입과는 접근법이 비슷하지만 프로토 타입은 콘셉트 확인이 끝난 뒤에 작성한 것을 전부 버리고 새로 얻은 정보를 사용해서 다시 올바른 형태로 재구축하기에 예광탄과는 차이가 있다. 다음 기법은 함수와 함수를 호출하는 쪽이 서로 계약을 맺고 있다고 간주하는 "계약에 의한 설계" 기법이다. 계약 내용을 미리 주석으로 알리고 계약대로 값이 전달되어 왔는지를 확인한다. 계약대로 값을 반환하는지는 단정문(assert)으로 표현한다. 코드도 단순해지고 요구된 것만 수행하여 올바른 코드를 작성하기 쉬워진다.

"방어적 프로그래밍" 기법은 함수에 잘못된 데이터가 넘어왔을 때 그것이 다른 함수 탓이었다고 해도 피해를 입지 않도록 방어적인 코드를 작성해 두는 것이다. 이 기법에는 2가지 관점이 있다. 하나는 파일, 사용자 인터페이스, 네트워크 등의 외부 소스에서 데이터 입력값을 확인한다라는 관점이다. 두번째는 입력 파라미터 값을 확인하는 관점이다. 이는 함수에서 무효한 입력을 검출하기 위함이다. 개발할 때는 단정문을 사용해서 실행 중 문제가 발생되면 바로 프로그램이 정지하게 되어 어디서 어떤 값이 문제인지를 빨리 파악할 수 있다.

다음은 조엘 온 소프트웨어에서 소개된 "개밥 먹기" 기법이다. 본인이 개발한 소프트웨어를 본인이 직접 사용해 보는 것이다. 개발자 본인이 사용자처럼 사용하여 사용자적인 관점을 얻는 것이다. 사용자에게 편리하다고 말하면서 소프트웨어를 제공하는 이상, 본인이 직접 사용하고 편리함을 증명해 보이라고 말한다.

마지막은 주위 상황이나 배경을 뜻하고 문맥이라고도 하는 "콘텍스트" 기법이다. 코드를 작성할 때 컨텍스트를 먼저 제시하면 읽는 사람이 상황을 우선 판단할 수 있고 무엇에 관한 코드인지를 파악할 수 있게 된다. 반대로 코드를 읽을 때는 컨텍스트를 파악한 다음에 내부 코드를 이해한다면 좀 더 원활하게 코드를 파악할 수 있게 된다.

7. 법칙: 프로그래밍의 안티패턴

안티 패턴은 일반적으로 사용되지만 실제로는 비효율적이거나 비생산적인 디자인 패턴을 의미한다. 9개의 패턴이 소개되었는데 내 주위나 나에게서는 5~6개 정도의 안티 패턴이 보인다. 사실 이 패턴이 반복적으로 보이는 것은 문제 해결이 급하다는 핑계를 대거나 문제가 되는 패턴을 심각하게 받아들이지 않기 때문으로 간주된다. 패턴 중 가장 피부에 와 닿고 해결하기 어렵다고 생각되는 건 브룩스의 법칙인 맨먼스 미신이다. 나도 그렇지만 대개 문제의 본질을 찾기보단 눈에 보이는 현상만 조치하려는 다급한 마음이 원인이라고 생각한다. 내가 결정권을 가지고 있을 때 더 그런 경향을 보이는 것 같다. 땜빵은 항상 더 큰 땜질을 하게 됨을 마음에 새기고 시간이 걸리더라도 하나씩 해결하는 착실함을 발휘해 보자.

나머지 안티 패턴은 "콘웨이의 법칙(아키텍처는 조직을 따른다)", 깨진 유리창 법칙(나쁜 코드는 개미구멍), 엔트로피 증가의 법칙(코드는 저절로 썩어간다), 80:10:10의 법칙(프로그래밍에 만병통치약은 없다), 조슈아 나무의 법칙(이름이 없는 것은 보이지 않는다), 세컨드 시스템 증후군(두 번째 배포는 기능 과다), 수레바퀴의 재발명(이미 있는데도 만든다), 야크의 털깎기(진짜 문제에 도달하지 못한다)이다. 모두 하나하나 자기반성이 필요한 이야기이다. 프로그램의 최종 목적은 나를 포함한 사용자가 만족하는 결과를 내는 것이니 후유증이 없는 방법을 찾아보자. 만약에 안티 패턴이 납득이 안 가면 "비자아적 프로그래밍" 습관처럼 만든 것에서 떨어져서 나를 분리해 객관적으로 보도록 노력하자.

책을 읽은 후 소감

101가지라는 많은 수에 주눅들었다가 읽다 보면 당연한 얘기도 있고  단순, 가독성, 반복 제거 들처럼 묘하게 반복되는 내용들이 있어 읽다보면 부담감이 줄어든다. 그리고 첫 3개 정석은 프로그래밍이 이렇다라는 사실을 소개한 거라 문제를 직접 해결하는 방법이 아니기에 읽고 이해 했다면 3개는 해야할 101개에서 빠지게 된다. 그렇다면 이제 거의 100개 정도만 남은 것이다. 좋은 프로그래머가 되기 위해 천 개, 만 개도 아니고  100개 정도만 알면 되기에 시도를 못할 정도의 개수는 아니라고 생각된다.  소스 구조를 바꿔야 하는 원리원칙들은 바로 시도해 보기 어렵지만 가독성을 높이기 위한 변수명, 함수명을 고치는 건 즉시 할 수 있는 일들이다. 시도하기 수월한 것부터 하나씩 도전하고 매번 꾸준히 하도록 노력해 봐야 겠다.

여러 후기들처럼 예제가 없어 이해가 잘 안되던 정석들이 있다. 예제가 있었다면 너무 분량이 많아져서 책 읽기가 부담 됐을꺼라 저자를 이해할 수 있다. 다행히 친절하게도 저자가 각 정석마다 참고서적을 달아 놓았다. 난 읽으면서 더 알고 싶은 것 정석에 대해서는 참고서적 중 제목이 마음에 드는 것에 표시해 놓고 연계해서 보기로 남겨두었다. 이 책은 전체적인 윤곽을 잡았다라는 데에 아쉬움보다 의의가 더 크다.

책을 추천하기 위해 서평을 쓰는데 이 책은 경험이 별로 없는 프로그래머가 읽으면 와 닿는게 적을 것 같다라는 생각이 든다. 나처럼 몇 년 코딩했는데 발전이 없다라고 생각하는 분들이 읽었으면 정말 도움이 될 꺼라 생각되어 정말 추천드린다.

각주

[1] 프로그래밍의 정석: http://www.aladin.co.kr/shop/wproduct.aspx?ItemId=120459446

[2] 개발자, 한 달에 책 한 권 읽기 모임: https://www.facebook.com/dev.reader/


Popit은 페이스북 댓글만 사용하고 있습니다. 페이스북 로그인 후 글을 보시면 댓글이 나타납니다.