우아한테크코스 - 프리코스 4주차

junho5336·6일 전
4
post-thumbnail

서론

지난 3주차를 진행하면서 피드백을 받고 이렇게도 적용할 수 있겠구나를 알아가는 과정이였다면 마지막 4주차는 알게된 지식 혹은 공통 피드백과 코드 컨벤션을 자신의 지식으로 체화하는 과정을 가지는 시간을 가져볼 수 있었다.

공통피드백, 피어리뷰, 주간회고록 등등 수많은 지식이 하나되어 어쩌구저쩌구
아무튼 알게된 내용들을 전부는 아니지만 내 무기로 만들어버렸다...!!!!🔥🔥🔥

👍 피어리뷰

피어리뷰를 통해서도 많은 사람들의 코드를 보며 감탄했다. Enum의 활용방식, 객체를 어떻게 나누고, 테스트코드를 어떻게 작성하는지 등등 많은 내용을 배울 수 있었다.

공통 피드백 내용의 응용풀이방식을 보는듯한 기분이라 더 이해하기 좋았다.

MVC 패턴, 팩토리 메서드 패턴, DDD(Domain Driven Development), 템플릿 메서드 패턴 등등 정말 다양한 방식의 디자인패턴을 적용한 참가자들의 코드를 봤다.

하지만 디자인패턴과 관련해서는 아는게없기도 할 뿐더러 혼란스러운 점이 많아 많이 참고하지 못했다.

아직 디자인패턴에 익숙하지 않은 나에게는 무엇이 옳다 그르다를 판단하기도 어려울 뿐더러 무엇이 현 상황에 적합한지 고려하기도 어려웠기 때문에 지금은 디자인패턴에는 집중하지 않는것으로 결정...!😵‍💫

🧘‍ 주간 회고록

4주차 과제가 나온 수요일 저녁. 백앤드 트랙의 3주차 회고록을 모조리 섭렵했다.
+ 11월 21일 월요일 오전 12시 43분... 이후로 올라온 (백앤드)회고록마저 섭렵해버렸다
다른 트랙도 보고싶은데 몸이하나라서 아쉽다...


회고록 다가져와~!@!@!@@@@

모든 참가자의 노하우를 흡수해보겠다는 각오로 덤벼들었고, 사람들의 고민과정에서 많은 수확을 얻어낼 수 있었다. 하지만 나는 천재가 아니니까 모든 노하우를 흡수할 수는 없다.

위에서 디자인 패턴 하나도 못고르는걸 보면 잘 알 수 있는 부분이다. 그래도 설계단계에서 도움이 될만한 방법들을 몇가지 추렸고 적절한 선택과 집중으로 다음 내용들을 참고했다.

@parkmuhyeun 님의 Flow chart
본격적인 설계에 앞서 프로그램이 어떤 흐름을 가지는지 순서도로 나타내보자

@le2ksy 님의 클래스 다이어그램
클래스 다이어그램을 적용하여 예쁘게 볼 수 있도록 도식화해보자

좋은 회고록 항상 감사합니다🙇‍♂️

🌊 Flow Chart

플로우 차트를 작성해보면 머릿속의 흐름을 그림으로 표현할 수 있을 것이고 다이어그램도 이쁘게 나올것이다.

일단 흐름을 막 떠오르는대로 썼다.

이렇게보니 절차적으로는 참 생각하기 편해지는데 아직 내공이 부족한 탓에 객체지향적으로는 생각하기가 어려웠다.

그래도 절차라도 이해하는게 어디인가...

클래스다이어그램도 먼저 작성해보려고했는데 계속 어딘가에서 꼬인다...
다이어그램만 한 3번정도 갈아엎고 나서 생각해본 결론으로는 일단 간략하게 기능을 작성하고 나중에 리팩토링하면서 클래스다이어그램을 그려보기로 했다.
나는 천재가 아니니까 주특기인 삽질로 승부를 본다.

🥺 1차구현

주어진 ApplicationTest를 통과해야겠다는 마음으로 일단 주어진 테스트를 모두 통과했다.

기능들이 너무 난잡하게 얽혀있기도 하고 뭐가 뭔지 잘 읽히지 않는다...
역시 나는 천재가아니기 때문에 한번에 잘 짜여질거란 기대도 안했다.

테스트를 어떻게 짜야할지도 모르겠고~ 기능을 어떻게 나눠야할지도 모르겠고~

애시당초 TDD에서 테스트를 먼저 통과하라고는 하는데 Application을 먼저 통과하란 얘기는 아닌게 분명하다

3주차 피드백중 객체는 객체스럽게 사용하라는 문구가 있다.


너는 지금 전혀 스윙하고 있지 않아

지난 3주간 진행된 우테코는 나를 통과만 되는 코드로는 절대 만족할 수 없는 사람으로 만들어버렸다. 아쉽지만 1차로 작성한 코드는 눈물을 머금고...


엎어..!!


🔥 다시 살펴보기

코수타 2회차때 포비님이 말하셨던 TDD는 ㅆㄹㄱ다 를 인용해보자.
그렇다 내 코드는 쓰레기다 태초마을로 돌아가자

아래는 지극히 개인의 주관적인 관점으로 객체를 나누고있습니다.
스탠드업 코미디를 본다는 느낌으로 가볍게 봐주시면 감사하겠습니다.

💪 객체 쪼개기

게임 진행간 어떤 객체들이 어떤 행위를 하는지 아주 잘게 쪼개보자.

다리를 건너고있는 62번 참가자를 보자.
지금 사진에서 보이는 객체는 다리, 사람이 보이고 다리는 각 유리발판이 모여서 만들어졌다는것을 볼 수 있다.

그렇다면 다리(발판들의 집합), 사람으로 나눠서 생각해볼 수 있겠다.

각 객체의 행위를 정의해보자.


🎯 사람

이러다 다~ 죽어

행위

  • 🏃‍ 앞으로 간다
  • 👼 부활! (재시작을 의미한다..ㅎㅎ)

상태

  • 🦶 몇칸을 건넌 상태인가?
  • 😇 죽었나? 살았나?

🎯 다리

  • 📚 발판들의 집합이다.

요구사항 안지킬거에요?

// 제공된 BridgeMaker 클래스를 활용해 구현해야 한다.
// BridgeMaker의 필드(인스턴스 변수)를 변경할 수 없다.
// BridgeMaker의 메서드의 시그니처(인자, 이름)와 반환 타입은 변경할 수 없다.

public class BridgeMaker {

    public List<String> makeBridge(int size) {
        return null;
    }
}

근데 조건중에 BridgeMaker 반환타입을 변경하지 말라고하는데요???
BridgeList<String>으로 해야될걸요?

예.. 아무튼 그렇게 됐습니다...


🎯 발판

행위

  • 👷 안전한가요?

상태

  • 안전한 발판 (⬆️ 위 발판 / ⬇️ 아래 발판)

🎯 BidgeGame

BridgeGame은 위 객체들에게 질문을 던져가며 게임을 진행하는 중재자 역할로 보자.

행위

주어진 행위를 어디에 써먹을지 잘 생각해보자.

  • 🏃‍ 사람이 움직여요! #move()
  • 🔄 재시작할래요! #retry()
  • 🎤 게임 진행상태를 알려드립니다
  • 📝 게임 진행과정을 드리겠습니다 (ResultMap)

상태

  • 진행상태 (👍 성공 / 👎 실패 / 🏃‍ 진행중)
  • ⏰ 게임 반복횟수

사실 클래스 다이어그램이라기엔 조금 이상하지만...
객체가 물어본다는 행위를 기반으로 다이어그램을 작성하면 이렇게 표현할 수 있겠다.

위에나온 표는 처음부터 저렇게 나오지 않았습니다.
저는 위 구조가 한번에 나오는 천재가 아니기 때문에 처음에는 이렇게 생긴걸로 시작했습니다.


📚 (주어진) 기능목록

객체쪼개기에서 정의한 내용을 먼저 생각하고
기능 목록은 주어진(사용해야하는) 객체들을 먼저 기능으로 둬보자

⌨️ 사용자 입력을 받는다. - InputView

  • 다리길이 입력 #readBridgeSize
    • ⚠️ 숫자가 아니면 예외
    • ⚠️ 3 ~ 20 사이의 숫자가 아니면 예외
  • 이동 방향 입력 #readMoving
    • ⚠️ U, D 값이 아니면 예외
  • 게임 재시작 여부 입력 #readGameCommand
    • ⚠️ R, Q 값이 아니면 예외

🖥️ 게임 진행 상황과 결과를 출력한다. - OutputView

  • 게임 시작 메시지 출력 #printInit
  • 게임 진행상황을 출력 #printMap
  • 게임 종료 후 결과 출력 #printResult

🕹️ 다리 건너기 게임을 진행한다. - BridgeGame

  • 움직임을 수행한다. #move
  • 게임을 재시작한다. #retry
  • 진행 상태를 알려준다.
  • 진행 횟수를 알려준다.

다리를 생성해준다. - BridgeMaker

  • 다리를 생성한다. #makeBridge

더 자세한 기능목록이 보고싶다면 README.md 문서를 참고해주세요~


🏁 테스트 먼저

TDD는 잘 모르겠지만 일단 TDD에서 지향하는 방식인 테스트를 먼저 작성하고 가장 빠르게 통과하는 방식을 적용해보자.

TDD에 대해 완전 무지한 사람이 진행하는 방식이니 만약 틀린부분이있다면 아 TDD 그렇게하는거 아닌데 ㅋㅋ 한마디 남겨주고가시면 학습 원동력에 큰 도움이 될것같습니다. 🔨

✅ Floor 객체 테스트하기

예를들어 바닥은 U 혹은 D 라는 상태만 가져야한다는 것을 가지고 테스트를 만들면 이렇다.

여차저차해서 테스트를 통과시켜보자

이런 방식으로 흐름의 끝단에 있는 객체들부터 순차적으로 올라가면서 테스트를 작성해보자.

😵‍💫 테스트하기 어려운코드

중간에 Bridge를 만드는데 생성자에서 int size를 받고 내부에서 BridgeMaker를 생성하고 알아서 만들어지게끔 구성하려고했다.

이렇게 구조를 수정하고 테스트코드를 짜려고보니 내부에서 랜덤하게 생성되는 값들에 대해 테스트하기가 참 어려웠다. mocking을 해서 어쩌구.. 하기도 복잡해서 잠시 손놓고 생각을 다시해봤다.

위 내용이 무슨 말인가 싶을수도있겠지만 아래 그림을 보면 바로 아?! 할수도 있다.

3주차 과제 공통피드백에서 위와같은 내용이 있었다.
한마디로 내가 하려던건 BridgeGame(테스트하기 어려움) -> Bridge(테스트하기 어려움) -> BridgeMaker (테스트하기 어려움)

딱 이상황이다.
위 상황에 맞춰 BridgeMaker를 한단계 위에서 사용하게 하고 Bridge의 인자는 List<String>를 받게끔 구성하니 테스트하기가 한결 편해졌다.

⌨️ 다시 입력받기

다음과 같은 조건이 있다.

사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다.

그리고 이건 3주차의 조건이다.
사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 종료한다.

조건이 종료가 아닌 다시 입력받는 방식으로 변경되었다!!
지난 주차에 Application 메인 부분에 try - catch로 냅다 잡아버린게 마음에 들지 않았던걸까...

이런 방식으로 해결할 수 있겠다.

try-catch가 각 메소드별로 있는게 마음에 안든다.
뭔가 더 고급스럽게 프록시를 이용한다던가 스프링을 사용했다면 AOP로 잡아낸다던가... 뭔가 다른 방식이 존재할거같지만 프레임워크를 사용하지 않고 구현하는 방식은 찾아봐도 잘 모르겠다 ㅋㅋㅋㅋㅋ

다시봐도 프레임워크가 짱이다...

🛠️ 리팩토링

어쩌다보니 중복되는 상수값을 가지는 경우가 빈번히 생긴것을 확인할 수 있었다.

해당 피드백 내용으로 몇대 얻어맞은 뒤 연관된 상수를 Enum으로 묶을 생각을 해볼 수 있다.

왜 U, D값이 필요한가 한번 살펴보면 대부분 validation에 사용되고있음을 알수있다.
그렇다면 이러한 validation logic또한 enum에게 넘길 수 있겠다.

가령 이렇게 생긴놈을

이렇게 바꿀 수 있겠다.

간혹 이렇게 특정 클래스에서만 사용하는 상수들은 재사용성 혹은 연관성이 없다고 느껴져 굳이 enum으로 분리하지 않았다.

❓ 뭐 잊은거 없니??

3주차의 피드백 내용중 다음과 같은 내용이 있다.

테스트 코드도 코드야!!

딱 봐도 뭐라는지 모르겠다. 마치 더러운 방을 보고있는것같다.
방청소하는 시간을 좀 가지자. 청소하고 정리를해야 뭐가 어디에있는지 찾기쉽지...

🥸 느낀점

어쩌다 이지경이 되었는가.. 다시 생각해보는 시간을 가져보자

😂 Choi-JJunho_V1

Choi-JJunho_V1 진행과정 요약

처음에는 기능을 중심으로 코드를 작성하다보니 가장 윗단인 InputView와 OutputView를 건드리기 시작했고, 그러다보니 입력에서 Validation을 다 해주는에 아래 객체에서 굳이 중복되는 Validation을 해야하나? 라는 안일한 생각이 계속 들었다.

뭔 객체를 만들때마다 이런 생각이 계속 진행을 방해하니 집중도 안될 뿐더러 기껏 ApplicationTest를 통과해도 찝찝함이 남아있었다.

게다가 확장성을 생각해봤을 때도 이곳저곳 문제가 참 많았다.

Why?

왜 이런 현상이 일어났는가 분석해보는 시간을 가졌다.

  1. 😱 마음이 급하다.

제시간 내로 구현을 하지 못할까봐 마음졸인 끝에 제시된 기능을 기준으로 먼저 구현하고 보자는 식으로 덤벼들었던것이 잘못이였다.
4주차 마지막 과제라서 더 조급한 마음이 들었던것도 사실이다.

  1. 😎 너무 완벽하게 시작하려고했다.

서론에서 이야기한 FlowChart까지는 문제없이 작성할 수 있었다.
하지만 여지껏 한번도 작성해보지 않았던 클래스 다이어그램에 처음부터 완벽하게 모든 객체들의 상태, 메소드, 연관관계를 작성하려고했던 것에서부터 조급함이 더해졌다.
이 조급함은 결국 안되네..? 그럼 일단 구현부터! 라는 이상한 길로 빠지게 만들었다.

애시당초 시작부터 잘못되었다고 생각한 끝에 과감하게 리팩토링이 아닌 리스타트를 했다.

😆 Choi-JJunho_V2

역시 삽질은 위대하다. 한번 맞으니까 내 입지를 알고 아주 작은 객체부터 만들어보기 시작했다.
주어진 문제를 순서도를 참고하며 객체의 관점에서 바라보려고 노력했다.

V1에서 작성했던 Error Message같은 쓸만한 Enum까지 모조리 없애버리고 다시 짜면서 조바심을 내지 않는것에 집중했다.

차분히 하나씩 진행해도 충분히 할수있다고 스스로 믿음을 가지는것이 가장 중요한 시간이였다.

🛠️ 리팩토링

차분히 설계하고 깊게 곱씹으며 고민한 구조를 리팩토링하는일은 굉장히 즐거웠다.
내가봐도 구조를 고민한게 코드에 녹아들어있어 코드에 애정도 생겼다.

게다가 몇몇 구조를 수정해도 미리 작성해둔 테스트코드가 리팩토링한 코드에 문제가 없다는 것을 증명해주고있어 마음도 편안했다.

위 내용들 모두 TDD를 언급하는 모든 사람들의 말과, 글로부터 보고들었던 내용이라 머리로는 알고있었지만 직접 경험해보니 정말 가슴에 와닿았다.

💬 후기

우아한 테크코스 프리코스를 진행하면서 4주간 참 많은것을 배웠다.

1️⃣ 주차

Git Convention, Java Convention, Clean Code 등등 협업을 위해 어떤 노력을 할 수 있는지 알게되었다.

2️⃣ 주차

CleanCode 내용을 몇가지 적용해보면서 함수와 변수의 네이밍에 신경쓰기 시작했고, 함수가 최소한의 기능을 가지는지 의심하기 시작했다.

Github Discussion에서 성장에 굶주린 사람들의 모습에서 동기부여도 얻을 수 있었다.

3️⃣ 주차

3주차 공통피드백 문서를 확인하며 어딘가 부족한걸 알 수 있었면서도 나도모르게 스스로 만족했었다는 것을 알고 반성하는 시간을 가졌다. 만족을 경계해야한다는 교훈도 얻었다.

4️⃣ 주차

4주차에서는 생각과 구조화의 중요성을 알고, 조급함을 내려놓는 방법을 배웠다.

덕분에 막판에 제출하면서 발생한 예기치 못한 오류에도 크게 당황하지 않고 금방 해결책을 찾을 수 있었다.


BridgeRandomNumberGenerator 클래스의 패키지를 옮겨서 발생한 문제였다..😅
아니 클래스 코드를 변경하지 않는다는것이 패키지까지 해당될줄은... 미처 생각 안했던것같다.

🤔 그래서?

나는 천재가 아니기 때문에 객체지향 원칙 SOLID를 모두 생각하며 개발하지도 못하고, TDD를 완벽하게 적용할 엄두도 내지 못한다.

게다가 나는 이해속도가 남들에 비해 많이 느리기 때문에 무거운 엉덩이로 우테코 4주를 버텼다.
프리코스 기간동안 하루 4시간 이상 잔적이없다.🥱

머리가 멍청하면 몸이 고생해야지😂

글을 쓰고있는 지금도 많이 피곤하다... 프리코스 끝나면 일단 잠을 좀 자고 못다읽은 CleanCode도 마저 읽고 정리해봐야겠다.
내가 4주간 TDD, 객체, 함수, 네이밍 등등 다채롭게 맞으면서 놓치고있던 무언가가 책 내용에 있을 것 같아 기대된다.

역시 책은 아껴먹어야 맛있지

마무리

제가 좀 관종이라 Github Discussion 주간 회고록에 올라온 회고록에 댓글을 와르르 달았습니다🙇‍♂️

혹시 이 행동에 숨은 의미가 있다는것을 알고계셨나요?
지난 주차의 글을 인용해보면 리액션이 많을수록 공유의 장은 활발해지고 위에서 주절댄 이야기가 선순환으로 이어지는 현상이 이뤄질 것을 기대해볼 수 있다는것이다 라는 말을 했었습니다.

제가 처음 블로깅을 시작했었을 때 다른 사람의 잘보고갑니다 같은 한마디 혹은 좋아요 표시 하나 하나가 큰 동기부여가 되었습니다.

누군가 나의 글을 보고있다는 것을 인지하는 것 하나만으로도 학습에 굉장한 동기부여가 되기도합니다.
만약 그 글이 회고록이나 긴 시간 고민하면서 해결한 과정을 풀어나가는 글들이라면 동기부여가 배로 되는건 당연하겠죠.

여기서 지난주차에 언급했던 코이의 법칙을 조금 다른 관점으로 넓혀서 생각해보게 됩니다.
서로 관심을 가지고 공유하는 문화가 활성화되면 하나의 큰 어항을 만들어낼 수도 있습니다.
넓은 어항에 들어가는것도 좋지만 다같이 모여 넓은 어항을 만드는일도 정말 근사한 일이지 않을까요?

우리 모두 다같이 스스로의 고민과 해결과정을 공유해보기도 하고 누군가의 글을 봤다면 댓글도 한번 달아보고, 댓글달기가 부끄럽다면 👍따봉버튼👍이라도 눌러보는건 어떨까요?


길다면 길고 짧다면 짧은 프리코스 과정을 진행한 모든 참가자들과 나 자신에게 고생했다고 박수치며 글을 마무리하겠습니다~
다같이 박수~!!👏👏👏👏👏

📢 Choi-JJunho의 PR 깨알 홍보

profile
BackEnd

16개의 댓글

comment-user-thumbnail
4일 전

너무너무 유쾌하고 재밌는 글이에요 😁 더 보고싶은데 아쉬우어 ㅛㅠㅠ

1개의 답글
comment-user-thumbnail
4일 전

준호님의 우테코 블로깅을 계속 봐왔던 저로써는 가장 열정 있다고 느껴졌습니다.
제가 만약 우테코 평가담당이었다면 준호님은 꼭 뽑고싶었을거 같네요~

1개의 답글
comment-user-thumbnail
3일 전

슬랙에서 자주 보여 내적 친밀감이 꽤 있었는데, 유쾌한 사람이셨군요 ㅎㅎ 좋은 글 잘 보고 갑니다.

1개의 답글
comment-user-thumbnail
3일 전

글 너무 재밌게 읽었씁니다...! 자주 들리겟습니당

1개의 답글
comment-user-thumbnail
3일 전

저도 전엔 설계를 완벽히 짜고 들어가려 했는데 포기했어요! 직접 부딪혀봐야 똥인지 된장인지 아는 사람이란 걸 인정해서, 요구사항만 제대로 읽고 프로세스 정리되면 냅다 들어갑니다😂 선한 영향력을 퍼뜨릴 줄 아시는 준호님이 대단하게 느껴지네요 앞으로도 화이팅이예요💪💪

1개의 답글
comment-user-thumbnail
2일 전

저도 이번 미션을 하면서 크게 깨달은 점이 처음부터 완벽한 설계란 없다 였습니다 ㅎㅎㅎ
해보면서 많은 고민을 하면서 더 나은 설계로 이어지더라구요..!
매주 회고에 대해 리액션으로 동기부여가 된다라는 말이 정말 공감되네요 ㅎㅎ 준호님 덕분에 4주 미션을 완주할 수 있었습니다!!

1개의 답글

'모든 참가자의 노하우를 흡수해보겠다는 각오' 감명받고 갑니다 ㅎㅎ.. 준호님은 뭘 하든 되실 분 같아요. 선한 영향력을 만들려는 노력까지 완벽 👍🏻👍🏻

1개의 답글
comment-user-thumbnail
어제

4시간 미쳤씁니까.. 잠좀 자십쇼 휴먼.. ㅋㅋㅋㅋㅋ

답글 달기
comment-user-thumbnail
약 5시간 전

너무 재미있게 잘 읽었습니다! 회고록에서도 엄청난 정성이 느껴지네요 :) 많이 배우고 갑니다 ㅎㅎ

답글 달기