Good programmer 4 - 설계하고 테스트하기

in #kr-dev7 years ago (edited)

이벤트 문제를 가지고 예를 들겠습니다.
문제는 "N 명의 리스트에서 랜덤으로 k명을 뽑아서 출력한다." 입니다.

저는 코드가 짧은 것을 좋아해서 파이선에서는 권하지 않는 1줄 코딩을 선호합니다.
왜냐하면 의미상으로 "1~m-1 range 에서 c 개를 sample 해서 sorted"
명확하기 때문입니다. 마치 영어의 복문을 읽는 것과 유사하며,
잘 이해가 되지 않는 다고 하더라도 의미를 알면 파라미터를 유추해 낼 수 있습니다.

from random import sample
(lambda m, c: sorted(sample(range(1,m+1), c)))(45, 6)


저렇게 짜면 날로먹는 것이 아니냐, 랜덤을 이용해서 소중히 정성스럽게 짜야하는것 아니냐?
날로먹는것이 맞는데, 날로먹어야 할 것은 날로 먹는 것이 정답입니다.
DIY (Do not repeat yourself)

제가 랜덤 라이브러리를 잘 몰랐을때 random 을 이용해서 짠 적이 있습니다.
시험때여서 1분이 아까웠지만, 직접 짜느라 5분여를 까먹었습니다.
끝나고 나서 shuffle, sample 과 같은 라이브러리 도구가 있다는 사실을 알고는 허무했습니다.
라이브러리를 써야 하는 이유는 사실 다른 곳에 있습니다. (DRY 로 얻을 수 있는 이익)
내가 만든 로직보다 많은 사람들이 고민해서 이미 만들어 놓은 것입니다.
더 이상 잘 짤 수 없습니다. 물론 테스트도 필요 없습니다. 믿고 쓰면 되지요.
새로운 라이브러리를 사용하는 경우라면 이리 저리 따져봐야합니다만,
shuffle 이나 sample 은 이미 오랜 시간 사용되어져 왔고 검증되었습니다.
지금 python 이나 java 에서 라이브러리 소스를 보십시오.

그럼 라이브러리를 모른다고 했을때, 어떻게 접근해야 하는지 알아 봅니다.

입출력에 따라서 흐름을 먼저 살펴봅니다.

(1. 입력) --> (2. N 에서 K 개를 뽑는다) --> (3. 출력)

두번째 함수의 꼴은 어떠한 형태가 되어야 할까요?

입력 : n, k
출력 : list

파이선이나 자바라면와 같이 list 를 쓸 수 있다면,

list random_select_from(n, k)



C 의 경우에는

int** random_select_from(int n, int k)



또는

void random_select(int n, int k, int *list)



첫번째 경우에는 리턴 되는 배열은 함수내에서 malloc 을 사용해서 리턴할 수 있습니다.
두번째는 그냥 호출부에서 list 의 크기를 k 개로 잡아서 호출하는 것입니다.
지금과 같은 경우에는 두번째 방법이 좀 더 편합니다. (** 는 거부감이 듭니다)

중요한 것은 언어에 따라서 함수의 꼴이 차이가 난다는 점이고,
C 는 그러한 면에서 유연성이 떨어집니다.

파이선 자바스크립트 루비 등의 언어는 기본적으로 리스트, 딕셔너리를 가지고 있습니다.
자바의 경우는 기본형은 아니지만 라이브러리에서 충분히 지원하니 사용법이 까다롭긴 해도 쓸만 합니다.

C 에서도 라이브러리를 쓰면 비슷하게 쓸 수 있습니만,
DRY (Do not repeat yourself : 있는 것을 또 만들지 말라)라는 말이 있지요.
인터넷 어디엔가 C 에서도 리스트와 같이 쓸 수 있도록 만든 라이브러리가 있을 겁니다. (반드시)

question1.jpg

함수의 테스트는 어떻게 하면 될까요? (유닛테스트)

list 의 모든 원소는 중복되지 않아야 하며, 갯수는 k개 (이하)여야 한다.
list 의 모든 원소는 n 보다 작거나 같아야 한다.
위 과정을 N 번 반복해서 N 번 다 통과하면 유닛테스트가 통과하는 것으로 한다.

파이선 unittest 나 자바 junit 등을 이용해서 테스트를 만들면
random_select_from 함수는 만들 수 있을 것 같습니다.

글이 좀 길어져서, 테스트와 리팩토링은 1회 더 진행하도록 하겠습니다.
감사합니다.

  1. 내가 관리할 수 있는 코드량은? https://steemit.com/kr-dev/@agile/good-programmer-1
  2. HOWTO be Professional https://steemit.com/kr-dev/@agile/good-programmer-2-howto-be-professional
  3. 최소화 하기 https://steemit.com/kr-dev/@agile/good-programmer-3
  4. 설계하고 테스트 하기
  5. 테스트와 리팩토링
Sort:  

얼마전까지 kdj님하고 같은분인줄 몰랐네요 ㅎㅎ 다음 글이 기다려집니다

agile 계정은 "글 써놓고 도망가기용" 계정입니다. ㅋㅋ

약자도 있었군요.
DRY (Do not repeat yourself )
요즘 뼈저리게 느꼈습니다.

항상 시간과 비용의 문제인것 같네요...
8:2 정도로 8의 시간동안 개발하면 2의 시간동안은 클린작업을 해야합니다.
2는 최소입니다.
라이브러리를 만들 때는 2:8 정도 되는것 같습니다. 물론 테스트도 달아야 하니까
2마저 없다면, 1주일 후에 후회가 있겠죠....

python을 시작한지 얼마 안되서 sample이라는 함수가 있는지 이 글을 보고 알았습니다. 한수 배워 가네요.

shuffle 은 대부분 있지만 sample 은 python 에서 처음 보네요...

C++에서의 STL도 유용한데, 이게 허점이랄만한 것도 있는 것 같습니다.
unsigned int로 선언되어서 음수가 불가능한 경우라던지,
의외로 시간복잡도가 O(N)이라서 반복문 안에 넣으면 실제로는 이중반복문의 시간복잡도를 가지게 되는 경우도 있다고 하더라고요.

그보다 람다식에 관해서 개인적인 의문점이 있습니다.
람다식을 작성하면 컴파일 시간이랑 동작 시간이 길어진다는 얘기가 있던데, 어느 정도인가요? (너무 애매한 질문이긴 하지만...)

람다식 쓴다고 동작시간이 길어질 것 같지는 않은데요.
함수가 여러번 쓰이는 경우 람다 함수로 만들지 않겠지요?

으음... 그렇군요. 답변 감사합니다 :)