본문 바로가기
개인공부/우테코 회고

우테코 3주차 회고. (나중에 변경)

by 응가1414 2023. 11. 9.

  다양한 코드들을 검토하며 2주차 코드 리뷰를 진행하였습니다. 원활한 코드 리뷰를 통해 효율적인 방법을 채택하였고, 별도의 학습을 통해 코드의 유지보수성과 확장성을 강화하는 방향으로 노력하였습니다.

"외부 객체 생성"
  Config 클래스를 생성하여 객체를 초기화하였습니다. 클래스의 분리에 대한 학습 과정에서 '관심사의 분리를 위해 제3의 클래스를 생성'하는 방법을 접하게 되었습니다. 현재는 사용자가 하나의 로또만 구매하는 형태이지만, 연금 복권이나 주택 복권 등 다양한 복권 구매 방식이 업데이트 될 경우, 객체지향의 다형성을 이용할 수 있는 구조를 구현하고 싶었습니다. 프리코스가 끝난후 이를 위해 Lotto를 추상화할 수 있는 인터페이스를 구현하고, Config.lotto(interface Lotto lotto)의 형태로 구현해보려고 합니다. 이 과정으로 '제어의 역전'을 완성하고 싶습니다. 다시말해 "User 클래스가 능동적으로 사용할 객체를 선택하지 못하고, 대신 Config 클래스에서 수동적으로 사용할 객체를 제공받는 형태"을 구현하여 유저가 로또를 선택하는 책임을 없애고 외부에서 로또를 선택하는 방향을 구상하였습니다.
  
"검증 클래스 분리"
  검증 기능을 별도의 클래스로 관리하는 것이 적절한지에 대한 고민을 해보았습니다. 클래스 분리의 목적은 1. 클래스의 길이를 줄이는 것, 2. 로또, 로또 판매자, 로또 구매자 등 비슷한 특성을 가진 클래스가 발생할 경우, 검증 메서드를 중복 생성하지 않도록 하는 것입니다. 만약 로또 판매 외에도 사용자 간의 거래가 가능하게 된다면, 또는 로또 종류가 다양해진다면, 검증 클래스를 별도로 구현하는 것이 편리할 것이라는 생각이 들었습니다. 그러나 동시에, 클래스를 과도하게 사용하는 것은 아닌지, 혹은 모든 검증 메서드를 하나의 검증 클래스에 넣는 것이 옳은지에 대한 의문을 가지고 있습니다.
  
"예외 처리"
  입력에 대한 예외 처리를 NumberFormatException을 사용하는 것이 적절한지에 대해 고민해 보았습니다. 이전까지는 예외 발생 시 출력문을 따로 출력하지 않았지만, 이번에는 예외 발생 내용을 출력하여 확인해 보았습니다. 그 결과, 공백을 입력했을 때 문자열 예외가 발생하는 등 예외 처리가 제대로 이루어지지 않는 점을 확인할 수 있었습니다. 
  이를 통해 1, 2주차의 과제에서도 예외 처리가 충분히 이루어지지 않았음을 인지하게 되었습니다. 이에 따라 "특수 문자, 문자 입력 검증"을 포함하여 "숫자 입력 검사"로 간소화하는 등, 오류 출력문이 오류 검증이 이루어지도록 변경해 보았습니다. 세상의 일을 프로그램으로 정의 하는 과정에서 많은 예외 사항이 있다는 것을 인지를 하고 있습니다. 일상의 일중에 예외에 대한 검증을 하는 연습을 하고있습니다. 
  
"일급 콜렉션"
  코드 리뷰를 진행하면서 일급 콜렉션을 사용하는 경우를 많이 보았습니다. 일급 콜렉션은 객체 지향 프로그래밍의 원칙을 준수하면서, 콜렉션 객체를 캡슐화하고 관련 메서드와 속성을 제공하는 방식을 말합니다. 이는 콜렉션에 대한 동작을 캡슐화하고, 내부 데이터를 안전하게 관리할 수 있으며, 특정 도메인 관련 로직, 유지보수, 확장이 용이하고 재할당이 불가능한 등의 특징을 가집니다. 저는 이번 과제에 LottoEnvelop, LottoTargetNumResults, WinLottoNumbers라는 세 개의 일급 컬렉션을 만들어 사용하고 학습해보았습니다. 일급 컬렉션은 컬렉션에 이름을 부여함으로써, 해당 컬렉션이 어떤 역할을 하는지, 왜 만들어졌는지를 쉽게 이해할 수 있게 해줍니다. LottoEnvelop 타입의 매개 변수를 선언하여 캡슐화된 컬렉션을 할당하는 것이 다른 타입을 할당하는 실수을 줄일수 있으며 또한, LottoEnvelop에 관련된 메서드를 구현해 사용함으로써 더욱 편리함을 느꼈습니다.
 


"클래스 분리"
  이번에는 클래스의 분리에 많은 신경을 썼습니다. 유저(User), 통계(Statistic), 수익률(RateResult), 판단(Judgment) 등으로 유저의 행동을 클래스로 나누어 보았습니다. 클래스 분리의 기준은 유저의 행위(메서드) 중에서 추상적이고 공통적인 부분을 독립시키는 것이었습니다. '유저가 통계를 계산하여 보여준다'는 것이 가장 기본적인 흐름입니다. 하지만 이를 '유저가 (당첨된 것들만, 당첨되지 않은 것만) 통계를 계산하여 보여준다'로 확장할 경우, 클래스의 분리가 확장성에 유리하다는 생각이 들어 분리를 진행하였습니다. 통계라는 클래스를 독립시킴으로써 다양한 통계 관련 메서드를 사용할 수 있게 되었고, 유저가 통계를 계산해야 한다는 책임을 분리할 수 있었습니다. 이러한 결과를 보니, 클래스를 분리한 것이 나름의 성공이라고 생각합니다.
  
"메서드 이름의 고찰"
   메서드의 이름에 대해서도 많은 고민을 했습니다. 로또 판매자의 메서드는 '판다'(sell), 로또 진행자는 '고른다'(pick), 유저는 '보여준다'(show), '가져간다'(take) 등으로, 각 객체의 행위를 메서드 이름으로 표현해 보려고 노력하였습니다. 이를 통해 메서드의 특징을 이름 그대로 표현하려 했습니다.

"enum 관리"
   enum의 적용 부분은 많이 어려운 것 같습니다. enum의 정의는 '서로 연관된 상수들의 집합'이라는 점을 기억하면서, 로또 등수에 따른 금액을 enum으로 분리하여 관리하였습니다. 처음에는 enum을 이용해서 등수에 따른 당첨 횟수를 세려고 했지만, 많은 오류가 발생했습니다. 원인을 찾아보니, enum은 생성과 동시에 모든 클래스와 공유되는 싱글톤이라는 것을 알게 되었습니다. 이는 학교에서 배웠던 싱글톤과 공유 자원의 개념이 실제로 나에게 적용되는 것을 보고, 바로 List을 이용해 count따로 관리 하였습니다. 
   이후에는 LottoRank.MONEY_FIFTH_PLACE(money, index)를 생성하여 관리하게 되었습니다. 그런데 여기서도 고민이 들었습니다. 과연 enum의 매개 변수에서 index를 관리하는 것이 옳은 것인가에 대한 고민이었습니다. 처음에는 enum.ordinal()을 이용해서 index를 관리하려고 했지만, enum의 순서에 따라 index가 변경되는 점이 마음에 걸려, 매개 변수에 index를 명시하여 안전하게 관리하는 방향으로 선택하였습니다.
   인터넷에는 다양한 enum의 사용법이 나와있어서, 프리 코스가 끝나고 나서 다른 방식으로 enum을 관리해보려고 생각하고 있습니다. 예를 들어, 일반 로또와 연금 로또는 각각 등수에 따른 금액이 다르고, 다양한 종류의 로또에 따라서도 금액이 다르기 때문에, LottoGroup.enum을 이용하여 각각의 Lotto.enum을 관리해 보는 것을 구상 중입니다. 이렇게 하면 좀 더 흥미로운 enum의 사용법을 연습해볼 수 있을 것 같습니다.
   
  
"이번 과제의 실수"
   이번 과제에서는 작은 단위의 클래스 (당첨 번호들의 모임, 보너스 번호 등)부터 구현하다보니 코드 수정이 많았습니다. 처음 클래스를 설계할 때 모든 클래스의 메서드를 명시하고, 나중에 구현하면서 간과한 부분을 비교하고 싶었습니다. 그런데 이번에는 작은 단위의 클래스부터 먼저 구현하여 도구로 사용하는 방법을 채택해 보았습니다. 그러나 이렇게 하니 제가 만든 클래스의 메서드를 사용하기 위해 코드 수정이 많이 필요했습니다. 2주차 피드백에서 말씀하신대로 "기능 목록을 클래스 설계와 구현, 함수(메서드) 설계와 구현과 같이 너무 상세하게 작성하지 않는다."는 조언을 받고 이해했습니다. 다음번엔 요구사항과 예외 처리 부분을 세밀하게 작성하여 좀 더 유연하게 대응하도록 해야겠습니다.

'개인공부 > 우테코 회고' 카테고리의 다른 글

4주차 회고  (0) 2023.11.15