옥수수와 식빵 그리고 코딩

2주차 회고 본문

카테고리 없음

2주차 회고

옥식 2023. 11. 2. 20:37

 

업보업보 빔의 연속이었던 2주차! 회고를 시작해모겠습니다.

 

일단 1주차 코수타(코치와의 수다 타임)에서 충격적이었던 부분.

이...과제가... 하루에 두사간 정도만 투자해서 해결하라고 만든.. 문제였다고요????

믿을수 없는 현실에 눈물이 차올라서 고갤 들어.... 흐르지 못하게 또 활짝 웃어....

난.. 1주일 내내 9 to 24으로 매달려서 해결했는데..!

하지만 어쩌겠어요. 이렇게라도 문제를 해결했다는 것에 만족!하고 다시 심기일전해서 2주차를 시작했습니다.

 

이번 2주차에서는 지난 1주차 코드리뷰에서 많은 분들이 주셨던 피드백과 우테코에서 준 공통 피드백을 반영하기 위해 노력했습니다.

 

1. 기능 명세서 작성

지난번에는 냅다! 코드작성부터 시작했지만 이번에는 차근차근 readme 작성부터 시작하겠다는 마음으로! 디스코드의 '펭구스'님이 공유해 주신 기능명세서를 차근차근 작성해 보았다. (글에 쓰는 것을 허락해주신 펭구스님께 감사의 인사를 올립니다.)

https://velog.io/@pengoose_dev/프리코스-글쓰기-1-기능명세서

 

[프리코스 길잡이 #1] 기능명세서 그리고 커밋

기능명세서가 뭐에요

velog.io

이 글을 보면 붕어빵이 먹고 싶어집니다. 그래서 먼저 붕어빵 사먹고...

그런데 요즘 붕어 가격 왜이런가요..? 천원에 세마리 아니었냐고... 붕어들 왤케 비싸..! 

 

차분하게 기능 명세서를 작성해 봅니다.

 

  • 어떤 기능 필요? (기능 목록, 기능단위로 커밋하도록)
    1. 자동차 이름 입력. 단, 자동차 이름은 (,)를 기준으로 구분, 다섯글자 이하만 가능, 이름 중복 불가
    2. 자동차는 진진 or 멈춤을 n회 동안 한다.
    3. 사용자는 몇회의 이동할것인지 입력해야. (n회)
    4. 전진 : 4~9, 후진 : 0~3
    5. 경기 종료 후 우승자 발표(출력), 우승자는 한명 이상 가능(,)로 구분
    6. 입력이 잘못된 경우 throw로 예외발생
    7. 실행 결과는 시도횟수만큼 출력됨. (과정이 전부 출력됨)
    8. 단독 우승자 출력 시 (,) 출력 x
  • 입력 관련 함수
    • 자동자 이름 입력
    • 몇회 이동 할건지 입력
    • [ ] 입력이 잘못된 경우 throw예외 발생
  • 자동차 관련 함수
    • [ ] 이름은 (,)단위로 구분, 단 길이 5 이내.
    • (n)회 입력에 따라 전진 or 멈춤
    • 각 회마다 움직임 조건 : 0~9사이 랜덤값 구한 후 0~3이면 멈춤, 4~9면 전진
  • 출력 관련 함수
    • 게임을 완료한 후( = 모든 횟수를 마친 후) 결과( = 우승자)를 발표한다
    • 우승자는 한명이상일 수 있다. 여러명일 경우 (,)이용해서 구분. 단, 한 명일 경우 (,)가 붙으면 안된다.
    • 실행결과는 시도 횟수만큼 출력한다.
    • 각 경주 과정을 모두 출력한다.
    • 공동 우승자의 경우 출력 순서는 입력 순수대로 출력한다.
  • 예외 상황
    • [입력에서]
    • 공백만 있는 경우
    • 한 대 이하의 이름이 입력된 경우
    • 이름길이가 1미만, 5초과 인 경우 이름이 중복인 경우
    • 횟수 입력에 숫자가 아닌 것이 들어온 경우

2. 코드 작성

먼저 노션에 작성한 기능명세서를 바탕으로 체크리스트를 만들고!!!!!

하나씩 지워갈 때 쾌감..!

자동차 이름 입력 - 유효성 판단 함수 -> 정상작동 테스트

실행 반복 횟후 입력 - 유효성 판단 함수 -> 정상 작동 테스트

 

이 두가지를 마친 후

움직임 관련 함수를 만들었다.

 

솔직히 위 두가지는 유효성 판단을 할 때도 1주차랑 비슷해서 큰 어려움 없이 넘어가서 내가 이렇게 실력이 늘었다니..!라는 생각에 도취될 때 쯤 난관이 찾아왔다.

 

움직임 관련 함수를 한번만 출력하는건 가능했는데 이걸 반복적으로..? 에..?

단순하게 생각했는데 뭔가 단순하지 않았다....

 

한번 출력은 가능한데 이걸 앞에 했던 결과를 기억해서 그 위에 결과를 덧붙여야...? 에?

그때부터 시작된 짱구 굴리기.

그러다가 발견된 해법!

 

바로 배열에 값 저장하기!!

첫번째 결과를 [결과 배열]에 저장하고, 두번째는 첫번째 결과 += 두번째 결과 그리고 print!

이렇게 하면 완벽하게 난관을 뚫어나갈 수 있다!

 

하지만 여기서 문제가 있었음.

[결과배열]을 만들 때 그냥 냅다 빈 배열 [] 로 생성해 버리면 출력결과에 undefined문구가 같이 출력 되는 것.

왜냐면 빈 배열을 생성하면 배열 안에는 진짜 비어있기때문에 아무것도 정의되어 있다. 그런데 거기에 = 로 초기화를 시켜주는게 아니라 += 연산자로 뒤에 덧붙여 주니 undefinde + 결과값 이런게 계속 출력 되는 것이다.

 

그럼 빈 배열이 아닌 공백문자를 각 자동차 이름 수만큼 가지고 있는 배열이 필요한데 그걸 그때마다 수정할 수도 없고.. 어쩌지..하다가

자동차 배열을 복제하고 그 배열을 공백문자로 초기화 하면 되겠다는 생각..!으로 해결했다.

printEachProcess(car, times) {
    let forwordArry = [...car];
    forwordArry.fill('');

    for (let i = 0; i < times; i++) {
      this.driveOneCar(car, forwordArry);
      Console.print("\n");
    }

    return forwordArry;
  }

  driveOneCar(car, forwordArry) {
    // for (let i = 0; i < car.length ; i++) {
    //   forwordArry[i] += this.forwordOrStop(); //foreach도 이렇게 넣으면 되는거 아닐까
    //   Console.print(`${car[i]} : ${forwordArry[i]}`);
    // }
    car.forEach((name, index) => {
      forwordArry[index] += this.forwordOrStop();
      Console.print(`${name} : ${forwordArry[index]}`);
    })

    return forwordArry;
  }

 

그리고 코드리뷰에서 피드백 받았던 for문을 forEach함수로 바꾸기! 는 처음부터 하니까 진짜 너무 어려워서 일단 for문으로 만들고나서 수정하는 방법으로 만들어 봤다.

이제 약간 알듯도 하다. forEach! 이제 약간은 알겠어..!

 

그리고 또 하나의 난관

if (4 <= goStop <= 9) {
      marker = '-';
    }

이 코드의 문제점은 무엇일까요?

 

정답!

if (4 <= goStop && goStop <= 9) {
      marker = '-';
    }

이렇게 수정해야 합니다!

 

파이썬으로 코딩을 시작한 사람의 비애..! 저 문제 찾는데 30분 넘게 걸렸따.

 

여기까지 만들면 


경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)
a,b,c,d
시도할 횟수는 몇 회인가요?
5


a : -
b : -
c : 
d : -


a : --
b : --
c : 
d : --


a : ---
b : --
c : 
d : ---


a : ---
b : --
c : -
d : ----


a : ----
b : ---
c : --
d : ----

이런 결과물이 출력된다.

 

이제 진짜 거의 다 했다고  생각했는데! 마지막 최종 우승자 출력하는건 별거 아닐 거라고 생각했는데!!!!

생각보다 그렇지 않았따...

 

우승자를 어떻게 가려낼 것인가?

처음 생각

결과값을 배열에 담을 때 마다 직진을 하면 +1을 시켜서 마지막에 결과 출력하기.

지금 구현하라면 할 수 있는데 이거 작성할 때는 도무지 작성 방법이 생각이 안 났다.

class App {
    forwordOrStop(count) {
        let randomnum = Number(MissionUtils.Random.pickNumberInRange(0, 9));
        let marker = '';
        if (4 <= randomnum && randomnum <= 9) {
          marker = '-';
          count += 1;
        } 
    
        return marker;
      }
    
    printEachProcess(car, times) {
        let forwordArry = [...car];
        forwordArry.fill('');
        let countForwrd = [...car];
        countForwrd.fill(0);

        for (let i = 0; i < times; i++) {
        this.driveOneCar(car, forwordArry, countForwrd);
        Console.print("\n");
        }

        return forwordArry;
    }

    driveOneCar(car, forwordArry, countForwrd) {
        // for (let i = 0; i < car.length ; i++) {
        //   forwordArry[i] += this.forwordOrStop(); //foreach도 이렇게 넣으면 되는거 아닐까
        //   Console.print(`${car[i]} : ${forwordArry[i]}`);
        // }
        car.forEach((name, index) => {
        forwordArry[index] += this.forwordOrStop(countForwrd[index]);
        Console.print(`${name} : ${forwordArry[index]}`);
        })

        return forwordArry;
    }
}

지금 다시 생각해 보니까 이런 식으로 구현하면 될 듯 함.

,,, 안됨..! return을 두개를 못하니까...

 

안되나..? 찾아보니 배열이나 객체 형태로 반환가면 가능하다고 함.

그래서 다시 한번 수정 해 봤다.

 

 printEachProcess(car, times) {
    let forwordArry = [...car];
    forwordArry.fill('');
    let countForwrd = [...car];
    countForwrd.fill(0);

    for (let i = 0; i < times; i++) {
    this.driveOneCar(car, forwordArry, countForwrd);
    Console.print("\n");
    }

    return countForwrd;
  }

  driveOneCar(car, forwordArry, countForwrd) {
    // for (let i = 0; i < car.length ; i++) {
    //   forwordArry[i] += this.forwordOrStop(); //foreach도 이렇게 넣으면 되는거 아닐까
    //   Console.print(`${car[i]} : ${forwordArry[i]}`);
    // }
    car.forEach((name, index) => {
      let result = this.forwordOrStop(countForwrd[index]);
      forwordArry[index] += result.marker;
      countForwrd[index] = result.count;
  
    Console.print(`${name} : ${forwordArry[index]}`);
    })

    return countForwrd;
  }

  resultOfWinner(car, countForwrd) {
    let forWinnerCarIndex = [];
    let maximum = Math.max(...countForwrd);
    countForwrd.forEach((result, index) => {
       if (result === maximum) {
        forWinnerCarIndex.push(index);
        }
      })

    let finerWiner = [];
    for (let i = 0; i < forWinnerCarIndex.length; i++) {
      finerWiner.push(car[forWinnerCarIndex[i]]);
    }

    return finerWiner;

}

잘 작동 된다!

하지만 생각을 해 보니 마지막에 길이만 계산하면 되는 첫번째 코드가 더 효율적인 것 같아 제출은 처음에 만든 것으로 하기로 함.

 

아오 피곤하다.

 

아 처음 코드는

resultOfWinner(car, forwordArry) { // printEachProcess(의 마지막)받음.
   
    let winner = [];
    forwordArry.forEach(result => {
      winner.push(result.length);
    });

    let forWinnerCarIndex = [];
    let maximum = Math.max(...winner);

    winner.forEach((result, index) => {
      if (result === maximum) {
        forWinnerCarIndex.push(index);
      }
    })
 
    let finerWiner = [];
    for (let i = 0; i < forWinnerCarIndex.length; i++) {
      finerWiner.push(car[forWinnerCarIndex[i]]);
    }

    return finerWiner;
  }

이렇게 됨.

 

countForword를 못 받은 대신 각 결과의 길이를 계산해서 결과를 출력하는 방식으로 만들었다.

 

이번 코드 짜면서 신경쓴 점들.

1.  매직넘버 안 쓰려고 많이 노력함.

매직넘버 관련 링크!

https://stackoverflow.com/questions/47882/what-are-magic-numbers-and-why-do-some-consider-them-bad

 

What are magic numbers and why do some consider them bad?

What is a magic number? Why do many programmers advise that they be avoided?

stackoverflow.com

2. for문 줄이려고 노력함.

하지만..한번은 썼다... 적재적소에 활용하면 되는거 아닐까?라고 생각합니다.

그래도 forEach문을 꽤 이해할 수 있게 된 것 같아서 만족합니다.

 

3. 기능별 함수 분리

원래는 파일을 분리하고 싶었지만. 모듈화! 모르겠네요! 공부하고 다시 적용하는 걸로. 그래서 지금은 현재에 최선을 다 하자는 마음으로 함수라도 깔끔하게 분리했씁니다.

 

 

 

그리고 이번 과제에서 또 하나의 주제였던 jest!

..나의 미뤄놓은 업보...

 

그리고 async와 await (aka 비동기, promise)... 내가 아는 프로미스는 프로미스 나인밖에 없는데... 

이건 아직 제가 뭘 작성할 그건 아닌거 같고.. 다른분들이 작성한 블로그를 엄청 열심히 보는 중입니다.

봐도봐도 새로워.. 짜릿하진 않아... 깨달음을 얻으면 짜릿할 것 같은데.. 

 

일단 비동기 함수는 

https://velog.io/@rhemddjwhfla12/javascript-async-await-%EC%9D%B4-%EB%AD%98%EA%B9%8C%EC%9A%94-%EB%8F%99%EA%B8%B0%EC%99%80-%EB%B9%84%EB%8F%99%EA%B8%B0

 

[javascript] async & await 이 뭘까요?? (동기와 비동기)

동기와 비동기에 대해서 영혼까지 털어서 정리해보았습니다...

velog.io

여기에서 최대한의 깨달음을 얻었다. 이해는 못했지만 어찌어찌 사용은 하고 있는 상태에서 계속 공부하니까 더 빠르게 이해되는 것 같다.

역시 인생은 실전인가 봄.

 

jest는... 최대한 이해한 범위에서는 함수단위로 밖에 사용이 불가능할 것 같아 기능단위로 분리한 각 함수가 잘 작동하는지로 테스트 코드를 작성했다.

단순무식하지만..! 어쨌든 본래의 기능을 수행한다..! 얼레벌레 굴러가는 나의 코드... 과연 괜찮은 것인가?

 

Comments