코딩 호러가 들려주는 진짜 소프트웨어 개발 이야기

저자
제프 앳우드 지음
출판사
위키북스 | 2013-11-28 출간
카테고리
컴퓨터/IT
책소개
코딩 호러 블로그 운영자이자 스택 오버플로우의 공동 창업자가 들...
가격비교



임백준 님이 번역하신 또 다른 책 ! ㅎㅎㅎㅎ


저자이신 제프 앳우드 님은 프로그래머 사이에 유명한 블로그인 '코딩 호러'를 운영하시는 분이시다. 

그리고 코딩하면서 구글링을 했다면 누구나 알 법한 stackoverflow.com 을 창립해 사이트를 구축하신 분. 

오랫동안 닷넷 프로그래머로 일하셨고 지금은 루비 쪽에 관심이 있으신 것 같다.


'읽기 좋은 코드가 좋은 코드다' 라는 책에선 코드로 설명을 많이 하는 반면

이 책은 정말 - 이야기 - 가 많다.


그래서 조금......... 지루했다. 읽는 것도 꽤 걸렸다. 

물론 다 피가 되고 살이 되는 이야기 겠지만.............. 

지루하기도 하고 지겹기도 해서 어떤 글들은 대충 읽기도 했다.


제프 앳우드 님의 블로그에서 좋은 글들을 선별해 엮은 책이라 확실히 블로그 스러운 느낌의 글들이 많다.

절대로 그 분의 글솜씨를 폄하할 생각은 없지만 (물론 역자님 탓을 하고 싶지도 않다)

약간 앞뒤 말이 안 맞는 부분도 있었고, 문장이 길어서 이해하기 힘든 부분도 있었다.

내용 자체가 어려웠던 부분도 있었다.


짧게 결론을 내리면...............

'읽기 좋은 코드가 좋은 코드가' 라는 책보다 확실히 재미없었다 ㅡ_ㅡ...

나중에 좀 더 레벨업 된 개발자가 됐을 때 다시 읽어 보든가 해야겠다. 

- 내가 이해력이 딸려서 그런 것일 수도 있으니 -


포스팅 시작부터 이렇게 부정적인 얘기만 blah blah 하니까

아무도 안 읽을 것 같다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ



하지만 !!! 물론 읽을 만한 글들도 있다. 정말로 지루하기만 했다면 리뷰 글따위 쓸까 보냐.

처음부터 하나씩 훑으면서 자세한 리뷰를 남기겠다.




Part 1. 쓸데없는 일을 줄이는 법


아까 위에서 앞뒤 말이 안 맞는 부분이 있었다고 했는데

바로 이 파트에 그런 글들이 있었다.


'쓸데없는 일 하지 않기' 라는 글에서 할일 목록 따위를 만들어서

스스로를 강박주의자로 만들지 말라는 글이 있었다. 

심지어 굉장히 진지하게 할일 목록을 전부 내다 버리라고 글을 쓰셨다.

정말로 중요한 일이 있다면 우리의 뇌가 그걸 잊어버릴 일은 없다고.


그런데 


'우리 프로젝트는 언제나 90퍼센트 가 완료돼 있을 뿐이다.' 라는 글에서는 조금 다르다.

이 글에서는 목록이 없으면 스케줄도 없다고 하며

프로젝트가 90% 완료에만 머무는 슬럼프를 넘기 위해서는

개발자들에게 자기가 해야 할 일을 모두 자세하게 나열해보도록 권장하는 글이 있었다.


둘다 쓸데없는 일을 줄이는 방법이긴 하지만 전혀 다른 방법이다...

물론 내가 이해 못 한 부분이 있기야 하겠으나 이런 모순된 글을 보면서

앞뒤가 안 맞는 부분이 있다고 생각했다.



'열정이 있는데 재능이 무슨 필요람?'

- 이 컬럼은 앞에 무슨 얘기인지 잘 이해가 안 됐지만 마지막 글귀가 가슴에 와닿았다.

'당신보다 재능이 있는 수천명의 개발자가 있다고 해서 기죽지 말라. 

당신에게 열정이 있는데 재능이 무슨 필요가 있단 말인가?'


솔직히 낭만주의에 젖은 듯한 말 같지만 그래도 공감이 전혀 안되는 건 아니다.

열정이 있고, 열정이 있다는 걸 확실히 표출하는 게 중요하다고 생각한다.



뭐 어찌됐든 이 파트에서 가장 기억에 남는 글은 '보이드의 반복법칙' 이라는 글이다.

상당히 흥미로운 글이었다.

소프트웨어 개발에서 사용되는 반복적인 방법(iterative)과 재귀적인 방법(recursive)의

사이에 존재하는 차이를 설명하기 위해 선택한 비유가 있었다.

그 비유로서 한 공군 대령이 제트 전투기와 관련된 연구 이야기를 하는데 꽤 재밌는 이야기였다.

이 글에서 말하고 싶은 바는 보이드의 반복법칙 그대로였다.

반복의 속도가 반복의 질보다 우선한다.


상당히 인상 깊은 글이었다. 굳.




Part 2. 프로그래밍


'깨진 유리창 이론'

- 깨진 유리창을 고치지 않은 채로 방치하지 말라.

일단 창문이 깨지기 시작하면 깔끔하고 기능적으로 잘 동작하던 시스템이 

순간적으로 엉망이 되어버리는 모습을 보아왔다. 그러니 최대한 빨리 고쳐야 하고

제대로 고칠 시간이 충분하지 않다면 일단 나무 판자라도 대서 때우기라도 하면서

더 이상 훼손되지 않도록 조치를 취해 그 문제를 인식하고 처리중이라는 사실을 드러내라.


위의 글은 실용주의 프로그래머에서 설명된 글 일부를 정리해서 쓴 것이다.

저런 경험이 있는 지는 잘 모르겠지만 왠지 모르게 공감이 가서 여기에 대충 적어봤다.



'궁극의 코드 카타'

- 카타 : 미리 정해진 동작을 반복해서 훈련하는 것을 의미. 무술에서 사용하는 단어.

프로그래밍을 잘 하기 위해선 어떻게 해야 되는지 방법들이 적혀있다.

참고할 수 있을 만한 사이트가 주석으로 달려있다.

http://www.codekata.com/

http://www.codingdogo.org/



'프로그래밍에서는 1이 가장 외로운 숫자다', '당신의 코딩 친구는 누구인가?'

- 음........ 위 글들은 페어 프로그래밍(Pair Programming) 이라는 키워드는 없었지만 

이 키워드를 강조하는 글들이었다. 


나한테 코딩 친구가 있는지 생각해보니까 아직은 없는 것 같다. 흐음.

아직까지 우리나라에서는 페어로 일하는 문화는 거의 없지 않나 싶다.(개발자들 사이에서)

오히려 서로 터치해봤자 트러블이 있을 수 있으니 각자 독립적으로 일하는 분위기랄까.

"쿨하지 못해 미안해. 그러니 각자 할 일 하자." 이런 느낌? 유감스럽다.



'소프트웨어 도제살이'

- 소프트웨어 개발에서 견습생/고참/장인 이라는 관계를 키워나가야 될 필요성을 말하는 글.

확실히 그런 건 있는 것 같다. 

'내가 하면 오늘 안으로 다 할 것을, 일부러 후배에게 일임하면서 경험을 쌓도록 도와주는 것'

쉬운 일은 아니다. 왜냐면 멘토 입장에서 후배하는 거 보면 복장이 터질 정도로 답답할 수 있으니까.

그럼에도 불구하고 훌륭한 후배들을 양산해 내기 위해 노력하시는 개발자 분들을 보면

정말 존경스럽다. 나도 그런 분들을 닮고 싶다.




Part 3. 웹 디자인

솔직히 개발자를 위한 책에서 이 파트가 다뤄졌다는 점이 신기하다.

게다가 글도 꽤 많은 양을 차지하고 있는 파트다. 우왕 의외다.


'앱이 웹사이트를 죽일 것인가?'

- 이 글에서의 결론을 정리하자면

웹사이트가 앱에게 죽지 않으려면 멍청한 웹사이트가 되어선 안 된다.


- 앱이 웹사이트 보다 나은 이유

(1) 더 빠를 수 있다.

(2) 단순한 Native UI Control 을 사용한다.

(3) 앱은 스크롤 공간을 더 효율적으로 사용한다.

(4) 온오프라인 상관없이 잘 동작한다.


- 웹사이트가 앱보다 나은 이유

(1) 브라우저만 있으면 어떤 장치에서도 사용할 수 있다.

(2) 설치할 필요가 없다.

(3) 업데이트 될 필요가 없다.

(4) 웹사이트는 보편적인 UI 경험을 제공할 수 있다.



'값싸고 손쉬운 사용성'

- 소프트웨어 프로젝트의 사용성과 관련해서 입문자를 위한 쉬운 책

'스티브 크룩의 사용성 평가, 이렇게 하라!'



'사용성 VS. 학습용이성'

- 조엘 스폴스키의 책 '프로그래머를 위한 사용자 인터페이스 디자인'

학습 용이성에 관심을 가져야 하는 경우 : 관광지 여행객과 같이 아주 가끔 방문하는 사용자

사용성에 관심을 가져야 하는 경우 : 전문적인 작가를 위한 워드프로세서



'구글의 가장 큰 UI 실수'

- 구글 메인의 I'm Feeling Lucky 버튼에 대해 엄청 까는 글인데 재밌다. ㅋㅋㅋ




Part 4. 테스트

- 유닛테스트(Unit Test) 를 한번 해보고 싶다는 생각은 하지만 아직도 실천되지 않는....ㅠ_ㅠ

- '예외 로그는 고객의 피드백이 가질 수 있는 최고의 형태다' 라고 하셨는데 맞는 얘기다. 공감 빵빵.




Part 5. 당신의 사용자를 알라

- 꽤 많은 양의 글을 담고 있지만 기억에 남는 글은 별로 없었다.


'묻지 말고 관찰하라'

- 이 글을 보면 초창기 구글.co.kr 의 화면 이미지가 있는데 정말 화가 난다. 지저분해서 ㅡ_ㅡ

지금은 모르겠는데 당시 한국 사람들은 고급 제품으로부터 복잡성을 기대한다는 이야기를 보고 놀랐다.

말도 안돼. 나도 한국 사람이지만 이해가 안 된다. 리얼리? ㅋㅋㅋ


- 그 밖에는 아마존의 상품 추천 기술 도입에 대한 실험 정신을 볼 수 있는 에피소드가 재밌었다.




Part 6. 우리가 관심을 둬야 할 것들


'인터넷... 그리고 그 밖의 모든 것들을 보존하기'

- 제이슨 스콧 : 2011년 인터넷 아카이브에서 공식적인 사료보관인으로 임명받음.

- 인터넷 아카이브가 하는 일 : 인터넷에서 단 한 번이라도 존재한 적이 있는 웹페이지를

당시의 모습 그대로 영구히 저장한다.

- 왜 ? : 인터넷에 올라오는 정보들은 너무나 빠르게 변하기 때문에 순식간에 모두 상실되는 것은

정상적인 현상이지만 그 결과로 우리의 문명은 기억상실증에 걸린 듯 하다. 

과거의 하이퍼링크에 대한 소스가 필요한 평범한 시민들에게 있어 꼭 필요한 일이다.


'유튜브 VS. 정당한 사용'

- 저자가 블로그에 어떤 영화의 일부 장면을 인용하고자 유튜브 동영상을 올리다가

유튜브에게 저지 당한.... (정확하게는 컨텐츠 제작자) 사연이 있는 글인데, 재밌다.

흥미롭기까지 할 정도인 유튜브의 기술..............ㅋㅋㅋㅋㅋㅋㅋ 진짜 대단하다. 짱이다.


- TED 강연 : How youtube thinks about copyright

http://www.ted.com/talks/margaret_stewart_how_youtube_thinks_about_copyright

꼭 봐야지 라고 생각하는 것들 중 하나가 되어버렸다. 대ㅋ박ㅋ



Part 7. 게이밍

- 아타리와 비쥬얼 베이직부터 시작해 게임 분석에 관한 이야기, 

게임 플레이어에서 게임 개발자로까지의 이야기가 있지만............ 

왠지 세대차이도 조금 느껴지고 당연한 이야기인 것 같아서 조금 실망.



Part 8. 읽어볼 만한 내용


'프로그래머는 책을 읽지 않지만 당신은 읽어야 한다'

- 저자가 추천해주신 책 목록

1. Code Complete 2

2. Don't Make Me Think (상식이 통하는 웹사이트가 성공한다)

3. Peopleware

4. Pragmatic Programmer (실용주의 프로그래머)

5. Facts and Fallacies of Software Engineering (소프트웨어 공학의 사실과 오해)



'아무도 당신을 돕지 않을 것이다. 그리고 그 점이 바로 멋진 부분이다'

- 시중에 나온 자기계발서의 95%는 완전히 쓰레기다............. 라고 하셨다.

ㅋㅋㅋㅋㅋㅋㅋ 왠지 책을 많이 안 읽어서 다행이다 라고 한심한 생각을 하게 된다 ㅋㅋㅋㅋㅋㅋ


- 유일하게 추천하는 자기계발서 '59초: 순식간에 원하는 결과를 끌어내는 결정적 행동의 비밀'

영문책이라 한글판으로 있는 지는 모르겠다. 원제는 '59 Seconds: Think a little, Change a lot'.

추천하는 이유는 과학적 연구결과를 찾아 인용하면서 설득하기 때문이라고 한다. 믿을만 하다는 것이다.




음........... 앞에 부정적인 말들을 많이 한 것 치고는 정리해보니

그래도 잘 읽은 책인 것 같다 ㅋㅋㅋ 나도 참 줏대없는 인간인듯ㅋ


원래 이 책이 나오기 전에 

'코딩 호러의 이펙티브 프로그래밍' 이라는 책이 먼저 나왔는데 그거 먼저 읽을 것 그랬다.

역자의 말에 의하면 그 책보다는 이 책이 좀 더 개발자에게 재밌을 거라고ㅋ


ㅇㅏ ~~~~~

다음엔 뭘 읽어볼까.


by kelicia 2014. 5. 1. 23:04



읽기 좋은 코드가 좋은 코드다

저자
더스틴 보즈웰, 트레버 파우커 지음
출판사
한빛미디어 | 2012-04-10 출간
카테고리
컴퓨터/IT
책소개
* 더 나은 코드를 작성하는 간단하고 실전적인 테크닉!이 책은 ...
가격비교



독서와 수십 억광년의 거리를 두다 언제부턴가 개발자를 위한 책을 읽기 시작 하면서

조금씩 책을 읽게 되었다. 그리고 지금은 리뷰까지 쓴다. 헛소리겠지만 나이 들었나 보다ㅋ


아무튼 간만에 재미있게 읽은 책이었다. 처음엔 단순히 임백준 님이 번역했다는 이유로

책을 선정했는데 선택하길 잘 한 것 같다. 굿초이스였다!


중학교때인가 독후감을 써내야 했었다. 당시의 난 책 읽는 것을 무지 싫어했지만

쓰긴 써야되니 임백준 님의 '뉴욕의 프로그래머'라는 책을 읽었다고 뻥을 치고 독후감을 썼다.


그러다 대학생이 되고 어느 날, 언니가 빌려온 책 중에 '뉴욕의 프로그래머'가 있는 걸 보고

중학교 때 생각이 나면서 호기심에 읽기 시작했고 임백준 님을 존경하게 되었다. 지금도 존경한다.

존경하는 분이 번역하신 책인 만큼 재미있겠거니 하고 '읽기 좋은 코드가 좋은 코드다' 라는 책을 읽게 되었다.



저자이신 더스틴 보즈웰, 트레버 파우커 두 분 모두 구글에서 근무한 경력이 있으신 분들이다. 짱이다.

지은이의 말이 시작하기 전에 다음 그림을 보고 공감해버리고 말았다. 

으, 생각만 하면 창피하다.

내가 지금도 이런다면 문제가 심각하겠지만 불과 2~3년 전만 해도

저랬던 건 확실하게 기억이 난다. 내가 짠 코드를 한 1년 뒤에 언니가 그 코드가 필요하다고 해서

파일을 넘겼는데 언니가 했던 말, '이 코드는 뭐하는 코드야? 이건 뭐고 저건 뭐하는 변수야?' 등등....


나 혼자 짠 코드라 주석따위 거의 없었고 변수 이름도 보면

내가 다시 봐도 기억도 안나고 뭐하는 변수인지 잘 파악도 안되는 그런 코드였다.

딱 위에 있는 그림과 같은 상황이었다. 제기랄.



리뷰에 앞서 참고로 이 책은 꽤 자잘하게 많은 예제 코드들이 있어

내 이해를 더 도울 수 있었고 코드 랭귀지도 C++, JAVA, Python, JavaScript, PHP 등 다양한 언어들

예시를 들어서 개인적으로 다양한 언어를 경험해본 나로서는 꽤 흥미로웠다.


그리고 이 책은 4 가지 파트로 구성되어있다.

1부. 표면적 수준에서의 개선 (이름 짓기, 주석, 미학, 코드베이스의 모든 줄에 적용될 수 있는 간단한 조언들)

2부. 루프와 논리를 단순화하기

3부. 코드 재작성하기

4부. 선택된 주제들



각 파트별로 리뷰를 남겨보겠다. 안 그러면 나중에 읽고서도 무슨 내용이 있었는지 기억이 잘 안난다.

중요하거나 기억에 남는 부분을 위주로 작성하겠다.




<< 1부. 표면적 수준에서의 개선 >>


(1) 이름에 정보담기

- 내 생각엔 이 파트의 내용은 정~~~말 깨알같은 도움이 되는 내용이었다. 버릴 게 없다.

특히 상황에 적합한 단어들을 골라 명명하라는 내용은 격하게 공감한다.

다음은 책에서 소개된 내용들이다.


 get

 fetch, download

 send

 deliver, dispatch, announce, distribute, route

 find

 search, extract, locate, recover

 start 

 launch, create, begin, open

 make

 create, set up, build, generate, compose, add, new

 filter

 select, exclude


왼쪽은 보통 일반적으로 많이 쓰는 단어들이다. 하지만 추상적으로 쓰일 때가 꽤 많다.

이를 대체하기 위해서는 아까도 말했듯이 오른쪽 단어들과 같이 상황에 적합한 단어들을 골라야 한다

내용이 기억에 남는다. 


나야 아마추어 수준이거나 그 이하의(ㅠㅠ) 개발자 지망생이긴 하지만...

어쨌든 개발하면서 왼쪽의 단어들을 많이 사용하는데 확실히 지금보니 추상적으로 썼을 때가

많았던 것 같다. 어휘력이 딸리다보니ㅡ_ㅡ.........


주석으로 blah blah 하느니 선언한 변수에 구체적이고 충분한 정보를 담는 이름을 명명하는 게 

훨씬 효율적이라는 것을 다시 한번 돌아볼 수 있었다.


그 외 기타 주의사항

- 단위 : time 보다는 time_ms, size 보다는 size_mb, angle 보다는 degrees_cw 등등



(2) 오해할 수 없는 이름들

- 경계를 다루는 한계값 관련

[1, 5] 가 1, 2, 3, 4, 5 를 포함하고 [5, 10) 가 5, 6, 7, 8, 9 를 포함하는 표기가 있듯이

영어도 이러한 표기 단어들이 있다.


경계를 포함하는 한계값 : min/max, first/last

경계를 포함하고 배제하는 범위 : begin/end (end가 애매하긴 하지만 관행인 것 같다)



(3) 미학

- 내가 개인적으로 추구하는 미학이랑 공감할 수 있는 부분이 많은 것 같아서 천만다행이다.



(4) 주석에 담아야 하는 대상

- '코드에서 빠르게 유추할 수 있는 내용은 주석으로 달지 말라' -> 이 이야기 보고 조금 뜨끔했다.

내 예전 코드를 까보면 내가 안 좋은 짓이란 짓은 꽤 많이 했었던 것 같다.(특히 쓸데없는 거) 끄엑ㅠㅠ


- 다음은 프로그래머 사이에서 널리 사용되는 표시라고 한다.


 TODO:

  아직 하지 않은 일, 해야할 일 

 (중요한 건 TODO:, 덜 중요한 건 todo: 이렇게 구분도 가능)

 FIXME:

  오작동을 일으킨다고 알려진 코드

 HACK:

  아름답지 않은 해결책

 XXX:

  위험! 여기 큰 문제가 있다



솔직히 TODO 빼고는 다 처음 본다..ㅋㅋㅋㅋㅋㅋㅋ

어쨌든 깨알같은(명확하고 간결한) 주석은 부지런히 달자. 

난 너무 주석을 안 다는 버릇이 있어서 고쳐야 된다.

다 피가 되고 살이 된다.




<< 2부. 루프와 논리를 단순화하기 >>


(1) 읽기 쉽게 흐름제어 만들기

- 함수 중간에서 반환해 중첩 제거하기

- 루프 내부에 있는 중첩 제거하기


아래 코드는 책에 있는 예제이다. 처음 코드를 두번째 코드로 고치자.


for ( int i=0; i<results.size(); i++ )

{

if ( results[i] != NULL )

{

non_null_count++;

if ( results[i]->name != "" )

{

cout << "considering candidate..." << endl;

}

}

}


for ( int i=0; i<results.size(); i++ )

{

if ( results[i] == NULL ) { continue; }

non_null_count++;


if ( results[i]->name != "" ) { continue; }

cout << "considering candidate..." << endl;

}


이 내용을 보면 '당연히 아래 코드처럼 짜야되는 거 아니야?' 라고 생각할지 모른다.

확실히 누가 봐도 아래 코드가 더 간결하고 아름답다. 혹은 'for each' 을 써서 다듬거나.


나는 이 책을 보면서 과거에 내가 짰던 코드들에 대해 많이 되돌아 보고 반성할 수 있었다.

왜 내가 첫번째 코드처럼 지저분하게 중첩을 사용했는지는 잘 모르겠다. 당시 좀 멍청했었나 보다.


코딩을 하다보면 가끔 이런 지저분한 중첩으로 논리를 복잡하게 할 때가 있는데 반성해야겠다.

정신놓고 코딩하면 첫번째 코드로 짤 수 있는 여지는 충분하다고 본다 ㅠ_ㅠ



(2) 거대한 표현을 잘게 쪼개기

- 이 장의 제목 그대로이다. 영리한 코드가 아닌 누구나 쉽게 이해할 수 있는 심플한 코드를 만들자.

자기 혼자 머리가 좋다고 논리를 복잡하게 꼬아놓은 그건 정말 ㅄ............. 잘난 척하지말자.


- Tip : Python, JavaScript, Ruby 같은 언어는 'OR' 연산자가 인수 중 하나를 반환한다.

(해당 값은 Boolean 으로 변환되지 않는다)

ex ) x = a || b || c 라는 코드는 a, b, c 라는 세 값 중에서 첫번째 '참' 값을 반환한다.


- C++ 에서 매크로를 사용할 수 있는데 보통 매크로의 사용을 자제하는 것이 좋다고 한다.

하지만 책의 예제와 같이 때에 따라선 매크로가 간단한 사용과 코드 가독성을 도움을 주기도 하니 기억해두자.



(3) 변수와 가독성

- 이 장에서는 내가 이 책에서 읽은 내용 중 가장 충격적(?)인 내용이 담겨져있다.


- 다음은 JavaScript 에서 Form 을 제출할 때의 함수이다.

대부분 아래와 같은 방식으로 코딩할 것이라고 생각했다...


submitted = false;    // 주의 : 전역 변수


var submit_form = function (form_name) {

if (submitted) {

return;    // 중복 제출 방지

}

...

submitted = true;

};


그런데 잘 알다시피 전역 변수는 사용하지 않는 편이 좋다.

특히 JavaScript 에서는 변수를 정의할 때 'var' 를 생략하면 해당 변수는 모든 JavaScript 파일과 <script> 블록에 접근할 수가 있다. 그러다보니 자기도 모르게 무의식적으로 이 변수와 같은 이름의 변수를 사용하면

이상한 버그를 만들어낸다. 나중에 작성한 코드에서 여전히 그 변수를 볼 수 있기 때문이다.


내 기억에 의하면 난 이 경험을 해본 적이 있다. 최악이었다.


var submit_form = (function () 

{

var submitted = false;    // 주의 : 아래에 있는 함수만 접근 가능


return function (form_name) {

if (submitted) {

return;    // 중복 제출 방지

}

...

submitted = true;

};

}());


어쨌든 아래 코드는 이해하기 힘들지만 JavaScript 에서 Private 변수를 만드는 테크닉이라고 한다.

정말 듣도 보도 못한 테크닉이고 이게 돌아가는 코드인지 조차 의심이 되는 이상한 코드였다 ! !

그래서 충격이었다. 이게 고급 개발자의 테크닉이란 말인가 ㅎㄷㄷ.... OTL......


익명함수가 있다는 걸 알고는 있었지만.... 이건... 크헙... 말도 안 나온다..

이런 식으로 익명 함수를 사용해 Private 한 범위를 만든다니............. 진짜 충격.......ㅠㅠ


이거 진짜 어떻게 돌아가는 건지.... submitted 변수가 계속 저장이 되나 저게????

그리고 어떻게 사용하는 건지 모르겠다.... form_name 은 어떻게 넣어 주는거지???


흐앙 ㅠㅠ........................ 패닉이다.

책에는 (이러한 테크닉에 대해 더 알고 싶으면 더글라스 크락포드의 자바스크립트 핵심 가이드(한빛,2008)

보라) 라고만 적혀있다......... 나중에 저 책을 사서 보든가 해야겠다 흑흑..




<< 3부. 코드 재작성하기 >>


(1) 상관없는 하위문제 추출하기

- 코딩을 하다보면 프로젝트랑은 직접적 연관은 없고, 자주 사용되는 도구 같이 유틸리티스러운(?) 부분을 짜게 된다.

그런 부분은 따로 디렉토리를 만들어서 모아두면 유용하게 쓰일 수 있다는 건 알고 있다.

하지만 실제로 난 코딩하면서 그래본 적이 없다 ㅡㅡ................. 이론만 알지 실천을 안하나보다. 제길.

어쨌든 일반적인 목적의 코드를 프로젝트의 특정 코드에서 분리하는 버릇을 좀 갖자 ! !



(2) 한번에 하나씩

- 책에 있는 예제가 깨알같다. 보면서 와닿는 것이 많고 깔끔한 코드가 정말 사랑스럽다.

- 한번에 여러 개를 못하고 하나에만 집중하는 타입인 나지만 이런 실수도 가끔 하는 것 같다. 

One Time One Job 하자!



(3) 생각을 코드로 만들자

- 앞에 코드 중첩을 피하는 방법이 다시 나오기는 하지만 그래도 다른 예제로 다시 상기시킬 수 있으니 좋았다.

- 저자님들의 말씀에 따르면 

" 간결한 코드를 작성하는 기술 중 하나는 라이브러리가 제공하는 기능을 잘 활용하는 것이다. "

이런 구절이 있는데 이걸 보고 감동 먹었다...........ㅠ_ㅠ.......


사실 나는 라이브러리를 나름 잘 갖다쓰는(?) 인간인데 

가끔 몇몇 분들께서 라이브러리를 활용해 구현했다고 하면 

그 순간, 그 사람의 능력을 폄하하고 개무시하는 분들이 계신다ㅡㅡ.

물론 혼자 완전 근본의 근본부터 다 짜면 좋겠지.... 인정한다. 


하지만 굳이 있는, 좋은 라이브러리를 무시하면서까지 과연 내가 그걸 일일이 다 짜야할 필요가 있을까. 

내 궁극적인 목적은 그게 아닌데도?? 제한된 시간은 어쩔건데??

라고 혼자 궁시렁 거리고는 한다 ㅠ_ㅠ....


그런 분들을 꽤 봤기 때문에 나는 - 내가 인정받지 못하는 게 두려우니까 -

되도록이면 라이브러리를 사용했다는 얘기를 많이 숨기는 편이다. 

난 적절한 라이브러리를 찾아서 입맛에 맞게 잘 사하는 것도 능력이고 노력하는 거라고 생각하건만.

(ㅋ 물론 '남이 하면 불륜이고 내가 하면 로맨스'라는 생각일지도 모르겠다)


아무튼 저자님의 저 말씀을 읽고는 왠지 용기를 불끈! 얻었다. 

감사합니다. 사랑합니다. 저 힘낼게요.


- 고무 오리 기법 : 실제로 어떤 대학의 컴퓨터 연구실은 프로그램을 디버깅할 때 누군가에게 도움을 요청하기에 앞서

그 문제를 방 한 켠에 놓아둔 곰 인형에게 말로 설명하라는 정책을 가지고 있다고 한다. 놀랍게도 이렇게 문제를

큰 목소리로 말하는 행위가 학생 스스로 해결책을 찾게 도움을 주는 것으로 드러났다.


아마 누구나 저런 경험 있지 않을까 싶다. 타인에게 도움을 청하려고 이런 문제가 있다고 말하다가 갑자기

혼자 해결하고는 싱겁게 대화가 끝나버리는 상황ㅋ

어쨌거나 어떤 프로그램 or 생각을 말로 설명하는 행위는 문제의 틀을 제대로 잡는 데 도움을 준다고 한다.



(4) 코드 분량 줄이기

- 자기 주변에 있는 라이브러리에 친숙해져라 :

""매일 15분씩 자신의 표준 라이브러리에 있는 모든 함수/모듈/형들의 이름을 읽어라.""

(C++ 표준 템플릿 라이브러리 STL, 자바 API, 파이썬 내장 모듈 등)


이 말에 공감하지만.... 매일 읽게 되지는 않는다는 슬픈 현실ㅠ_ㅠ.... 귀차니즘이 죄다.

하지만 저 귀차니즘이 도움이 됐다고 해야될까, 나는 한때 구현하는 게 귀찮아서

자바 API 를 정말 이 잡듯이 뒤지면서 코딩을 했던 적이 있다.


뭐... 좋게 보면 활용 능력이 좋은거고(?) 나쁘게 보면 능력이 없다고 볼 수 있다.

무능력 하다는 소리는 듣기 싫으니 부지런해져야겠다. 아직 경험이 많이 부족하니까 ㅠ_ㅠ 휴 -




<< 4부. 선택된 주제들 >>


(1) 테스트와 가독성

사실 테스트 코드를 따로 작성해 본 경험은 없지만...

이 장에서는 멍청하게 테스트 하는 방법을 똑똑하게 테스트 하는 방법으로 도달하기까지의 과정이

예제를 통해 잘 정리되서 나와있다. 역시 깨알같다. 굳굳.


가독성을 위한 책이다 보니 심플한 게 킹왕짱이다ㅋ



(2) 분/시간 카운터를 설계하고 구현하기

- 앞에서 보았던 내용들이 총집합 되는 예제가 나온다.

코드를 처음부터 잘 짜는 것 보다는 오히려 아름답지 않더라도 우선 작성을 하고 

문제점이 뭔지 파악하면서 계속 개선해나가는 방향으로 설명을 한다.


사실 마지막 장의 내용이 잘 이해가 안 간다. 앞에 봤던 코드들에 비해서 코드 양이 많아서

이리저리 정신없이 책을 뒤적이며 코드 이해하다가 조금 짜증이 났다.


그리고 내용도 좀 수준이 있는 것 같다. 설계와 성능에 대해 논하면서 코드를 개선해 나가는데

중상급 개발자 정도는 되야 이 정도 아이디어가 나오지 않을까 하는 생각이 들었다.

배경지식이 좀 필요하다보니... 나같은 허접이 이런 아이디어를 낸다는 건 조금 무리인듯ㅠ_ㅠ




모든 장을 훑다보니 리뷰가 길어졌다.

이 책은 한번 읽었지만 나중에 다시 한번 읽어볼 가치가 있는 것 같다.

내가 이 책을 읽고 과연 이렇게 실행에 옮겼는지 반성하게 되는 의미에서 좋은 책이라고 생각한다.


수학이나 개발 관련 서적이 좋은 게...

원서가 영어라도 수학 기호나 프로그래밍 언어는 누구나 공통으로 알고 있으니

그것을 통해서 이해가 잘 된다는 점이다ㅋ.ㅋ


아무튼 이 책은 실질적으로 도움이 되는 팁이나 조언들이 깨알같이 수록되어 있어 소장가치가 있는 것 같다.


나같은 초급 개발자도 충분히 읽었기 때문에 개발자라면 누구나 읽을 수 있고 ~

책도 300 페이지가 안 되는 책이라 접근성(?)이 뛰어나다고 할 수 있다 ㅋㅋㅋ


읽기 잘 했다는 생각이 드는 책이라 언니에게도 추천해줬다 ㅋ.ㅋ

다음엔 임백준 님이 번역하신 또다른 책을 읽어볼 계획이다!


by kelicia 2014. 4. 27. 00:00


Stack, Queue 에 이어서 Linked List.

사실 이걸 먼저 포스팅 했어야 되는데 ㅡ_ㅡ; 어쩌다보니 순서가 바꼈다.



<< Linked List >>


(1) 포인터를 이용하여 데이터를 저장한다.


(2) Array 와는 다르게 물리적 구조가 순차적이지 않다.

Array 의 경우, 메모리에 순차적으로 저장되지만 

Linked List 는 포인터를 이용하기 때문에 데이터가 메모리에 순차적으로 저장되어 있지 않다.


(3) Linked List 의 기본 단위는 Node 구조체로 이루어져 있다.

Node 구조체에 데이터와 Link 를 저장해놓는다.


(4) 각 Node 의 생성은 동적 할당으로 이루어지고, 

첫번째 Node 를 가르키는 노드인 Header Node 가 존재한다.

(5) Linked List 에는 3가지 종류가 있다.

- Single Linked List / Circular Linked List / Double Linked List

- 각 리스트 별로 삽입(Insert), 삭제(Remove) 연산이 있고, 

각 연산 별로 Header / Middle / Tail 에서 일어나는 경우를 살펴볼 것이다.

(이미지 출처 : http://blog.naver.com/zkd1750/90183988309)


연산 처리 과정을 그림으로 이해하기 쉽게 정리하면 좋겠지만

이미 다 배운 내용을 정리하는 차원이라 굳이 그리지는 않겠다. 귀찮다.



1. Single Linked List


(1) Insert

- Header

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서

[Head] -> [?] -> [A] -> [B] -> [C:Tail] 로 [?] 라는 노드를 삽입할 것이다.


방법은 간단하다. 다음과 같은 순서로 노드의 삽입이 이루어진다.

① [?].next = [Head].next

② [Head].next = [?]


- Middle

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서

[Head] -> [A] -> [B] -> [?] -> [C:Tail] 로 [?] 라는 노드를 삽입할 것이다.


① [?].next = [B].next

② [B].next = [?]


- Tail

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서

[Head] -> [A] -> [B] -> [C] -> [?:Tail] 로 [?] 라는 노드를 삽입할 것이다.


① [C:Tail].next = [?]

② [?].next = NULL

(1번과 2번의 순서가 바뀌어도 상관은 없다.)

③ *tail = [?]


(2) Remove

- Header

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서 [A] 를 삭제하면,

[Head] -> [B] -> [C:Tail]  이렇게 된다.


① [Head].next = [A].next    또는    [Head].next = [Head].next.next

② [A].next = NULL    // ① 연산으로 [A]를 가르키는 노드가 없으니 ① 연산 전에 [A]를 따로 저장

③ free([A])


- Middle

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서 [B] 를 삭제하면,

[Head] -> [A] -> [C:Tail]  이렇게 된다.


① [A].next = [B].next    또는    [A].next = [A].next.next

② [B].next = NULL    // ① 연산으로 [B]를 가르키는 노드가 없으니 ① 연산 전에 [B]를 따로 저장

③ free([B])


- Tail

[Head] -> [A] -> [B] -> [C:Tail]  이런 상태에서 [C:Tail] 를 삭제하면,

[Head] -> [A] -> [B:Tail]  이렇게 된다.


① free([B].next)    // next 가 tail 인 녀석을 찾아서 메모리 해제

② [B].next = NULL

③ *tail = [B]




2. Circular Linked List


(1) Insert

- Header

[Head] -> [A] -> [B] -> [C:Tail] -> [A]  이런 상태에서

[Head] -> [?] -> [A] -> [B] -> [C:Tail] -> [?] 로 [?] 라는 노드를 삽입할 것이다.


① [?].next = [Head].next

② [Head].next = [?]

③ [C:Tail].next = [?]


- Middle

S.L.L 와 동일하다.


- Tail

[Head] -> [A] -> [B] -> [C:Tail] -> [A]  이런 상태에서

[Head] -> [A] -> [B] -> [C] -> [?:Tail] -> [A] 로 [?] 라는 노드를 삽입할 것이다.


① [?].next = [C:Tail].next    또는    [?].next = [Head].next

② [C:Tail].next = [?]

③ *tail = [?]


(2) Remove

- Header

[Head] -> [A] -> [B] -> [C:Tail] -> [A]  이런 상태에서 [A] 를 삭제하면,

[Head] -> [B] -> [C:Tail] -> [B]  이렇게 된다.


① [Head].next = [A].next    또는    [Head].next = [Head].next.next

② [C:Tail] = [Head].next

③ [A].next = NULL    // ① 연산으로 [A]를 가르키는 노드가 없으니 ① 연산 전에 [A]를 따로 저장

④ free([A])


- Middle

S.L.L 와 동일하다.


- Tail

[Head] -> [A] -> [B] -> [C:Tail] -> [A]  이런 상태에서 [C:Tail] 를 삭제하면,

[Head] -> [A] -> [B:Tail] -> [A]  이렇게 된다.


① [B].next.next = NULL    // next 가 Tail 인 녀석을 찾아보니 [B]. 즉, [B].next = Tail

연산 후 모습 : [Head] -> [A] -> [B] -> [C:Tail]

② free([B].next)

연산 후 모습 : [Head] -> [A] -> [B] -> [ ]

③ [B].next = [Head].next 

연산 후 모습 : [Head] -> [A] -> [B] -> [A]

④ *tail = [B]

[Head] -> [A] -> [B:Tail] -> [A]




3. Double Linked List

- previous, next 가 존재해서 조금 귀찮다.

- 어떤 책은 prev / next 로 하는 책도 있고, left /right 로 하는 책도 있는데 전자를 선택하겠다.

- 앞에 보았던 노드의 구조가 [Data, Next] 라면 지금은 [Prev, Data, Next] 정도 되겠다.


(1) Insert

- Header

[Head] ↔ [A]  [B]  [C:Tail]  이런 상태에서

[Head]  [?]  [A]  [B]  [C:Tail]  [?] 라는 노드를 삽입할 것이다.


① [?].prev = [Head] 

② [?].next = [Head].next

③ [Head].next = [?]

④ [?].next.prev = [?]


- Middle (Header 와 똑같다고 보면 된다)

[Head] ↔ [A]  [B]  [C:Tail]  이런 상태에서

[Head]  [A]  [?]  [B]  [C:Tail]  [?] 라는 노드를 삽입할 것이다.


① [?].prev = [A] 

② [?].next = [A].next

③ [A].next = [?]

④ [?].next.prev = [?]


- Tail

[Head] ↔ [A]  [B]  [C:Tail]  이런 상태에서

[Head]  [A]  [B]  [C]  [?:Tail]  [?] 라는 노드를 삽입할 것이다.


① [?].prev = [C:Tail] 

② [?].next = NULL

③ [C:Tail].next = [?]

④ *tail = [?]


(2) Remove

- Header

[Head]  [A]  [B]  [C:Tail이런 상태에서 [A] 를 삭제하면,

[Head]  [B]  [C:Tail] 이렇게 된다.


① [Head].next = [A].next    또는    [Head].next = [Head].next.next

② [Head].next.prev = [Head]

③ [A].prev = NULL    //  연산으로 [A]를 가르키는 노드가 없으니 ① 연산 전에 [A]를 따로 저장

④ [A].next = NULL

⑤ free([A])


- Middle (Header 와 똑같다고 보면 된다)

[Head]  [A]  [B]  [C:Tail이런 상태에서 [B] 를 삭제하면,

[Head]  [A [C:Tail] 이렇게 된다.


① [A].next = [B].next    또는    [A].next = [A].next.next

② [A].next.prev = [A]

③ [B].prev = NULL    // ①,  연산으로 [B]를 가르키는 노드가 없으니 ① 연산 전에 [B]를 따로 저장

④ [B].next = NULL

⑤ free([B])


Tail

[Head]  [A]  [B]  [C:Tail이런 상태에서 [C] 를 삭제하면,

[Head]  [A]  [B:Tail] 이렇게 된다.


① [B].next.prev = NULL    // next 가 Tail 인 녀석을 찾아보니 [B]. 즉, [B].next = Tail

② free([B].next)

③ [B].next = NULL

④ *tail = [B]



# Linked List 사용 사례 : 

- Stack, Queue, Tree 구현할 때 사용될 수 있다.

- 많이 쓰이기는 하는데 막상 사용 예제를 검색해보면 딱히 나오지는 않는 것 같다...



아, 드럽게 많네.

그림 별로 안 올려도 포스팅 하는데 겁나 오래걸린다ㅠㅠ


( + 이 포스팅에서 free 나 *tail 은 C언어로 쓰인 자료 참고하느라 추가했다.

원래 Java 로 코드를 한번 짜봤었는데 C 로는 안 해봐서 조금 지저분해도 써봤다. )


'Programming' 카테고리의 다른 글

[C]printf()에서 "%ul"와 "%lu"의 차이?  (0) 2015.07.05
언리얼엔진4 : DataTable 오브젝트 생성하기  (0) 2014.09.22
Delegate (대리자)  (1) 2013.12.20
[Python, C#]Lambda Form  (0) 2013.12.19
PHP vs. Ruby vs. Python  (0) 2013.12.19
by kelicia 2014. 4. 25. 02:36