프로그래머의 뇌
Publish date: 2022-04-03Tags: 구현-지침 뇌
( 이미지 출처 : http://www.yes24.com/product/goods/105911017)
감상
2022.04.03
연구자가 쓴 학구적인 책이다. 많은 논문을 인용한 점은 로버트 L Glass의 책을 생각나게도 한다. 이 책의 독자의 뇌 안에서는 경험적,직관적으로 알고 있던 코딩에 대한 노하우와 인지과학에 대한 상식이 통합되어 정리가 될듯한다.
참고자료
- 저자의 발표 영상 : Programming is writing is programming - Felienne
- https://www.hedycode.com/ : 저자가 만든 교육용 프로그래밍 언어
- https://embrava.com/pages/flow : 집중상태를 알려주는 램프
정리
PART I 코드 더 잘 읽기
- CH 1 코딩 중 겪는 혼란에 대한 이해
- 코드를 읽거나 작성할 때 LTM(장기 기억 공간), STM(단기 기억 공간), Working memory(작업 기억 공간)에서 인지 과정이 함께/상호보완적으로 일어난다.
- 코드를 읽을 때 혼란이 생기는 이유
- 지식의 부족 = LTM의 문제 (문법, 키워드를 모름)
- 정보의 부족 = STM의 문제 (읽은 코드에서 변수, 메서드가 하는 역할을 모름)
- 처리 능력의 부족 = 작업기억공간의 문제 (머리 속에서 흐름을 따라갈수 없음)
- CH 2 신속한 코드 분석
- STM은 2-6개 사이의 항목을 저장하는 용량이다.
- STM은 제약을 극복하기 위해 LTM과 협업한다.
- LTM에 지식이 충분하면 STM의 공간을 절약한다.
- 코드를 읽을 때 우선은 영상 기억 공간에 저장되고 일부만이 STM에 보내진다.
- LTM에 디자인 패턴, 도메인 지식이 있다면 코드를 기억하기가 쉽다.
- 알려진 디자인 패턴,주석문, 명확한 표식 등은 코드를 두뇌에서 처리하게 쉽게 만든다.
- CH 3 프로그래밍 문법 빠르게 배우기
- 문법에 대한 지식이 많을수록 청킹을 쉽게 할 수 있다.
- 기억에 도움이 되는 기법
- 플래쉬 카드
- 정기적인 입력. 긴 기간에 걸쳐 고르게 학습
- 기억을 인출하는 연습
- 정보간 연결 경로 구축
- 능동적 정교화 (기억하고자 하는 기억을 기존 기억과 연관지어 생각)
- CH 4 복잡한 코드 읽는 방법
- 작업 기억 공간의 한계를 넘어선 인지부하가 오면 코드를 이해할 수 없다.
- 코드를 읽을 때 생기는 인지부하의 종류
- 내재적 인지부하 : 문제 자체의 특성에 의한 복잡성에 인한 부하
- 외재적 인지부하 : 코드의 표현방식에 따른, 개발자의 지식부족으로 인한 부하
- 리팩토링으로 읽는 사람에게 익숙한 지식에 맞춰 코드를 변경함으로서 외재적 인지부하를 줄일 수 있음.
- STM의 부하를 줄여서 코드 이해에 도움이 되는 기법
- 의존 그래프 : 변수/메서드 등 코드 사이의 관계를 선으로 이음
- 상대표 : 프로그램의 실행도중에 변수값의 변화를 표현하는 표
PART II 코드에 대해 생각하기
- CH 5 코드를 더 깊이 있게 이해하기
- 변수의 역할은 고정값, Flag등 11가지로 나눌 수 있다.
- 역할에 따른 표기법(suffix, prefix)등을 이용할 수도 있다.
- 헝가리안 표기법도 원래 의도는 타입을 표현하기보다 의미론적으로 때로는 변수의 역할을 표기하는 방법을 제안한 것인데 적용되면서 한 쪽으로 치우친 면이 있다.
- 코드를 이해하는 2개의 층위
- 텍스트 구조 지식 : 문법 개념 등 프로그램의 표면적인 이해
- 계획 지식 : 코드 작성자의 의도(계획, 달성하고자하는 것)를 이해
- 코드를 읽는 능력과 자연어를 읽는 능력에 상관 관계가 크다는 연구결과가 있다.
- 시각화, 질문, 요약 등 자연어 읽기에 적용가능한 전략을 코드 읽기에도 사용할 수 있다.
- CH 6 코딩 문제 해결을 더 잘하려면
- 정신모델(mental model)은 우리가 문제를 생각할 때 형성하는 정신적 표상
- 풀어야 할 문제에 대해 추론하기 위해 사용할 수 있는 작업 기억 공간 내의 추상화
- 예: 소스 코드의 특정 라인이 실행되고 있다는 생각 (실제로는 바이너리 코드가 실행됨)
- 예: 변수를 박스로 생각, 또는 꼬리표로 생각
- 예: 자료구조, 디자인 패턴, 아키텍처 패턴, UML 다이어그램
- 정신모델이 구체적이면 복잡한 시스템에 대해 생각할 때 도움이 된다.
- LTM에 저장되고 작업 기억 공간에서 사용된다.
- 개념적 기계(notional machine)는 컴퓨터가 어떻게 기능하는지를 추상적으로 표현.
- 예: 소스 코드에서의 계산식(
double farenheit = (9.0 /5.0) * celsius + 32
)은 ‘대입 개념적 기계’ - 기존의 스키마타를 프로그래밍에 적용
- 층위 : 운영 체제 -> 가상머신/바이트코드 -> 컴파일러/인터프리터 -> 프로그래밍 언어
- 여러 개념적 기계가 상호보완되기도하고 상충되는 정신모델을 만들기도 함.
- 예: 소스 코드에서의 계산식(
- 정신모델(mental model)은 우리가 문제를 생각할 때 형성하는 정신적 표상
- CH 7 생각의 버그
- LTM에 저장된 지식은 새로운 상황/분야로 긍정적 전이가 되기도하고 부정적 전이가 되기도한다.
- 오개념을 방지하기 위해 테스트와 문서화를 하자.
PART III 좋은 코드 작성하기
- CH 8 명명을 잘하는 방법
- camelCase는 snake_case에 비해 더 잘 구분이 되지만 인식하는데 시간은 더 길린다.
- 나쁜 이름을 가진 코드에 버그가 많다.
- 상관관계가 인과관계를 의미하지는 않는다. 근본 원인은 실력 없는 프로그래머, 어려운 도메인 등일수 있으므로
- 나쁜 이름 근처에 버그가 있을 가능성이 높으므로 찾는 것은 도움이 된다.
- 이름 형식의 틀, 작명 방법론이 도움이 된다.
- CH 9 나쁜 코드와 인지 부하를 방지하는 두 가지 프레임워크
- 마틴파울러가 리팩토링 책에서 언급한 ‘코드 스멜'은 인지부하를 높힌다.
- 예: 긴 매개변수 목록 -> 작업 기억공간을 많이 소모
- 인지부하 측정 방법 : 눈깜빡임 비율, 피부 온도, 파스 척도(스스로 부하 정도의 느낌을 표시)
- 언어적 안티 패턴 : 코드가 실제 수행하는 작업과 맞지 않는 이름
- 높은 인지부하 초래. LTM에서 잘못된 정보를 읽어볼수 있음.
- 잘못된 청킹으로 이어짐.
- 마틴파울러가 리팩토링 책에서 언급한 ‘코드 스멜'은 인지부하를 높힌다.
- CH 10 복잡한 문제 해결을 더 잘하려면
- 암시적 기억
- 근육 기억이 이에 해당. 예: 타이핑
- 자동화 : 아무 생각없이, 뇌의 에너지 소모가 거의 없이 작업을 실행할 수 있게 한다.
- 의도적 연습으로 암시적 기억을 개서할 수 있다.
- 명시적 기억
- 능동적으로 불러와야 하는 기억
- 예: for loop 문법
- 기존 코드를 연구하면 프로그래밍에 필요한 명시적 기억을 강화하는데 도움이 됨.
- 코드 설계 방법이 포함된 코드가 도움이 됨.
- 수학교육에서도 ‘풀이된 예제'하는 공부가 효과적이였다는 연구 결과가 있음.
- 코드 설계 방법이 포함된 코드가 도움이 됨.
- 암시적 기억
PART IV 코딩에서의 협업
- CH 11 코드를 작성하는 행위
- CDN(Cognitive Dimensions of Notation, 인지적 차원 표기법) framework에 따르면 프로그래밍의 세부 활동은 각각 여러 기억공간에 부하를 준다
- 검색 -> STM
- 이해 -> 작업 기억 공간
- 전사(transcription) -> LTM
- 증가(incrementation), 탐구(exploration) -> 세 영역 모두
- 프로그래밍 중 중단
- 프로그래밍에는 워밍업이 필요. 코드에 대한 정신 모델을 재구상하는데 시간이 걸림 -> 생산성에 악 영향
- 중단에 대처하는 기법
- 정신 모델 저장 : 문서, 주석문으로 옮겨놓기
- 미래 기억 향상 : 할 일 기록해 두기
- 하위 목표 라벨 붙이기 : 문제를 나눠서 기록
- 인지부하가 낮을 때 중단이 일어나도록 알려주는 장치 활용. (예: 플로라이트, 슬랙의 상태 표시)
- CDN(Cognitive Dimensions of Notation, 인지적 차원 표기법) framework에 따르면 프로그래밍의 세부 활동은 각각 여러 기억공간에 부하를 준다
- CH 12 대규모 시스템의 설계와 개선
- CDCB(cognitive dimensions of codebase, 코드베이스의 인지차원) : 코드베이스, 라이브러리, 프레임워크가 미치는 영향을 이해하는데 도움이 되는 CDN의 확장판
- 인지적 차원 : 오류 경향성, 일관성, 분산성, 숨겨진 의존성, 점도, 점진적 평가, 역할 표현력, 매핑 근접성, 힘든 정신 활동, 보조 표기법, 추상화, 가시성
- 설계 기동(Design maneuver) : 코드베이스에서 특정 차원을 개선하기 위해 코드베이스를 변경하는 것. 트레이드 오프가 있다.
- 오류 경향성 <-> 점도
- 잠정성 및 점진적 평가 <-> 오류 경향성
- 역할 표현력 <-> 분산성
- CDCB의 차원들은 CDN의 각 활동들을 돕거나 악형향을 끼친다.
- 예: 일관성은 검색/이해를 돕지만 전사에는 악영향
- 예: 추상화는 이해를 돕지만 탐구에는 악영향
- CDCB(cognitive dimensions of codebase, 코드베이스의 인지차원) : 코드베이스, 라이브러리, 프레임워크가 미치는 영향을 이해하는데 도움이 되는 CDN의 확장판
- CH 13 새로운 개발자 팀원의 적응 지원
- 전문가는 코드를 추상적으로 추론할 수 있지만 초보자는 세부 사항에 집중하고 이를 벗어나기 어렵다.
- 중급자도 새로운 정보를 학습할때 초급수준의 사고 방식으로 떨어질 수 있다.
- 적응지원(온보딩) 개선
- 새 팀원이 수행할 프로그래밍 활동은 한 번에 한개로 제한해야 한다.
- 새 팀원의 기억 지원
- LTM 지원 : 도메인과 기술 스택에 대한 정보 설명
- STM 지원 : STM에 부하가 적은 규모가 작고 집중할 수 있는 작업을 할당
인상깊은 단락
추천 서문
닷넷의 dateTime.AddDays(1)
vs 노다 타임의 localDate.PlusDays(1)
(감상. 닷넷의 DateTime.addDays()
는 Java의 BigDecimal.add()
와 비슷하게 메서드가 호출된 객체 내부의 상태값을 바꾼다는 착각을 유도한다.)
p30
취인 판(Qutin Fan)의 논문.
특히 ‘이 함수는 주어진 이진 트리를 중위 순회하며 프린트한다’ 같은 고수준 주석문은 코드를 청크 단위로 쪼개는 데 도움이 된다. 반면 i++; 다음에 ‘i를 1만큼 증가'같은 저수준 주석문을 넣는 것은 오히려 청킹 작업에 부담이 된다.
p43
요약하자면, 오랫동안 학습한 만큼 더 오래 기억한다. 이것은 더 많은 시간을 학습해야 한다는 것을 의미하는 것이 아니라 더 오랜 간격을 두고 학습해야 한다는 것을 의미한다.
(감상 : 벼락치기 공부를 한 내용은 잘 잊어버린다는 이야기가 있는데 위의 내용과 일맥상통한다.)
p48
우리의 기억이 서로 연결되어 있을 때 관련 기억을 찾는 것이 더 쉽다. 즉 인출 강도는 다른 기억에 연관된 기억일 때 더 높다.
기억이 저장될 때 기존 스키마타에 맞추기 위해 심지어 기억이 바뀌는 일도 가능하다.
p49
정교화는 기억하고자 하는 내용을 기존 기억과 연관 지으면서 생각하는 것을 뜻하고, 이렇게 한 결과 LTM에 이미 저장되어 있는 스키마타에 맞춰서 새로운 기억이 저장된다.
p57
물론 많은 IDE가 메서드나 함수의 정의로 손쉽게 이동할 수 있는 기능을 제공하지만 정의를 확인하는 일은 여전히 작업 기억 공간을 사용하고 외재적 인지 부하를 유발할 수 있다.
p65
상태표 활용 사례
코드를 머리로 실행해보는 과정을 트레이싱(tracing) 혹은 인지적 컴파일(cognitive compiling)이라고 한다.)
p79
앱헝가리온 표기법 vs 시스템 헝가리언 표기법.
시모니의 제안은 본질적으로 훨씬 더 의미론적이였다. 이를 오늘날에는 앱 헝가리안 표기법이라고 부른다. 앱 헝가리안 표기법에서 접두어는 단지 변수의 타입이 아닌 좀 더 구체적인 의미를 갖는다. 예를 들어 시모니는 자신의 논문에서 X의 인스턴스 개수를 나타낼 때 cX를 사용하고(따라서 cColors는 유저 인터페이스에서 컬러의 개수를 의미할 수 있다) 배열의 길이를 나타낼 때는 lCustomers와 같이 lX를 사용할 것을 제안했다.
p84
앞서 언급했듯이 프로그래머는 평균적으로 자신의 업무 시간의 60%를 코드 작성이아닌 읽는 것에 할애하는 것으로 추정된다.
p85
fMRI(기능적 자기공명영상) 처리기로 분석결과 코드를 읽을 때 언어 이해와 관련된 뇌 영역이 활성화 됨.
p87-88
워싱턴 대학교의 샤텔 프랫Chantel Prat)교수의 연구
학습률, 즉 코드 아카데미의 수업을 얼마나 빨리 마쳤는지에 대한 측도는 언어 능력이 가장 큰 요인이었다.
그림 5.4와 같이, 프로그래밍 언어를 얼마나 잘 배울 수 있는지는 인간이 자연어를 배우는 능력으로 예측 가능하다는 것을 이 연구 결과를 통해 알 수 있다.
p112
이미 살펴본 바와 같이, 개념적 기게는 코드를 실제로 실행하는 기계의 동작을 설명하기 위해 만들어졌기 때문에 몇 가지 특성은 기계와 동일하다. 예를 들어 몰리적 기계와 마찬가지로 개념적 기계는 ‘상태state'라는 개념을 가지고 있다.
p124
긍정적 전이 vs 부정적 전이
네덜란드의 컴퓨터 과학 교수이자 데이크스트라 알고리즘을 고안한 에츠허르 데이크스트라는 “정신이 손상되기” 때문에 베이직을 가르치는 것은 금지되어야 한다는 유명한 말을 했다.
p125
체스, 프로그래밍 모두 다른 일반적 지능으로 전이가 잘 되지 않음.
2장에서 우리는 아드리안 더호로트의 연구에 대해 살펴봤다. 실험 결과 무작위 설정에 대해서는 체스 전문가의 기억력이 초보자보다 나을 것이 없었다.
p126
그러나 이 섹션에서 이미 살펴본 대로 SQL에서 자바스크립트로의 원거리 전이는 일어날 가능성이 낮으며, 새로운 프로그래밍 언어 에서도 전문가 수준을 갖추려면 새로운 전략뿐만 아니라 새로운 문법도 많이 배워야한다.
p138
넷스케이프의 프로그래머 필 칼튼(Phil Karlton)은 컴퓨터 과학에는 난제가 딱 두가지 있는데, 바로 캐쉬 무효화와 이름 짓기라는 유명한 말을 했다.
p139
식별자는 타입(클래스, 인터페이스, 구조체, 대리자, 열거형), 변수, 메서드, 함수, 모듈, 라이브러리, 네임스페이스
변수 이름이 중요한 첫 번째 이유는 대부분의 코드베이스에서 읽을 내용의 상당 부분이 이름이기 때문이다. 예를 들어 약 200만줄의 코드로 구성된 이클립스 소스 코드에서 토큰의 33%, 무나의 72%가 식별자에 해당한다.
p141
코드베이스 전반에 걸쳐 유사한 객체에 동일한 단어를 사용하면 뇌가 LTM에 저장된 관련 정보를 더 쉽게 찾을 수 있다.
p143
존스 홉킨스 대학교의 돈 로리(Dawn Lawrie)의 연구
“프로그램 개발 초기에 만들어진 식별자의 품질이 계속 유지된다.” 따라서 새 프로젝트를 시작할 때는, 초기 단계에서 이름을 만드는 방식이 그 이후로도 계속 사용될 가능성이 높기 때문에 좋은 이름을 선택하는 데 특히 주의를 기울여야 한다.
p152-153
Dave Binkley의 To camelcase or under_score 논문
빙클리의 연구결과는 캐멀 케이스가 프로그래머와 비프로그래머 모두에게서 더 높은 정확도를 갖는다는 것을 보여준다. 식별자 이름이 캐멀 케이스로 작성되었을 때 올바른 옵션을 선택할 확률이 51.5% 더 높았다. 그러나 답을 식별하는 데 들어간 시간 역시 더 걸렸다. 참가자들이 캐멀 케이스로 적힌 식별자를 찾는데 0.5초가 더 걸렸다.
다양한 수준의 경험을 가진 사람들을 비교할 때, 빙클리는 캐멀 케이스에 대한 교육을 더 많이 받은 프로그래머들은 변수 이름이 캐멀 케이스로 작성된 경우 더 빨리 답을 찾는다는 것을 발견했다.
p157
더 나은 변수명에 대한 페이텔슨의 3단계 모델
페이텔슨에 따르면 이름을 선택할 때 고려해야할 주요 사항은 이름의 의도이며, 이 의도는 개체가 어떤 정보를 보유하고 있으며 무엇을 위해 사용되는지를 나타내야 한다는 것이다.
p161
마틴파울러의 코드 스멜에 대한 정리. 이 중 다시 보니 인상적인 내용
주석문 : 주석문은 그 코드가 무엇을 하는지가 아니라 왜 거기 있는지를 설명해야 한다. 미들맨 : 클래스가 자신이 하는 일은 없이 위임을 많이 사용하면 이 클래스가 굳이 존재할 이유가 있는가?
p167
Linguistic Anti-Pattern Detector (LAPD) 소개
인지부하에 대한 파스 척도(Paas scale)
p171-172
언어적 안티패턴을 가진 코드가 인지부하를 많이 유발함을 보여주는 연구결과. 안구추적장치에서 해당 코드를 사람이 가장 많이 검사한 것으로 나타났고 fNIRS(Funtional near-infrared spectroscopy, 기능적 근적외선 분광기) 장치의 결과로도 언어적 안티패턴이 있는 코드를 읽을 때 평균 산소화 혈류량이 유의미하게 증가.
p181
암시적 기억의 흥미로운 점은 암시적 기억을 충분히 훈련하면, 그것을 사용하는 데 뇌가 거의 에너지를 소모하지 않는다는 것이다.
p190
GitHub에서 탐구할 저장소 찾기
도메인이 조금이라도 익숙한 저장소를 선택하는 것이 가장 권장할 만한데, 낯선 단어와 개념으로 인한 외재적 부하 없이 프로그래밍 자체에 집중할 수 있기 때문이다.
p194
검색은 STM에 무리를 가한다. 검색 대상, 이미 탐색한 코드의 경로 및 이유, 그리고 더 심층적으로 탐색해야 할 사항을 기억해야 한다. 따라서 이런 활동을 할 때 기억의 부하를 줄이기 위해 종이나 별도의 문서에 노트를 작성하면 도움이 된다.
p197-198
파닌의 연구에 따르면, 프로그래머는 2시간 동안 중단되지 않고 업무에 집중할 수 잇는 시간이 하루에 평균 한 번 정도에 불과했다.
나카가와의 결과는 프로그램 이해 과제에서 일종의 워밍업 및 냉각 단계가 잇으며 그 중간에 가장 힘든 작업이 수행된다는 것을 시사한다.
업무가 중단된 뒤 코드 작성 작업을 다시 시작하는 데 약 25분이 소요됐다. 메서드를 작성하다가 중단되면, 프로그래머가 1분 이내에 작업을 재개할 수 있었던 경우는 10%에 불과했다.
p199
또한 참가자들은 업무를 중단해야 할 때 의미 없는 무작위 문자를 코드에 추가해 컴파일 오류를 일부러 유발했다. 파닌을 이를 장애물 경고(roadblock reminder)라고 불렀다.
(감상: 식사하기 전에 깨어지는 테스트를 만들어 놓는 것과 유사)
그러나 코드는 프로그래머의 사고 과정을 거의 설명하지 못하므로 대부분 작성자의 정신 모델을 적절하게 표현하지 못한다.
존 오스터하우스 John Osterhout은 ‘A Philosophy of Software Design’ 에서 이를 멋지게 묘사했다. “주석문의 배후에 놓은 전반적이 아이디어는, 설계자의 마음속에는 있었지만 코드로 표현할 수 없었던 정보를 포착하는 것이다.”
p201
GitHub에서 검색된 TODO 주석 1억3700만개
p204
플로라이트 ( 집중상태를 알려주는 램프) https://embrava.com/pages/flow
p209
독일 연구자 슈테판 하넨베르크(Stefan Hanenberg)의 타입시스템이 오류를 방지하는 효과에 대한 연구
p223
팀의 선임자들이 효과적으로 가르치고 설명하는 데 어려움을 겪는 이유 중 하나는 많은 경우 ‘전문가의 저주’ 때문이다. 어떤 기술을 충분히 익히고 나면, 그 기술이나 지식을 배우는 것이 얼마나 어려웠는지 잊어버린다. 따라서 새 팀원이 동시에 처리할 수 있는 새로운 작업의 수를 과대평가하게 된다.
마치며
추천자료
- 책
- 논문