본문 바로가기

부트캠프/우아한테크코스

우아한테크코스 회고 - 자동차 경주

반응형

페어 미션 (덧셈 계산기, 자동차 경주)

우아한 테크코스의 큰 장점은 이 부분이었던 것 같다. 2대 1로 미션을 진행하는 페어 프로그래밍이 있다는 점 !
물론 끝까지 페어와 함께 하는 것은 아니고, 한 미션에 적어도 2가지 개발 단계가 주어진다.
이때, 1단계는 페어와 페어프로그래밍하고, 2단계는 혼자 프로그래밍한다.

추가 정보
+ 페어는 매 미션마다 바뀐다.
+ 단계가 끝나는 시점은 프로젝트 pull-request를 남기고 marge 되는 시점이다.
+ marge가 되기 전까지 리뷰어(현업 경험이 있는 개발자)의 피드백을 받고, 수정 후에 다시 리뷰 요청을 보낸다.

 

페어 프로그래밍이란?

 
페어프로그래밍은 애자일 소프트웨어 개발 중 하나로, 하나의 컴퓨터에서 두 명의 프로그래머가 작업하는 방법이다.
 
페어 프로그래밍 할 때, 역할이 주어지는데 역할은 드라이버(Driver)와 내비게이터(Navigator)가 존재한다.
코드를 실제로 작성하는 사람이 드라이버가 되고 다른 한 사람이 내비게이터가 되어 코드 검토를 하며 진행한다.

  • 내비게이터(navigator): 과정 중에 의문이 드는 점이나 잘못 흘러가고 있는 상황을 대화로 바로 잡는다.
  • 드라이버(driver): 현재 진행하는 것을 말로 표현하며 진행하며, 내비게이터와의 대화 역시 함께 진행한다.

 
그리고 중요한 건 두 프로그래머는 수시로 역할이 바꿔야 한다. (많아도 15분 간격으로 역할 변경)
이때, 정해둔 시간이 되면 내가 쓰던 코드가 있어도 바로 변경하는 것이 좋다.
 

미션 키포인트 - 단위 테스트

 
 
테스트 구분을 하는 이유는 무엇일까?

  • 비즈니스 로직과 테스트 로직을 분리
  • 여러 번 테스트를 할 때 자동화
  • 기능명세서처럼 빠르게 테스트
  • 배포에 테스트코드는 불포함
  • 테스트 코드도 하나의 문서

 
그럼 main에서 프로그램 실행으로 테스트하는 것은 왜 안 좋을까?
main Test에 문제점"테스트 결과를 사람이 수동으로 확인" 같다고 생각한다.
 


 

배운 점

 
페어와 많은 이야기를 하면서 다양한 지식을 얻었지만, 여전히 궁금했던 부분들을 리뷰어에게 질문했었다. 
다음은 내가 의문이 들었던 내용과 리뷰어에게 받은 답변을 정리해 봤다.
 
 

Q. toString 사용을 지양해야 하는 건가요?

객체는 객체스럽게 사용하는 것이 중요하다고 생각해서 객체의 인스턴스를 단순 출력을 위해 getter를 사용하는 것은 지양해야겠다고 다짐을 하면서 toString을 활용했었다.

 

예를 들어, Car의 name을 출력하기 위해 getName()을 제작하기보다 toString()을 실행하면 name이 리턴되도록 작성하였습니다.

@Override
public String toString() {
   return name;
}

 

그러나, 이번에 페어와 함께 이야기하면서 toString은 디버깅에 적합하다는 이야기와 함께 toString을 사용자에게 보이는(출력하는) 용도로는 사용하지 않는다는 이야기를 들었다.
 
그래서 getter와 toString 두 방식 다 출력을 위해서 사용하는 것은 지양해야 하는 것이 맞는지, 둘 중 하나를 선택해야 하는 상황이 온다면, 어떤 방식을 선택하는 것이 더 좋은 코드를 만들 수 있는지 궁금했었다.
 

 

A. toString보다 getter가 썩 나쁘지 않은 선택지이다.

두 방식 다 출력을 위해 사용하는 걸 지양해야 할까?
결국 값을 꺼내와서 출력을 해아하니까 우린 어떤 방식을 써서라도 가져와야 한다. → 필연적 필요함!
 
어떤 방식을 선택할지, 그리고 더 좋은 방식이 있을까?
 toString() 은 디버깅 / 로깅 쪽에서 사용하자고 할 거다. 
그렇다면 getter 가 썩 나쁘지 않은 선택지가 된다.
 


Q. 자동차의 이동 상태를 어디서 관리하는 것이 좋을까요?

페어와 함께 미션을 구현하면서 자동차의 이동 상태를 Car 클래스에서 관리하는 것이 좋을지, 자동차들을 관리하는 Game 클래스에서 관리하는 것이 좋을지 이야기를 나누었다.
자동차의 상태다 보니 Car 클래스에서 관리해야 할 것 같지만, 그렇게 되면 출력 시 OutputView에게 전달될 때 Car -> Game -> Controller -> OutputView로 많은 이동이 필요하지 않나라는 생각이 잠시 들었다. 결론적으로는 Car 클래스에서 관리하도록 구현하였지만, 다른 사람의 의견이 궁금했다.
 

A. 상태 관리를 적절한 클래스에서 하도록 하는 게 출력 여부보다 중요하다.

두 가지 포인트가 있다.

  1. 값을 출력하는 것과 객체 지향적으로 개발하는 것(좋은 코드를 짜는 것)을 별개로 생각해 보자.
  2. 개발하다 보면 이점만 다 챙길 수 있는 상황이 거의 없을 것이다. 무언가를 선택하면 다른 하나를 어느 정도 놓을 필요가 있다.

상태 관리를 적절한 클래스에서 하도록 하는 게 출력 여부보다 중요하다고 생각한다.
그렇다면 출력할 때 많은 이동이 발생하는 걸 어느 정도 감안해야 한다.
"어떤 걸 더 중요하게 생각해야 유지 보수하기 좋은 코드가 될까?" 관점에서 생각해 보시면 선택하기 더 편해질 거다.
변경하기 더 어려운 것, 자주 변경되는 것, 중요한 로직이 담긴 것을 출력할 것보다 먼저 고려해라.
 

 


Q. 예외 메시지를 enum으로 한 곳에 모아서 관리 할 것인가? 장단점을 생각해보자.

장점

  • 한 곳에 모아서 예외를 관리하기 때문에 관리하기 편하다
    • 예외 메시지를 한 곳에 모아뒀으니, ‘예외 메시지’에 공통으로 무언가를 처리할 때 유용할 것 같다. 
  • 예외 메세지가 변경되어도 도메인 클래스에 수정이 일어나지 않는다. (도메인을 변경으로부터 자유롭게 할 수 있다.)
    • 하지만 “도메인이 변경되는 걸 그렇게 보수적으로 생각해야 할까?” 심지어 도메인 로직도 아니고 예외 메시지인데 말이다.
    • 우리가 경계해야 할 것은 ‘도메인의 변경’ 그 자체가 아니라, ‘외부 요인으로부터 발생하는 도메인의 변경’ 이라고 생각한다.

 

단점

  • 가독성이 떨어질 수 있다.
    • 예외가 발생하는 지점에서 무슨 예외 메시지가 전달될지 바로 알 수가 없다.
    • 예외 발생지점을 역추적할 때도 메시지를 한 곳에 모아뒀을 때 더 어렵다고 생각한다.
  • 예외 메세지에 접근하기 위해 불가피한 depth가 생긴다.
    • 이건 위에서 말한 가독성을 떨어트리는 요인이기도 하지만, 코드를 작성할 때도 고려해야 할 점을 하나 추가하는 행위이다.
    • 이제 예외를 던질 때마다 예외 메시지 모음 집에 가서 내가 원하는 메시지가 있나 찾아야 한다. 여간 귀찮은 일이다.

 


검증 메서드 이름을 지을 때 not 일 때 통과인지, is 일 때 통과인지를 일관성 있게 짓자.

검증 메서드를 작명할 때 '이하' , '이상' 까지 드러낼 필요는 없다고 생각하지만, 검증 메서드 이름을 지을 때 not일 때 통과인지, is일 때 통과인지를 일관성 있게 짓자.

 


AutoCloseable 사용해보기

이번에 BufferdReader, BufferedWriter를 사용하면서 동작이 끝났을 때 버퍼가 close 하는 방법에 대해 고민하였다. 

고민하면서 페어와 찾아보니 AutoCloseable을 알 수 있었다.

 

AutoCloseable를 사용하면 try-catch-reasource 로 사용될 경우, try-catch문이 종료되면 AutoCloseable의 close 함수가 호출된다는 것을 알게 되었다.

그래서 BufferdReader, BufferedWriter를 사용하는 클래스를 AutoCloseable을 impliments 하게 하여 close가 불러질 때 버퍼를 close하도록 하였다.

 


소감

 
이렇게 말로만 들으니 여전히 "페어프로그래밍을 어떻게 하지?" 하는 의문이 들었다.
그래서 페어와 본 미션에 들어가기 전에 간단한 미션으로 페어 프로그래밍 체험을 할 수 있었다.
미션 난이도는 지금 혼자 한다고 생각하면 30~60분이었을 것 같다. (아닐 수도!)
 
그러나 함께 '요구사항을 어떻게 작성하는지'부터 '코드를 어떻게 작성하는지' 등을 맞춰가면서 하다 보니, 주어진 20분 동안 요구사항을 하나도 구현하지 못하였다.
생각을 맞춰가고, 코드스타일을 맞춰가다 보니 시간이 혼자 할 때보다 더 소요되는 것 같다.
 
이후 나와 페어는 남아서 함께 더 공부하기보다 집에서 각자 해당 미션을 풀어보고, 코드 스타일을 공유하면서 지식을 공유하기로 하였다. 그렇게 다음날 코드를 서로 확인하면서 다르게 구현한 부분이 무엇이 있는지 각자의 코드의 장단점은 무엇일지 확인할 수 있어서 이후 함께 하게 된 페어 프로그래밍이 수월했던 것 같다.
 
그리고 실제 미션을 페어와 함께하면서 다양한 시선을 배울 수 있었던 것 같다. 나는 "좋은 코드란 무엇일까?", "더 효율적인 코드란 무엇일까?"에 대해 많이 생각해 본 적도 없으며, 깊게 다른 사람의 의견을 들어본 적이 없었던 것 같다. 
하지만 이번에 함께 하나의 노트북으로 공부를 하다 보니 서로의 의견을 들어보면서 내가 생각하지 못한 좋은 정보를 많이 얻을 수 있었다. 
 
그리고 여전히 고민이 되었던 부분들에 대해서는 리뷰어와 함께 이야기하면서 코드를 발전시키고 지식을 높여나갈 수 있는 것 같다.

반응형