[작년 문제 풀어보기] 5기 최종 코딩테스트 피드백

별의개발자커비·2023년 10월 8일
1

우테코 도전기

목록 보기
13/37
post-thumbnail

📝 내 코드 피드백

1. 길이가 여유롭다면 변수화

  • 반영
    : 메소드 길이가 10을 넘어가지 않기 때문에 추가해주는 게 좋은 것 같다!

2. 객체화, get 제거

  • 반영 1
    일단 시간이 부족해서 못했던 players 객체화, recommand의 util화를 했고, 그러면서 getWeekMenus도 util에 있기보다는 Players 로 이동시켰다. 그러면 getPlayer를 쓰지 않을 수 있었다.

  • 반영 2
    get 문제들을 해결하기 위해 Players, RecommendCategories에 각 get이 필요했던 메소드들을 분리해줬다.

3. 메소드 이동으로 get 제거

참고: enum 전체 name 반환

https://knight76.tistory.com/entry/enum-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EB%A6%AC%EC%8A%A4%ED%8A%B8list%EB%A1%9C-%EC%96%BB%EA%B8%B0

  • 반영
    랜덤 카테고리를 생성하는 메소드를 enum으로 넘겨줬다. get 제거!

4. domain - request 의존성 제거

  • 반영
    바로쓰면 안된다는 게 사실 아직 완전히 이해가지는 않지만 느낌만 알겠다. 일단 의존성을 풀어서 수정!

5. ☑️ 출력 메소드 분리

6. 패키지 분리

  • 반영
    패키지도 안 분리하고 올렸었구나...ㅎ 분리 완료!

7. 리터럴 값 상수화

  • 반영
    일단 리터럴 값이 뭔지를 몰라서 찾아봤다.그리고 메소드 추출 완료!

리터럴 값 vs 상수

본문 발췌

피드백 반영 ver. pr 링크

https://github.com/woowacourse-precourse/java-menu/pull/214

🔎 스터디원 코드 분석

0. 궁금한 점

- random 클래스를 컨트롤러 생성자의 인자로 주는 장점은?

랜덤 메소드를 관할하는 클래스는 한 번만 생성해놓으면 되는데, 그럼 보통 getInstance를 떠올리기 쉽다. 이렇게 컨트롤러의 생성자의 인자로 넘겨줘서 클래스 필드로 선언하는 것의 장점은 뭘까?

- OutputView 등을 enum으로 하는 것의 장점은?

0. 소소한 것들

  1. 시작 메시지등의 경우 print 메소드 분리 깔끔하다.

  2. validate 전의 인자를 raw라는 네이밍으로, 그 바깥에서는 scan이라는 네이밍 아이디어!

  1. Stream의 collectingAndThen으로 모아서 리스트에 넣는 것까지 한 번에!

1. 랜덤 테스트를 위한 방식

- 추상화를 통한 제어 vs 우테코 제공 NsTest

추상화를 통한 제어를 하면 우테코에서 제공하는 메소드 이외의 경우도 테스트 할 수 있다는 장점이 있고,

우테코에서 제공한 테스트를 이용하면 shuffle 등의 메소드 자체에 대해 추상화 없이 테스트 할 수 있다는 장점이 있다.

다만, 해당 테스트 코드가 돌아가는 방식을 이해하고 run main이 아니더라도 사용할 수 있는지를 확인해야할 것 같다.run main에서만 사용 가능하다면 제약이 있고, run main으로 연결하는 방법을 생각해봐야할 것 같다.

- 추상화를 통한 제어

- 우테코 제공 NsTest

https://velog.io/@dlguswl936/우테코-제공-NsTest-메소드-들여다보기

2. random 클래스를 만들어 빼기

random을 관리하는 클래스를 만들어도 좋겠다. 비록 이 기능 하나만 있더라도 의미가 있어보인다.

3. RetryUtil의 static 메소드인 read!

controller내에 read 함수를 만드는 게 아니라 retryUtil을 따로 만들어서 거기의 static 메소드로 만들고,

import 문을 넣어놓음으로써 별도 추가 없이 바로 read 메소드 불러오기!

4. read하고 결과를 또 밖에서 read!

이렇게 하면 genarateCoaches() 속에서
형식에 대한 검증 결과를 read로 retry 처리를 한 번 한뒤,

Coaches에 대한 길이 검증 결과를 반환한다.
그 결과인 genarateCoaches()를 read로 감싸면 검증 결과에 대해 retry를 다시 해주는 구조!

각 검증이 일어나는 과정마다 메소드로 분리해서 감싸주면 될 것 같다!

5. validate의 범위 분리

예를 들어, 코치 입력 시 조건들이 아래와 같을 때,

공백 불가/ ','로 구분/ 특수문자말고 한영만/ 5명까지 입력 가능/ 이름은 2~4자

거치는 순서대로 검증 책임은 이렇게 나눠진다.

  • InputView (→InputValidator)

  • 단, InputView에 정규식이나 비교 메소드를 넣지 않고,
    InputValidator를 만들어 InputView에서 쓰일 수 있는 메소드들을 static 메소드로 분리한다.

    • 공백 불가
    • ','로 구분
    • 특수문자말고 한영만
  • Coaches

    • 5명까지 입력 가능
  • coach

    • 이름은 2~4자

6) InputValidator 후에, InputConverter를 따로!

어차피 ,로 입력받은 걸 List로 반환해주는 건 동일한 기능이기 때문에!

7. dto→객체 변환: dto에 to객체메소드, 그 안에 from

대놓고 new 객체를 dto를 받아서 만드는 게 아니라,
dto 내에 dto->객체의 to객체메소드를 만들어서,
그 안에 객체의 from 메소드를 가져와서 객체로 변환한다!

이렇게 하면 생성자를 privat으로 감출 수 있기도 하다!

8. 아니 frequency 함수가 있었다니!

9. 조건 대로 결과 받았지만 결과로 나온 것 다시 한 번 조건 validate!

10. 메인 추천 로직의 이런 계층 구조, get도 안쓰고 따라쳐보기

메뉴 추천 로직을 따라가보자, 다음엔 나도 만들어볼 수 있게!

  • Controller
recommendCategories.recommendMenus(coaches, menuShuffle)

: 일단 coaches랑 shuffle(MenuGenerator)들고 추천카테고리들 돌러 들어감

  • RecommendCategories
coaches.recommendMenus(recommendCategory, menushuffle)

: 추천 카데고리들 중 하나씩 갖고 coaches 돌러 들어감, 셔플은 계속 갖고감.

  • Coachs
coach.recommendMenu(menuCategory, menushuffle)

: 코치들 중 한명씩 갖고 코치에 hate, 이미recommend과 함께 처리해야하므로 들어감

  • Coach
  • 필드: hateMenuNames, recommendMenuNames
menucategory.recommendMenu(gateMenuNames, recommendMenuNames, menushuffle)

: 자기가 가진 hate, 이미recommend 갖고 카테고리enum으로 추천 받으러 들어감. 셔플은 끝에서 해야하는 기능이므로 갖고 들어감.

  • MenuCategory
menushuffle.getMenuFromShuffle(그카테고리의 음식리스트)
  .filter(!hateMenuNames, recommendMenuNames)
  .findFirst.isPresent(recommenMenuNames::add);

: 그 카테고리의 음식 리스트를 셔플돌려서 하나 갖고, 필터로 hate, recommend 거르고, 나오면 갖고온 코치 recommend에 추가, 아니면 다시 돌아가는 건 어딨지?

11. 그 안의 전략패턴!

우선 전략패턴에 대한 설명은 해당 포스팅을 발췌했다.

12. 테스트만을 위한 생성자

에 대한 의견이 좀 있는데, 일단 현재는 이렇게 정리하려고 한다.

  • 해당 포스트에서 제시한 것 중 하나인 default 접근 제어자를 사용함으로써 같은 패키지 안에서 사용하고
  • 구분을 위해 fromTest 이런 식으로 메소드로 분리해서 구분한다
    public static RecommendMenuNames fromTest(List<String> recommendMenu) {
        return new RecommendMenuNames(recommendMenu);

13. 반복 출력시 람다 + join + printf

우선, 공식문서에서의 join

다음으로, 해당 포스팅에서 String.join과 비슷한 기능들에 대한 설명을 가져와서 이해했다.

코드로 돌아가보자면,

  1. 코치 리스트 forEach해서 코치 하나씩을 람다로 꺼내서
  2. menus에 | 랑 코치 메뉴들 join 시켜담고,
  3. printf로 [ 이름 | 메뉴들 ] 틀에 넣어서 출력해준다!

14. MessageFormat.format

메시지를 끼워넣는 또 다른 방식!
printf와 똑같아보이는데 이건 출력되지 않는다는 점이 차이인 것 같다. 왜 여기는 이걸로 썼을까?

0개의 댓글