Slide 1

Slide 1 text

Writing Correct Code @ 손코딩뇌컴파일눈디버깅 구종만 [email protected] 1 / 128

Slide 2

Slide 2 text

자기소개 퀀트 개발자 : DRW Trading Group (~'09) GETCO (~'11) Two Sigma Investments ('14~) 알고리즘 문제 해결 전략 ('11) algospot.com 운영진 ('07~) 2 / 128

Slide 3

Slide 3 text

자기소개 프로그래밍 대회 참가 : 탑코더 오픈 준우승 ('07) 구글 코드 잼 결선 ('04, '06, '08) ACM‑ICPC 결선 ('03, '04) 전문 분야 : 일단 일 벌리고 수습하느라 고통받기 모르는 것 잘 아는것처럼 얘기하기 3 / 128

Slide 4

Slide 4 text

오늘 할 이야기 좋은 프로그램을 작성하기 위한 우주적 지혜 ! 4 / 128

Slide 5

Slide 5 text

오늘의 토픽 #1 다음 중 무엇이 옳은가 ? / / K & R s t y l e f o r ( i n t i = 0 ; i < n ; + + i ) { . . . } / / B S D s t y l e f o r ( i n t i = 0 ; i < n ; + + i ) { . . . } 5 / 128

Slide 6

Slide 6 text

오늘의 토픽 #2 변수명 , 무엇으로 해야 하는가 ? c o n s t i n t a n s w e r _ t o _ l i f e _ t h e _ u n i v e r s e _ a n d _ e v e r y t h i n g = 4 2 ; c o n s t i n t A n s w e r T o L i f e T h e U n i v e r s e A n d E v e r y t h i n g = 4 2 ; c o n s t i n t g A n s w e r T o L i f e T h e U n i v e r s e A n d E v e r y t h i n g = 4 2 ; c o n s t i n t A n s w e r _ T o _ L i f e _ T h e _ U n i v e r s e _ A n d _ E v e r y t h i n g = 4 2 ; c o n s t i n t A N S W E R _ T O _ L I F E _ T H E _ U N I V E R S E _ A N D _ E V E R Y T H I N G = 4 2 ; c o n s t i n t A T L T U A E = 4 2 ; c o n s t i n t S I X _ B Y _ N I N E = 4 2 ; 6 / 128

Slide 7

Slide 7 text

오늘의 토픽 #3 탭이 옳은가 , 스페이스가 옳은가 ? 7 / 128

Slide 8

Slide 8 text

( 죄송 ) 8 / 128

Slide 9

Slide 9 text

우주적 진리는 없고요 꾸준히 맨땅에 헤딩하는 게 답입니다 9 / 128

Slide 10

Slide 10 text

진짜로 할 이야기 " 어떻게 하면 잘 동작하는 코드를 쉽게 짤 수 있을까 ?" 연습할 필요가 있긴 할까 ? 흔한 실수들은 어디에서 올까 ? 그 실수들은 어떻게 피 할까 ? 어떻게 하면 좋은 코드를 짤 수 있을까 ? 앞으로 어떻게 수련하면 될까 ? 10 / 128

Slide 11

Slide 11 text

주의 오늘 하는 얘기는 모두 저의 사견 여러분의 취향 , 상황 , 목표에 맞지 않을 수도 있음 ! 적절히 취사선택해 주세요 ^^; 11 / 128

Slide 12

Slide 12 text

왜 공부해야 하나요 ? 테스팅이 있잖아요 ! 대충 짜도 테스팅만 꼼꼼하게 하면 잘 되는 것 아닌가 요 ? 12 / 128

Slide 13

Slide 13 text

우리 마음 속 .jpg 13 / 128

Slide 14

Slide 14 text

현실 .jpg 14 / 128

Slide 15

Slide 15 text

범퍼카 프로그래밍 " 아이고 머리야 , 범퍼카라서 정말 다행이야 ! 이번엔 이쪽으로 돌려볼까 ?" " 어 , 이렇게 하니까 테스트가 실패하네 ? 이번엔 이렇게 고쳐보자 " 15 / 128

Slide 16

Slide 16 text

두 가지 문제 세상에 존재하는 모든 버그 : 모든 테스트를 통과했다 ! 테스트는 코드에 대한 이해를 대체할 수 없다 범퍼카만 운전해서 주차 실력이 늘 수 있을까 ? " 범퍼카 운전 경력만 20 년입니다 걱정마세요 !" → ... 라고 말하는 발렛 파킹 요원이 있다면 ? 16 / 128

Slide 17

Slide 17 text

17 / 128

Slide 18

Slide 18 text

두 명의 거인 18 / 128

Slide 19

Slide 19 text

피터 : 테스트는 먹는 건가 ? d e f c r o s s ( A , B ) : " C r o s s p r o d u c t o f e l e m e n t s i n A a n d e l e m e n t s i n B . " r e t u r n [ a + b f o r a i n A f o r b i n B ] d i g i t s = ' 1 2 3 4 5 6 7 8 9 ' r o w s = ' A B C D E F G H I ' c o l s = d i g i t s s q u a r e s = c r o s s ( r o w s , c o l s ) u n i t l i s t = ( [ c r o s s ( r o w s , c ) f o r c i n c o l s ] + [ c r o s s ( r , c o l s ) f o r r i n r o w s ] + [ c r o s s ( r s , c s ) f o r r s i n ( ' A B C ' , ' D E F ' , ' G H I ' ) f o r c s i n ( ' 1 2 3 ' , ' 4 5 6 ' , ' 7 8 9 ' ) ] ) . . . 19 / 128

Slide 20

Slide 20 text

피터 : 테스트도 하지 뭐 ... d e f t e s t ( ) : " A s e t o f u n i t t e s t s . " a s s e r t l e n ( s q u a r e s ) = = 8 1 a s s e r t l e n ( u n i t l i s t ) = = 2 7 a s s e r t a l l ( l e n ( u n i t s [ s ] ) = = 3 f o r s i n s q u a r e s ) a s s e r t a l l ( l e n ( p e e r s [ s ] ) = = 2 0 f o r s i n s q u a r e s ) a s s e r t u n i t s [ ' C 2 ' ] = = [ [ ' A 2 ' , ' B 2 ' , ' C 2 ' , ' D 2 ' , ' E 2 ' , ' F 2 ' , ' G 2 ' , ' H 2 ' , [ ' C 1 ' , ' C 2 ' , ' C 3 ' , ' C 4 ' , ' C 5 ' , ' C 6 ' , ' C 7 ' , ' C 8 ' , [ ' A 1 ' , ' A 2 ' , ' A 3 ' , ' B 1 ' , ' B 2 ' , ' B 3 ' , ' C 1 ' , ' C 2 ' , a s s e r t p e e r s [ ' C 2 ' ] = = s e t ( [ ' A 2 ' , ' B 2 ' , ' D 2 ' , ' E 2 ' , ' F 2 ' , ' G 2 ' , ' H 2 ' , ' I ' C 1 ' , ' C 3 ' , ' C 4 ' , ' C 5 ' , ' C 6 ' , ' C 7 ' , ' C 8 ' , ' C ' A 1 ' , ' A 3 ' , ' B 1 ' , ' B 3 ' ] ) p r i n t ' A l l t e s t s p a s s . ' 20 / 128

Slide 21

Slide 21 text

피터 : 아 200 줄이나 짰다 . 끝 ! http://norvig.com/sudopy.shtml 21 / 128

Slide 22

Slide 22 text

론 : 진짜 개발자는 테스트를 짠다 ! 22 / 128

Slide 23

Slide 23 text

론 : 자 봐 , 테스트를 시작했다 ! r e q u i r e ' t e s t / u n i t ' r e q u i r e ' s u d o k u t e s t . r b ' r e q u i r e ' p r o j e c t . r b ' c l a s s T C _ M y T e s t < T e s t : : U n i t : : T e s t C a s e d e f s e t u p e n d d e f t e s t _ h o o k u p a s s e r t _ e q u a l ( 5 , 2 + 2 ) e n d e n d 23 / 128

Slide 24

Slide 24 text

c l a s s G a m e d e f G a m e : : t e s t _ g a m e g a m e = G a m e . n e w g a m e . t e s t _ g a m e g a m e e n d d e f t e s t _ g a m e @ c e l l s = [ ] f o r i i n 0 . . 8 0 @ c e l l s . p u s h i e n d e n d d e f c e l l ( i ) @ c e l l s [ i ] e n d e n d 론 : 게임 클래스도 만들어야지 ! 24 / 128

Slide 25

Slide 25 text

일 주일 후 25 / 128

Slide 26

Slide 26 text

26 / 128

Slide 27

Slide 27 text

동작하는 기능 격자의 이 칸에 이 숫자를 넣읍시다 이 격자의 이 칸에 넣을 수 있는 숫자들은 뭔가요 ? 들어갈 수 있는 숫자가 하나만 있는 칸이 있나요 ? 게임이 끝났나요 ? ( 끝 ) 27 / 128

Slide 28

Slide 28 text

28 / 128

Slide 29

Slide 29 text

29 / 128

Slide 30

Slide 30 text

TDD 를 하지 말자는게 아닙니다 어디 가서 " 구모씨가 테스트해봐야 소용없다더라 " 하 시면 안됩니다 다만 : 테스트는 만능이 아니다 코드와 알고리즘을 이해하지 못하면 테스트도 도와 줄 수 없다 이해하기 쉽고 , 간결한 코드를 짜기 위한 꾸준한 수련 ! 어떻게 하면 더 좋은 코드를 짤 수 있나 감시하는 매의 30 / 128

Slide 31

Slide 31 text

무엇을 수련하고 무엇을 감시해야 하는가 ? 31 / 128

Slide 32

Slide 32 text

할 수 있는 실수가 너무 많다 ! ( 스택 | 자료형 | 배열 크기 |...) 오버플로우 깨진 루프 불변식 잘못된 상수 요구 조건을 잘못 이해 라이브러리 잘못 사용하기 최소 크기의 입력 / 최대 크기의 입력 잘못 처리 답이 존재하지 않는 경우 잘못 구현 .... 32 / 128

Slide 33

Slide 33 text

어떻게 이들을 피해가야 할까 ? 원포인트 레슨 : 수많은 함정들을 하나하나 공부해서 피해간다 방법론 : 함정들을 만나지 않을 수 있는 기본기를 갖춘 다 ( 현실 : 둘다 해야됨 ) 33 / 128

Slide 34

Slide 34 text

Part I: Common Pitfalls 34 / 128

Slide 35

Slide 35 text

예제 문제 : LECTURE 길이 2n 인 소문자 문자열을 길이 2 씩의 문자열로 분리한 뒤 , 정렬해 합쳐서 출력하라 . (n <= 500) abbaaccb ab ba ac cb ab < ac < ba < cb abacbacb 35 / 128

Slide 36

Slide 36 text

/ / c o d e # 1 : 1 l i n e t o f i x s t r i n g s o r t _ b i g r a m s ( c o n s t s t r i n g & s ) { v e c t o r < s t r i n g > b i g r a m s ; / / 길이 2 인 문자열들로 분리 f o r ( i n t i = 0 ; i < s . s i z e ( ) ; i + = 2 ) b i g r a m s . p u s h _ b a c k ( s . s u b s t r ( i , 2 ) ) ; f o r ( i n t i = 0 ; i < b i g r a m s . s i z e ( ) ; + + i ) { / / 삽입 정렬 i n t j = i - 1 ; s t r i n g t = b i g r a m s [ i ] ; w h i l e ( j > = 0 & & b i g r a m s [ j ] > t ) { b i g r a m s [ j + 1 ] = b i g r a m s [ j ] ; - - j ; } b i g r a m s [ j ] = t ; } s t r i n g r e t ; / / 정렬된 조각들을 결합 f o r ( c o n s t a u t o & s : b i g r a m s ) r e t + = s ; r e t u r n r e t ; } 36 / 128

Slide 37

Slide 37 text

/ / c o d e # 1 : 1 l i n e t o f i x s t r i n g s o r t _ b i g r a m s ( c o n s t s t r i n g & s ) { v e c t o r < s t r i n g > b i g r a m s ; / / 길이 2 인 문자열들로 분리 f o r ( i n t i = 0 ; i < s . s i z e ( ) ; i + = 2 ) b i g r a m s . p u s h _ b a c k ( s . s u b s t r ( i , 2 ) ) ; f o r ( i n t i = 0 ; i < b i g r a m s . s i z e ( ) ; + + i ) { / / 삽입 정렬 i n t j = i - 1 ; s t r i n g t = b i g r a m s [ i ] ; w h i l e ( j > = 0 & & b i g r a m s [ j ] > t ) { b i g r a m s [ j + 1 ] = b i g r a m s [ j ] ; - - j ; } b i g r a m s [ j ] = t ; / / 뭐가 문제? ? } s t r i n g r e t ; / / 정렬된 조각들을 결합 f o r ( c o n s t a u t o & s : b i g r a m s ) r e t + = s ; r e t u r n r e t ; } 37 / 128

Slide 38

Slide 38 text

삽입 정렬의 동작 s t r i n g t = b i g r a m s [ i ] ; 38 / 128

Slide 39

Slide 39 text

삽입 정렬의 동작 39 / 128

Slide 40

Slide 40 text

우리가 알고 있는 것 j 는 다음에 t 와 비교해야 할 원소의 위치 j + 1 은 현재 t 가 있어야 할 자리 A [ j + 2 . . i ] 는 t 보다 큰 숫자들이 포함됨 이 사실들은 반복문의 진행 내내 성립한다 : → 반복문 불변식 ! 40 / 128

Slide 41

Slide 41 text

반복문 불변식 (Loop Invariant) 각 반복문 내용이 시작할 때 , 그리고 종료할 때 성립 중간 결과가 원하는 답으로 가는 길 위에 있나 ? / / ( 1 ) 여기서 성립한다 f o r ( . . . ; . . . ; . . . ) { / / ( 2 a ) 여기서 성립한다면 s o m e t h i n g ( ) ; s o m e t h i n g _ e l s e ( ) ; / / ( 2 b ) 여기서도 성립한다 } / / ( 3 ) 여기서 성립하면 → 우리가 원하는 결과 41 / 128

Slide 42

Slide 42 text

삽입 정렬과 반복문 불변식 i n t j = i - 1 ; s t r i n g t = b i g r a m s [ i ] ; w h i l e ( j > = 0 & & b i g r a m s [ j ] > t ) { b i g r a m s [ j + 1 ] = b i g r a m s [ j ] ; - - j ; } 1. b i g r a m s [ 0 . . j ] 는 정렬되어 있다 2. b i g r a m s [ j + 2 . . i ] 는 정렬되어 있고 , t 보다 크다 42 / 128

Slide 43

Slide 43 text

/ / c o d e # 1 : f i x e d s t r i n g s o r t _ b i g r a m s ( c o n s t s t r i n g & s ) { v e c t o r < s t r i n g > b i g r a m s ; / / 길이 2 인 문자열들로 분리 f o r ( i n t i = 0 ; i < s . s i z e ( ) ; i + = 2 ) b i g r a m s . p u s h _ b a c k ( s . s u b s t r ( i , 2 ) ) ; f o r ( i n t i = 0 ; i < b i g r a m s . s i z e ( ) ; + + i ) { / / 삽입 정렬 i n t j = i - 1 ; s t r i n g t = b i g r a m s [ i ] ; w h i l e ( j > = 0 & & b i g r a m s [ j ] > t ) { b i g r a m s [ j + 1 ] = b i g r a m s [ j ] ; - - j ; } b i g r a m s [ j + 1 ] = t ; } s t r i n g r e t ; / / 정렬된 조각들을 결합 f o r ( c o n s t a u t o & s : b i g r a m s ) r e t + = s ; r e t u r n r e t ; } 43 / 128

Slide 44

Slide 44 text

교훈 : 반복문 불변식 ! 반복문을 짜기 전에 반복문이 하는 일과 내부의 변화 를 생각하기 ( 불변식을 주석으로 적어 두자 ) 44 / 128

Slide 45

Slide 45 text

/ / c o d e # 2 : 1 l i n e t o f i x s t r i n g s o r t _ b i g r a m s ( c o n s t s t r i n g & s ) { v e c t o r < c o n s t c h a r * > s u f f i x ; / / 각 위치에서 시작하는 문자열 포인터 f o r ( i n t i = 0 ; i < s . s i z e ( ) ; i + = 2 ) / / 저장 s u f f i x . p u s h _ b a c k ( s . c _ s t r ( ) + i ) ; f o r ( i n t i = 0 ; i < s u f f i x . s i z e ( ) ; + + i ) / / 선택 정렬 f o r ( i n t j = i + 1 ; j < s u f f i x . s i z e ( ) ; + + j ) i f ( s t r n c m p ( s u f f i x [ i ] , s u f f i x [ j ] , 2 ) = = 1 ) / / 첫 2 글자만 비교하자 s w a p ( s u f f i x [ i ] , s u f f i x [ j ] ) ; c h a r b u f [ 1 0 0 1 ] ; f o r ( i n t i = 0 ; i < s . s i z e ( ) / 2 ; + + i ) / / 결과를 만든다 f o r ( i n t j = 0 ; j < 2 ; + + j ) b u f [ i * 2 + j ] = s u f f i x [ i ] [ j ] ; b u f [ s . s i z e ( ) ] = 0 ; r e t u r n s t r i n g ( b u f ) ; } 45 / 128

Slide 46

Slide 46 text

/ / c o d e # 2 : 1 l i n e t o f i x s t r i n g s o r t _ b i g r a m s ( c o n s t s t r i n g & s ) { v e c t o r < c o n s t c h a r * > s u f f i x ; / / 각 위치에서 시작하는 문자열 포인터 f o r ( i n t i = 0 ; i < s . s i z e ( ) ; i + = 2 ) / / 저장 s u f f i x . p u s h _ b a c k ( s . c _ s t r ( ) + i ) ; f o r ( i n t i = 0 ; i < s u f f i x . s i z e ( ) ; + + i ) / / 선택 정렬 f o r ( i n t j = i + 1 ; j < s u f f i x . s i z e ( ) ; + + j ) i f ( s t r n c m p ( s u f f i x [ i ] , s u f f i x [ j ] , 2 ) = = 1 ) / / 첫 2 글자만 비교하자 s w a p ( s u f f i x [ i ] , s u f f i x [ j ] ) ; c h a r b u f [ 1 0 0 1 ] ; f o r ( i n t i = 0 ; i < s . s i z e ( ) / 2 ; + + i ) / / 결과를 만든다 f o r ( i n t j = 0 ; j < 2 ; + + j ) b u f [ i * 2 + j ] = s u f f i x [ i ] [ j ] ; b u f [ s . s i z e ( ) ] = 0 ; r e t u r n s t r i n g ( b u f ) ; } 46 / 128

Slide 47

Slide 47 text

man strncmp RETURN VALUES The strcmp() and strncmp() functions return an integer greater than, equal to, or less than 0, according as the string s1 is greater than, equal to, or less than the string s2. The comparison is done using unsigned characters, so that '\200' is greater than '\0'. ‑1, 0, 1 외의 값도 반환된다 ! 47 / 128

Slide 48

Slide 48 text

교훈 : Know Your Tools! ( → C++ 은 이 면에서는 헬게이트 !) 48 / 128

Slide 49

Slide 49 text

C++ Pop Quiz (1) / / 일별 종가가 주어질 때 하루 동안 일어난 최대 변화를 반환한다 i n t m a x _ p r i c e _ d i f f ( c o n s t v e c t o r < i n t > & p r i c e s ) { i n t r e t = 0 ; f o r ( i n t i = 0 ; i < p r i c e s . s i z e ( ) - 1 ; + + i ) r e t = m a x ( r e t , a b s ( p r i c e s [ i + 1 ] - p r i c e s [ i ] ) ) ; r e t u r n r e t ; } 뭐가 문제일까 ? 49 / 128

Slide 50

Slide 50 text

C++ Pop Quiz (1) / / 일별 종가가 주어질 때 하루 동안 일어난 최대 변화를 반환한다 i n t m a x _ p r i c e _ d i f f ( c o n s t v e c t o r < i n t > & p r i c e s ) { i n t r e t = 0 ; f o r ( i n t i = 0 ; i < p r i c e s . s i z e ( ) - 1 ; + + i ) r e t = m a x ( r e t , a b s ( p r i c e s [ i + 1 ] - p r i c e s [ i ] ) ) ; r e t u r n r e t ; } v e c t o r < i n t > e m p t y ; a s s e r t ( m a x _ p r i c e _ d i f f ( e m p t y ) = = 0 ) ; 런타임 오류 ! 50 / 128

Slide 51

Slide 51 text

size_t f o r ( i n t i = 0 ; i < p r i c e s . s i z e ( ) - 1 ; + + i ) Alias of one of the fundamental unsigned integer types. It is a type able to represent the size of any object in bytes: size_t is the type returned by the sizeof operator and is widely used in the standard library to represent sizes and counts. 64 비트 머신에서 대개 s i z e _ t 는 64 비트 부호 없는 정수 ! 51 / 128

Slide 52

Slide 52 text

대체 그럼 무슨 일이 ? A . s i z e ( ) = 0 A . s i z e ( ) - 1 = 2^64‑1 i < A . s i z e ( ) - 1 i 는 부호 있는 32 비트 정수 A . s i z e ( ) - 1 은 부호 없는 64 비트 정수 i 가 64 비트 부호 없는 정수로 캐스팅 ! 그런데 i 는 잘해봐야 32 비트 정수니까 비교는 항상 실패 ! 52 / 128

Slide 53

Slide 53 text

C++ Pop Quiz (1) / / 방법1 f o r ( i n t i = 0 ; i < ( i n t ) p r i c e s . s i z e ( ) - 1 ; + + i ) r e t = m a x ( r e t , a b s ( p r i c e s [ i + 1 ] - p r i c e s [ i ] ) ) ; / / 방법2 f o r ( i n t i = 0 ; i + 1 < p r i c e s . s i z e ( ) ; + + i ) r e t = m a x ( r e t , a b s ( p r i c e s [ i + 1 ] - p r i c e s [ i ] ) ) ; / / 방법3 f o r ( i n t i = 1 ; i < p r i c e s . s i z e ( ) ; + + i ) r e t = m a x ( r e t , a b s ( p r i c e s [ i - 1 ] - p r i c e s [ i ] ) ) ; 53 / 128

Slide 54

Slide 54 text

C++ Pop Quiz (2) / / 큰 정수 구현 s t r u c t B i g I n t e g e r { . . B i g I n t e g e r ( i n t x ) { . . } B i g I n t e g e r o p e r a t o r - ( c o n s t B i g I n t e g e r & r h s ) c o n s t { . . } B i g I n t e g e r o p e r a t o r ^ ( c o n s t B i g I n t e g e r & r h s ) c o n s t { . . } } ; o s t r e a m & o p e r a t o r < < ( o s t r e a m & o s , c o n s t B i g I n t e g e r & r h s ) { . . } i n t m a i n ( ) { / / l a r g e s t k n o w n m e r s e n n e p r i m e : 2 ^ 5 7 8 8 5 1 6 1 - 1 c o u t < < B i g I n t e g e r ( 2 ) ^ B i g I n t e g e r ( 5 7 8 8 5 1 6 1 ) - B i g I n t e g e r ( 1 ) < < e n d l ; } 컴파일 에러 ! 54 / 128

Slide 55

Slide 55 text

연산자 우선 순위 c o u t < < B i g I n t e g e r ( 2 ) ^ B i g I n t e g e r ( 5 7 8 8 5 1 6 1 ) - B i g I n t e g e r ( 1 ) < < e n d l ; 55 / 128

Slide 56

Slide 56 text

C++ Pop Quiz (2): Fixed? / / 큰 정수 구현 s t r u c t B i g I n t e g e r { . . B i g I n t e g e r ( i n t x ) { . . } B i g I n t e g e r o p e r a t o r - ( c o n s t B i g I n t e g e r & r h s ) c o n s t { . . } B i g I n t e g e r o p e r a t o r ^ ( c o n s t B i g I n t e g e r & r h s ) c o n s t { . . } } ; o s t r e a m & o p e r a t o r < < ( o s t r e a m & o s , c o n s t B i g I n t e g e r & r h s ) { . . } i n t m a i n ( ) { / / l a r g e s t k n o w n m e r s e n n e p r i m e : 2 ^ 5 7 8 8 5 1 6 1 - 1 c o u t < < ( B i g I n t e g e r ( 2 ) ^ B i g I n t e g e r ( 5 7 8 8 5 1 6 1 ) - B i g I n t e g e r ( 1 ) ) < < e n d l ; } 56 / 128

Slide 57

Slide 57 text

c o u t < < ( B i g I n t e g e r ( 2 ) ^ B i g I n t e g e r ( 5 7 8 8 5 1 6 1 ) - B i g I n t e g e r ( 1 ) ) < < e n d l ; 57 / 128

Slide 58

Slide 58 text

연산자 우선 순위 c o u t < < ( B i g I n t e g e r ( 2 ) ^ B i g I n t e g e r ( 5 7 8 8 5 1 6 1 ) ) - B i g I n t e g e r ( 1 ) < < e n d l ; Rule of thumb: ( 남이 ) 헷갈릴 가능성이 있다면 무조건 괄호로 감싸 라 ! 깔끔한 코드는 잠재적 오류만큼의 가치는 없다 ! 58 / 128

Slide 59

Slide 59 text

C++ Pop Quiz (3) s t r u c t I t e m ; s t r u c t P l a y e r { v e c t o r < I t e m * > i t e m s ; i n t s t r e n g t h ; / / 들 수 있는 아이템의 최대 수는 힘과 같다 P l a y e r ( i n t s ) : s t r e n g t h ( s ) , i t e m s ( s t r e n g t h , n u l l p t r ) { } } ; 59 / 128

Slide 60

Slide 60 text

C++ Pop Quiz (3) s t r u c t I t e m ; s t r u c t P l a y e r { v e c t o r < I t e m * > i t e m s ; i n t s t r e n g t h ; / / 들 수 있는 아이템의 최대 수는 힘과 같다 P l a y e r ( i n t s ) : s t r e n g t h ( s ) , i t e m s ( s t r e n g t h , n u l l p t r ) { } } ; v o i d t e s t _ p l a y e r ( ) { P l a y e r p ( 1 0 ) ; a s s e r t ( p . i t e m s . s i z e ( ) = = 1 0 ) ; / / 런타임 오류, 혹은 실패! } 60 / 128

Slide 61

Slide 61 text

초기화 리스트의 순서 s t r u c t P l a y e r { v e c t o r < I t e m * > i t e m s ; i n t s t r e n g t h ; / / 들 수 있는 아이템의 최대 수는 힘과 같다 P l a y e r ( i n t s ) : s t r e n g t h ( s ) , i t e m s ( s t r e n g t h , n u l l p t r ) { } 클래스 선언부 내의 순서대로 초기화됨 ! 초기화 리스트 내의 순서와 상관 없음 ! 61 / 128

Slide 62

Slide 62 text

C++ Pop Quiz (3) s t r u c t P l a y e r { i n t s t r e n g t h ; v e c t o r < I t e m * > i t e m s ; / / 들 수 있는 아이템의 최대 수는 힘과 같다 P l a y e r ( i n t s ) : s t r e n g t h ( s ) , i t e m s ( s t r e n g t h , n u l l p t r ) { } 혹은 P l a y e r ( i n t s ) : s t r e n g t h ( s ) , i t e m s ( s , n u l l p t r ) { } 62 / 128

Slide 63

Slide 63 text

C++ Pop Quiz (4) s t r u c t P e r s o n { s t r i n g n a m e ; v e c t o r < P e r s o n * > c h i l d r e n ; } ; v o i d c o l l e c t ( P e r s o n * p e r s o n , v e c t o r < P e r s o n * > & c o l l e c t e d ) { c o l l e c t e d . p u s h _ b a c k ( p e r s o n ) ; f o r ( a u t o c h i l d : p e r s o n - > c h i l d r e n ) c o l l e c t ( c h i l d , c o l l e c t e d ) ; } / / p e r s o n 과 그의 모든 자손을 배열에 모은다 v e c t o r < P e r s o n * > c o l l e c t _ f a m i l y _ r e c u r s i o n ( P e r s o n * p e r s o n ) { v e c t o r < P e r s o n * > c o l l e c t e d ; c o l l e c t ( p e r s o n , c o l l e c t e d ) ; r e t u r n c o l l e c t e d ; } 63 / 128

Slide 64

Slide 64 text

( 사실 이 코드는 잘 동작합니다 ) 64 / 128

Slide 65

Slide 65 text

재귀호출이 싫어요 ! s t r u c t P e r s o n { s t r i n g n a m e ; v e c t o r < P e r s o n * > c h i l d r e n ; } ; / / p e r s o n 과 그의 모든 자손을 배열에 모은다 v e c t o r < P e r s o n * > c o l l e c t _ f a m i l y ( P e r s o n * p e r s o n ) { v e c t o r < P e r s o n * > c o l l e c t e d ( 1 , p e r s o n ) ; f o r ( a u t o p : c o l l e c t e d ) f o r ( a u t o c h i l d : p - > c h i l d r e n ) c o l l e c t e d . p u s h _ b a c k ( c h i l d ) ; r e t u r n c o l l e c t e d ; } 65 / 128

Slide 66

Slide 66 text

파헤치자 f o r ( a u t o p : c o l l e c t e d ) { . . } f o r ( a u t o i t = b e g i n ( c o l l e c t e d ) ; i t ! = e n d ( c o l l e c t e d ) ; + + i t ) { P e r s o n * p = * i t ; . . } f o r ( a u t o i t = c o l l e c t e d . b e g i n ( ) ; i t ! = c o l l e c t e d . e n d ( ) ; + + i t ) { P e r s o n * p = * i t ; . . } 66 / 128

Slide 67

Slide 67 text

반복자 무효화 v e c t o r 에 원소를 추가하거나 , 지우거나 , 크기를 변경 하면 이미 존재하는 모든 반복자는 무효화될 수 있다 i t 값을 참조하면 런타임 오류가 발생할 수 있음 ! 종류에 따라 다르지만 다른 모든 컨테이너에도 반복자 무효화 규칙이 존재 See Iterator invalidation rules 67 / 128

Slide 68

Slide 68 text

무효화의 이유 v e c t o r 는 여유분을 포함한 적당히 큰 메모리를 미리 할당해 둔다 꽉 찼을 때 p u s h _ b a c k 이 들어오면 : 더 큰 메모리를 할당해서 현재 메모리 내용을 복사 ! 이전 메모리는 해제한다 그러면 기존 반복자는 해제된 메모리를 가리킴 ! 68 / 128

Slide 69

Slide 69 text

개선 가능하면 안하는게 좋습니다 s t r u c t P e r s o n { s t r i n g n a m e ; v e c t o r < P e r s o n * > c h i l d r e n ; } ; / / p e r s o n 과 그의 모든 자손을 배열에 모은다 v e c t o r < P e r s o n * > c o l l e c t _ f a m i l y ( P e r s o n * p e r s o n ) { v e c t o r < P e r s o n * > c o l l e c t e d ( 1 , p e r s o n ) ; f o r ( i n t i = 0 ; i < c o l l e c t e d . s i z e ( ) ; + + i ) f o r ( a u t o c h i l d : c o l l e c t e d [ i ] - > c h i l d r e n ) c o l l e c t e d . p u s h _ b a c k ( c h i l d ) ; r e t u r n c o l l e c t e d ; } 69 / 128

Slide 70

Slide 70 text

이대로 가면 끝이 없음 ! 오늘 밤 12 시에 집에 가야 함 ! 70 / 128

Slide 71

Slide 71 text

/ / c o d e # 3 : 2 l i n e s t o f i x s t r i n g s o r t _ b i g r a m s ( c o n s t s t r i n g & s ) { i n t n = s . s i z e ( ) ; c h a r * * b i g r a m s = ( c h a r * * ) m a l l o c ( s i z e o f ( c h a r * ) * n / 2 ) ; f o r ( i n t i = 0 ; i < n / 2 ; + + i ) { b i g r a m s [ i ] = ( c h a r * ) m a l l o c ( s i z e o f ( c h a r ) * 2 ) ; s t r n c p y ( b i g r a m s [ i ] , s . c _ s t r ( ) + i * 2 , 2 ) ; } f o r ( i n t i = 0 ; i < n / 2 ; + + i ) f o r ( i n t j = i + 1 ; j < n / 2 ; + + j ) i f ( s t r n c m p ( b i g r a m s [ i ] , b i g r a m s [ j ] , 2 ) > 0 ) s w a p ( b i g r a m s [ i ] , b i g r a m s [ j ] ) ; c h a r * b u f = ( c h a r * ) m a l l o c ( s i z e o f ( c h a r ) * 1 0 0 0 ) ; f o r ( i n t i = 0 ; i < n / 2 ; + + i ) f o r ( i n t j = 0 ; j < 2 ; + + j ) b u f [ i * 2 + j ] = b i g r a m s [ i ] [ j ] ; b u f [ n ] = 0 ; r e t u r n s t r i n g ( b u f ) ; } 71 / 128

Slide 72

Slide 72 text

문제 : 배열 크기 ! C 문자열은 NULL 로 끝나는 배열이므로 , 실제 길이보 다 용량이 1 커야 한다 c h a r * b u f = ( c h a r * ) m a l l o c ( s i z e o f ( c h a r ) * 1 0 0 0 ) ; 아래 줄은 왜 괜찮을까 ? b i g r a m s [ i ] = ( c h a r * ) m a l l o c ( s i z e o f ( c h a r ) * 2 ) ; 72 / 128

Slide 73

Slide 73 text

/ / c o d e # 3 : 2 l i n e s t o f i x s t r i n g s o r t _ b i g r a m s ( c o n s t s t r i n g & s ) { i n t n = s . s i z e ( ) ; c h a r * * b i g r a m s = ( c h a r * * ) m a l l o c ( s i z e o f ( c h a r * ) * n / 2 ) ; f o r ( i n t i = 0 ; i < n / 2 ; + + i ) { b i g r a m s [ i ] = ( c h a r * ) m a l l o c ( s i z e o f ( c h a r ) * 2 ) ; s t r n c p y ( b i g r a m s [ i ] , s . c _ s t r ( ) + i * 2 , 2 ) ; } f o r ( i n t i = 0 ; i < n / 2 ; + + i ) f o r ( i n t j = i + 1 ; j < n / 2 ; + + j ) i f ( s t r n c m p ( b i g r a m s [ i ] , b i g r a m s [ j ] , 2 ) > 0 ) s w a p ( b i g r a m s [ i ] , b i g r a m s [ j ] ) ; c h a r * b u f = ( c h a r * ) m a l l o c ( s i z e o f ( c h a r ) * 1 0 0 1 ) ; f o r ( i n t i = 0 ; i < n / 2 ; + + i ) f o r ( i n t j = 0 ; j < 2 ; + + j ) b u f [ i * 2 + j ] = b i g r a m s [ i ] [ j ] ; b u f [ n ] = 0 ; r e t u r n s t r i n g ( b u f ) ; } 73 / 128

Slide 74

Slide 74 text

진짜 문제 : 쓸데 없이 복잡한 도구 사용 ! 74 / 128

Slide 75

Slide 75 text

C 문자열이 복잡하다고 ? " 옛 선현들은 다 이걸로 코딩했어 복잡하긴 뭘 " " 진정한 개발자는 바이트 단위에서 노는거야 C++ 문 자열은 똥이야 ! 똥이라고 " "80 년대생들이 K&R C 를 알겠냐 ? 요즘 애들은 로망이 없어요 " 75 / 128

Slide 76

Slide 76 text

복잡하다 ≠ 어렵다 76 / 128

Slide 77

Slide 77 text

쉽다 vs 어렵다 : 접근성 쉽다 : 내가 이미 알고 있다 이미 내 컴퓨터에 깔려 있다 어렵다 : 학습 커브를 다시 통과해야 한다 고생해서 구해서 설치해야 한다 77 / 128

Slide 78

Slide 78 text

간결하다 vs 복잡하다 : 논리적 간결하다 : 한번에 한 가지의 일을 한다 문맥에 신경쓰지 않아도 된다 복잡하다 : 여러 개의 일이 섞여 있다 문맥에 신경써야 한다 78 / 128

Slide 79

Slide 79 text

왜 간결함을 선호해야 하는가 ? 프로그래밍은 저글링과 같다 신경써야 하는 모든 것들이 하나의 공 ! " 이 공을 던지고 싶나 ? 이 공은 사실 두개란다 " 공 하나의 가격은 비싸다 ! 나는 2 개의 공을 던지고 받을 수 있다 세계 기록 : 고작 13 개 ! 79 / 128

Slide 80

Slide 80 text

C 스타일 문자열은 왜 복잡한가 ? 추가적인 문맥을 달고 온다 ! 문자열의 최대 길이는 배열의 길이 ‑1 을 넘어갈 수 없다 strncpy 는 NULL 문자를 추가하기도 하고 , 하지 않 기도 한다 ! strncmp 만 사용하면 NULL 문자가 필요없다 ! 문자열을 사용하는 입장에서 이 문맥은 노이즈일 뿐 ! 80 / 128

Slide 81

Slide 81 text

복잡한 도구는 왜 복잡할까 ? 81 / 128

Slide 82

Slide 82 text

지인짜 문제 : 추상화가 부족하다 ! 82 / 128

Slide 83

Slide 83 text

추상화와 간결한 코드 문맥을 제거함으로써 더 높은 레벨에서 사고할 수 있 게 해준다 ! 어떤 도구를 어떻게 사용해야 하는가 ? Part II 에서 계속 83 / 128

Slide 84

Slide 84 text

/ / c o d e # 4 : 1 l i n e t o f i x s t r i n g s o r t _ b i g r a m s ( c o n s t s t r i n g & s ) { v e c t o r < s t r i n g > b i g r a m s ; f o r ( i n t i = 0 ; i < s . s i z e ( ) ; i + = 2 ) b i g r a m s . p u s h _ b a c k ( s . s u b s t r ( i , 2 ) ) ; f o r ( i n t i = 0 ; i < s . s i z e ( ) ; + + i ) { i n t j = i - 1 ; s t r i n g t = b i g r a m s [ i ] ; w h i l e ( j > = 0 & & b i g r a m s [ j ] > t ) { b i g r a m s [ j + 1 ] = b i g r a m s [ j ] ; - - j ; } b i g r a m s [ j + 1 ] = t ; } s t r i n g r e t ; f o r ( c o n s t a u t o & s : b i g r a m s ) r e t + = s ; r e t u r n r e t ; } 84 / 128

Slide 85

Slide 85 text

s t r i n g s o r t _ b i g r a m s ( c o n s t s t r i n g & s ) { v e c t o r < s t r i n g > b i g r a m s ; f o r ( i n t i = 0 ; i < s . s i z e ( ) ; i + = 2 ) b i g r a m s . p u s h _ b a c k ( s . s u b s t r ( i , 2 ) ) ; f o r ( i n t i = 0 ; i < s . s i z e ( ) ; + + i ) { i n t j = i - 1 ; s t r i n g t = b i g r a m s [ i ] ; w h i l e ( j > = 0 & & b i g r a m s [ j ] > t ) { b i g r a m s [ j + 1 ] = b i g r a m s [ j ] ; - - j ; } b i g r a m s [ j + 1 ] = t ; } s t r i n g r e t ; f o r ( c o n s t a u t o & s : b i g r a m s ) r e t + = s ; r e t u r n r e t ; } 85 / 128

Slide 86

Slide 86 text

s t r i n g s o r t _ b i g r a m s ( c o n s t s t r i n g & s ) { v e c t o r < s t r i n g > b i g r a m s ; f o r ( i n t i = 0 ; i < s . s i z e ( ) ; i + = 2 ) b i g r a m s . p u s h _ b a c k ( s . s u b s t r ( i , 2 ) ) ; f o r ( i n t i = 0 ; i < b i g r a m s . s i z e ( ) ; + + i ) { i n t j = i - 1 ; s t r i n g t = b i g r a m s [ i ] ; w h i l e ( j > = 0 & & b i g r a m s [ j ] > t ) { b i g r a m s [ j + 1 ] = b i g r a m s [ j ] ; - - j ; } b i g r a m s [ j + 1 ] = t ; } s t r i n g r e t ; f o r ( c o n s t a u t o & s : b i g r a m s ) r e t + = s ; r e t u r n r e t ; } 86 / 128

Slide 87

Slide 87 text

87 / 128

Slide 88

Slide 88 text

정줄놓 앞에 장사 없다 어떠한 원칙과 기법도 신중하고 주의깊은 프로그래머 의 대체재가 될 수 없다 ! 은총알을 항상 경계하자 ! 88 / 128

Slide 89

Slide 89 text

이 외의 중요한 오류 클래스들 물리적 기계의 한계에서 오는 문제 변수형 오버플로우 스택 오버플로우 실수 연산의 정확성 문제 ( 여기도 지뢰밭 ) http://floating‑point‑gui.de/ TopCoder Tutorial Part 1, Part 2 89 / 128

Slide 90

Slide 90 text

휴식 ! 90 / 128

Slide 91

Slide 91 text

Part II: Writing Good Code 91 / 128

Slide 92

Slide 92 text

Disclaimer 이 파트는 더더욱 주관적인 취향의 영역 모두에게 자신의 기준이 있음 오늘의 이야기도 우주적 기준이 아님 미시적 관점 (X) 좋은 소프트웨어 아키텍처 , 디자인 패턴 , 소프 트웨어 스택 (O) 어떻게 간결한 함수를 작성할까 ? 어떻게 이 클 래스를 잘 만들까 ? 92 / 128

Slide 93

Slide 93 text

간결성 revisited 한 번에 하나의 일만 하기 문맥의 수로 결정된다 혹이 달려오는 도구는 쓰지 말자 다양한 단계에서의 간결성 도구의 선택 함수 하나 클래스 구조 설계 93 / 128

Slide 94

Slide 94 text

같은 값이면 추상화 ! 복잡 간결 i n t A [ M A X _ N ] ; v e c t o r < i n t > A ; / / 정렬한 상태로 유지한다 i n t A [ M A X _ N ] ; s e t < i n t > A ; / / 모든 P e r s o n 에 대해 P e r s o n p e o p l e [ M A X _ N ] ; f o r ( i n t i = 0 ; i < n ; + + i ) { f o r ( a u t o p e r s o n : p e o p l e ) / / 최대값을 구한다 f o r ( i n t i = 0 ; i < n ; + + i ) { . . } * m a x _ e l e m e n t ( b e g i n ( A ) , e n d ( A ) ) / / 두 P e r s o n 을 비교 s t r u c t C o m p a r a t o r { . . } ; [ ] ( c o n s t P e r s o n & a , c o n s t P e r s o n & b ) { . . } i n t x [ N ] , y [ N ] , z [ N ] ; v e c t o r < P o i n t > p o i n t s ; 94 / 128

Slide 95

Slide 95 text

지옥에서 온 코드 .cpp s t r i n g c o m p l e x i t y _ h e l l ( c o n s t s t r i n g & s ) { c h a r b u f [ 1 0 2 4 ] , t m p [ 1 0 2 4 ] ; s t r c p y ( b u f , s . c _ s t r ( ) ) ; f o r ( i n t i = 0 ; i < s . s i z e ( ) ; i + = 2 ) f o r ( i n t j = i + 2 ; j < s . s i z e ( ) ; j + = 2 ) { i f ( b u f [ i ] > b u f [ j ] | | ( b u f [ i ] = = b u f [ j ] & & b u f [ i + 1 ] > b u f [ j + 1 ] ) ) { s t r n c p y ( t m p , & b u f [ i ] , 2 ) ; s t r n c p y ( & b u f [ i ] , & b u f [ j ] , 2 ) ; s t r n c p y ( & b u f [ j ] , t m p , 2 ) ; } } r e t u r n s t r i n g ( b u f ) ; } 95 / 128

Slide 96

Slide 96 text

어느 쪽 ? 96 / 128

Slide 97

Slide 97 text

개선 s t r i n g s o r t _ b i g r a m s ( c o n s t s t r i n g & s ) { v e c t o r < s t r i n g > b i g r a m s ; f o r ( i n t i = 0 ; i < s . s i z e ( ) ; i + = 2 ) b i g r a m s . p u s h _ b a c k ( s . s u b s t r ( i , 2 ) ) ; s o r t ( b i g r a m s . b e g i n ( ) , b i g r a m s . e n d ( ) ) ; s t r i n g r e t ; f o r ( c o n s t a u t o & b : b i g r a m s ) r e t + = b ; r e t u r n r e t ; } 97 / 128

Slide 98

Slide 98 text

Mutable vs Immutable C 의 문자열 : 문자를 바꾸고 , 길이를 늘리고 , 줄일 수 있다 ! c h a r b u f [ 6 4 ] ; s t r c p y ( b u f , " H e l l o W o r l d ! " ) ; b u f [ 4 ] = ' ' ; Python 의 문자열 : 새 문자열을 얻는다 ! h e l l o = ' H e l l o W o r l d ! ' h e l l = h e l l o [ : 4 ] + ' ' + h e l l o [ 5 : ] 98 / 128

Slide 99

Slide 99 text

변수의 개념 Immutable: 특정 값에 이름을 붙인다 조작하면 새로운 값을 얻는다 Mutable: 값을 담을 수 있는 메모리 " 조각 " 에 이름을 붙인다 메모리에 새 값을 써넣으면 모든 사람들의 값이 바 뀐다 ! 99 / 128

Slide 100

Slide 100 text

변경 가능한 값은 추가 문맥을 가져온다 100 / 128

Slide 101

Slide 101 text

Immutable 프로그래밍 모든 함수는 " 이전의 값을 이용해 새 값을 계산한 다 " 의 연속 이전의 값이 바뀌면서 이전 부분과 다음 부분이 섞일 여지를 주지 않는다 파이프라인 ‑ 지향 프로그래밍 101 / 128

Slide 102

Slide 102 text

고려할 점 : 오버헤드 데이터를 생성하고 바로 처리하면 더 빠를 수는 있다 ! 대부분의 경우 주의깊은 알고리즘과 자료 구조 선택으 로 극복 지원되는 경우에는 lazy evaluation 을 적극 활용 102 / 128

Slide 103

Slide 103 text

보다 고수준에서의 간결성 SRP (Single Responsibility Principle) 객체간의 직접적 의존성을 최대한 줄인다 남아 있는 직접적 의존성 ‑ 추상화하라 ! 필요한 문맥만 남기고 없앤다 간결하다 ≠ 컴포넌트의 개수가 적다 가능한 상태의 수가 적다 Stateless 시스템을 향해 ! 103 / 128

Slide 104

Slide 104 text

예 : 온라인 채점 시스템 1. 새 소스 코드가 제출됨 2. 해당 문제가 채점 준비된 상태인지 확인 3. 파일서버에서 채점 데이터 다운로드 4. 샌드박스 생성해서 프로그램 컴파일 및 실행 5. 채점 결과 확인 104 / 128

Slide 105

Slide 105 text

Initial design 105 / 128

Slide 106

Slide 106 text

106 / 128

Slide 107

Slide 107 text

대체 뭐가 문제야 ? 엄청 많은 직접적 의존성 ! Actor 들은 모두 상태를 잔뜩 쥐고 있다 문제들 : 재시도는 어떻게 하지 ? 한 Actor 가 실패하면 전체 시스템이 멈춘다 Actor 간 리소스 공유 107 / 128

Slide 108

Slide 108 text

Task Queue 108 / 128

Slide 109

Slide 109 text

왜 더 나은가 ? 컴포넌트도 , 의존성도 없다 각 작업에는 아무런 상태가 없다 한 작업 실패가 다른 작업 실패에 영향을 주지 않음 투명한 재시도 정책 각 액터 단위로 관리하지 않고 태스크 큐 자체에서 관리 109 / 128

Slide 110

Slide 110 text

요점 정리 문맥의 수를 줄이는 것이 최우선 적절한 도구 선택 전후 코드간 의존성 줄이기 : " 파이프라인 " 직접적 의존성 줄이기 추상화 의존성 만들기 110 / 128

Slide 111

Slide 111 text

이런 코드를 보셨나요 ? s t r u c t P l a y e r { s t r i n g n a m e ; } ; s t r u c t T e a m { v e c t o r < P l a y e r > m e m b e r s ; } ; / / 팀 내에 주어진 이름을 가진 사람이 있는가? b o o l h a s _ m e m b e r ( T e a m * t e a m , c o n s t s t r i n g & n a m e ) { b o o l f o u n d = f a l s e ; i f ( t e a m ! = n u l l p t r ) { i n t i ; f o r ( i = 0 ; i < t e a m - > m e m b e r s . s i z e ( ) ; + + i ) { i f ( t e a m - > m e m b e r s [ i ] . n a m e = = n a m e ) { b r e a k ; } } f o u n d = i < t e a m - > m e m b e r s . s i z e ( ) ; } r e t u r n f o u n d ; } 111 / 128

Slide 112

Slide 112 text

이런 코드를 보셨나요 ? / / A 에서 세 원소를 골라 합이 s 가 되도록 할 수 있나? b o o l f i n d 3 ( c o n s t v e c t o r < i n t > & A , i n t s ) { b o o l f o u n d = f a l s e ; f o r ( i n t i = 0 ; i < A . s i z e ( ) ; + + i ) { f o r ( i n t j = i + 1 ; j < A . s i z e ( ) ; + + j ) { f o r ( i n t k = j + 1 ; k < A . s i z e ( ) ; + + k ) { i f ( A [ i ] + A [ j ] + A [ k ] = = s ) { f o u n d = t r u e ; b r e a k ; } } i f ( f o u n d ) b r e a k ; } i f ( f o u n d ) b r e a k ; } r e t u r n f o u n d ; 112 / 128

Slide 113

Slide 113 text

이런 코드를 보셨나요 ? s t r u c t P l a y e r { s t r i n g n a m e ; i n t s t r , d e x , m a n a ; } ; b o o l o p e r a t o r < ( c o n s t P l a y e r & a , c o n s t P l a y e r & b ) { i f ( a . s t r = = b . s t r ) { i f ( a . d e x = = b . d e x ) { i f ( a . m a n a = = b . m a n a ) { r e t u r n a . n a m e < b . n a m e ; } r e t u r n a . m a n a < b . m a n a ; } r e t u r n a . d e x < b . d e x ; } r e t u r n a . s t r < b . s t r ; } 113 / 128

Slide 114

Slide 114 text

깊은 중첩 (nesting) if 안에 for 안에 if 안에 for.. 답을 찾았는지 기록하기 위한 북키핑 변수들 루프 밖에서 선언된 카운터 114 / 128

Slide 115

Slide 115 text

다시 짜기 s t r u c t P l a y e r { s t r i n g n a m e ; } ; s t r u c t T e a m { v e c t o r < P l a y e r > m e m b e r s ; } ; / / 팀 내에 주어진 이름을 가진 사람이 있는가? b o o l h a s _ m e m b e r _ r e w r i t e ( T e a m * t e a m , c o n s t s t r i n g & n a m e ) { i f ( ! t e a m ) r e t u r n f a l s e ; f o r ( c o n s t a u t o & m e m b e r : t e a m - > m e m b e r s ) i f ( m e m b e r . n a m e = = n a m e ) r e t u r n t r u e ; r e t u r n f a l s e ; } 115 / 128

Slide 116

Slide 116 text

다시 짜기 / / A 에서 세 원소를 골라 합이 s 가 되도록 할 수 있나? b o o l f i n d 3 _ r e w r i t e ( c o n s t v e c t o r < i n t > & A , i n t s ) { f o r ( i n t i = 0 ; i < A . s i z e ( ) ; + + i ) f o r ( i n t j = i + 1 ; j < A . s i z e ( ) ; + + j ) f o r ( i n t k = j + 1 ; k < A . s i z e ( ) ; + + k ) i f ( A [ i ] + A [ j ] + A [ k ] = = s ) r e t u r n t r u e ; r e t u r n f a l s e ; } 116 / 128

Slide 117

Slide 117 text

다시 짜기 s t r u c t P l a y e r { s t r i n g n a m e ; i n t s t r , d e x , m a n a ; } ; b o o l o p e r a t o r < ( c o n s t P l a y e r & a , c o n s t P l a y e r & b ) { i f ( a . s t r ! = b . s t r ) r e t u r n a . s t r < b . s t r ; i f ( a . d e x ! = b . d e x ) r e t u r n a . d e x < b . d e x ; i f ( a . m a n a ! = b . m a n a ) r e t u r n a . m a n a < b . m a n a ; r e t u r n a . n a m e < b . n a m e ; } 117 / 128

Slide 118

Slide 118 text

Return early " 하나의 return 문 ": 파스칼 시절의 유물 언제 반환할까 ? 예외 상황 발생 반환값이 정해짐 재귀호출시의 기저사례 코드를 첫줄에서 아래줄까지 쭉 읽을 수 있게 한다 각 중첩은 새로운 문맥을 만든다 ! 118 / 128

Slide 119

Slide 119 text

Design by Contract Design by contract (DbC), also known as contract programming, programming by contract and design‑by‑contract programming, is an approach for designing software. It prescribes that software designers should define formal, precise and verifiable interface specifications for software components, which extend the ordinary definition of abstract data types with preconditions, postconditions and invariants. Wikipedia 119 / 128

Slide 120

Slide 120 text

머릿속에서 계약하기 머릿속에서 , 혹은 주석으로 : 이 함수는 무엇을 가정할까 ? 이 함수의 결과는 무엇일까 ? 머릿속 시나리오 쓰려면 함수가 간결해야 한다 ! 함수의 처음과 끝부터 작성하기 120 / 128

Slide 121

Slide 121 text

선언적 프로그래밍 " 무엇을 "/" 어떻게 " 분리하기 SQL/regexp 의 생산성 ! 직접 다 만들어 쓸 수는 없어도 유용한 생각 도구 ! 121 / 128

Slide 122

Slide 122 text

map d e f d o u b l e _ e l e m e n t s ( A ) : B = [ ] f o r i i n x r a n g e ( l e n ( A ) ) : B . a p p e n d ( A [ i ] * 2 ) r e t u r n B d e f d o u b l e _ e l e m e n t s 2 ( A ) : r e t u r n m a p ( l a m b d a x : x * 2 , A ) 122 / 128

Slide 123

Slide 123 text

Closing Remarks 123 / 128

Slide 124

Slide 124 text

수련의 방법 짧은 코드 여러개 짜기 하비 프로젝트 온라인 채점 시스템 , 프로젝트 오일러 실패 기록하기 , 포스트모템 다양한 수준의 추상화 , 도구를 사용해 보기 다양한 프로그래밍 패러다임 124 / 128

Slide 125

Slide 125 text

마지막으로 드리고 싶은 말씀 125 / 128

Slide 126

Slide 126 text

매의 눈 126 / 128

Slide 127

Slide 127 text

Talk Inspired By: 생각하는 프로그래밍 ( 인사이트 ) Beautiful Code ( 한빛미디어 ) http://iq0.com/notes/deep.nesting.html Rich Hickey Simple Made Easy Value of Values 127 / 128

Slide 128

Slide 128 text

감사합니다 128 / 128