계산기 미션 회고

yshjft·2022년 3월 27일
0

미션내용

미션의 요구사항은 아래와 같았다.

  • 객체지향적인 코드로 계산기 구현하기
  • 기능
    • 더하기
    • 빼기
    • 곱하기
    • 나누기
    • 우선순위(사칙연산)
    • 테스트 코드 구현하기
    • 계산 이력을 맵으로 데이터 저장기능 만들기
  • (선택) 정규식 사용

그리고 위와 같은 요구사항에 따라 아래와 같은 내용으로 구현하였다.

  1. 정수형 연산만 가능하록 구현하였습니.
  2. 더하기, 빼기, 곱하기, 나누기 연산의 우선순위를 반영하여 연산할 수 있도록 구현하였습니다.
  3. junit5를 이용하여 테스트 코드를 작성하였습니다.
  4. LinkedHashMap을 이용하여 계산 결과를 저장하였습니다.
  5. 정규식은 사용하지 않았습니다.

미션을 해보며...

회고를 어떻게 써야할지 감이 잘 잡히지 않아 간단하 미션을 진행하며 재미었던 점과 아쉬운 점을 구분여 작성하였다.

😊 좋았던점

  1. 객체지향적으로 코드 작성
    가장 좋았던점이다. 결과물이 어떻든 간에 어떻게 하면 코드를 객체지향 5대 원칙을 지키며 작성할 수 있을지 많이 고민해보는 시간이 되었다. 특히 이번주 과제엿던 디자틴 패턴 탐구에서 학습한 패턴을 직접 적용(전략 패턴인지 팩토리 패턴 인지 확실하지 않지만...)할 수 있는 시간이었다.

  2. TDD
    이전에 TDD를 하려면 가장 막막했던 것이 복잡한 로직에 대한 테스트 코드를 한번에 작성하는 것이었다. 예를 들면 아래와 같다.

    사칙연산 로직 테스트 코드 작성 → 사칙연산 로직 실제 코드 작성**

    이러한 방식의 테스트 코드 작성은 항상 놓치는 부분이 생겼고 너무 복잡해 테스트 코드를 작성하기 어렵게 만들었다. 하지만 이번에 멘토님에게 질문을 드리고 아래와 같은 방법으로 변경하였다.

    더하기 테스트 코드 작성 → 더하기 실제 코드 작성
    빼기 테스트 코드 작성 → 빼기 실제 코드 작성
    ...

    변경된 방법을 사용해보니 테스트 코드에서 놓치는 부분이 줄어들었고 테스트 코드를 작성하는 것이 이전보다 수월해졌다. 결과적으로 변경된 방식을 과제에서 직접 사용해보는 것을 통하여 TDD에 조금 더 익숙해질 수 있는 시간이었다.

😕 아쉬운점

조급함

사실 이번 미션은 아쉬움점이 좋은점보다 큰 미션이었던거 같다. 그리고 그러한 아쉬운점의 주요한 원인은 조급함이었다. 너무 조급했다. 빨리 과제를 완료해야 더 많이 PR을 받을 수 있고 더 많이 배울 수 있을 것이라고 잘 못 생각했다. PR 요청을 한 후 다른 분들의 PR을 보고 결과물을 보면서 내가 잘 못 생각하다는 것을 더 확실히 알 수 있었다.

조급해하지 말자. 내가 더 배울 수 있고 좋은 결과물을 만들 수 있는 기회를 스스로 버렸다. 지금은 속도보다 배우는 것에 집중하고 더 낳은 결과물을 만들 수 있도록 노력하자. 이번 한주는 계산기 미션에서 스스로 부족하다고 느끼느 것들을 다시 개선해보는 시간을 가져봐야겠다.

리뷰에 따른 개선

드디어 첫 코드 리뷰를 받았고 리뷰 받은 내용을 바탕으로 코드를 개선하였다.

반영 내용

  1. 디렉토리 구조 변경과 필요 없는 의존성 제거
  2. if → switch로 변경
  3. 클래스명 변경(Validation → Validator)
  4. LSP 준수할 수 있도록 instanceof와 다운 캐스팅 제거
  5. 실수형 연산 가능하도록 개선

개선하며 공부한 내용

  • if → switch
    “constant expression required”로 인해 getter를 switch에서 이용할 수 없었다. 따라서 Enum에서 static 메서드stream()을 이용하여 String을 Enum type으로 변경하고 이를 switch에서 사용할 수 있도록 하였다.
  • LSP, OCP
    이 내용은 다른 곳에 정리하였다.

리뷰에 따른 개선(2)

반영 내용

  1. map을 이용하여 enum 조회 속도 향상
  2. 하드 코딩 지양
  3. 불필요한 의존성 제거
  4. 인터페이스 이름 변경

개선하며 공부한 내용

  • map을 이용한 enum 조회 속도 향상
    기존 stream을 이용한 순차 조회 방식에서 map을 이용하는 방시으로 변경하여 enum 조회 속도를 향상시켰다.

    BEFORE

    public static CommandTypes strToCommandType(String selectedCommand) throws WrongInputException{
        return Arrays.asList(CommandTypes.values()).stream()
                    .filter(commandType -> commandType.getCommandId().equals(selectedCommand))
                    .findAny()
                    .orElseThrow(() -> new WrongInputException());
    }

    AFTER

    private static final Map<String, CommandTypes> commandIds =
                Collections.unmodifiableMap(Stream.of(values())
                        .collect(Collectors.toMap(CommandTypes::getCommandId, Function.identity())));
    
    public static CommandTypes findCommandType(String selectedCommand) throws WrongInputException{
        return Optional.ofNullable(commandIds.get(selectedCommand)).orElseThrow(WrongInputException::new);
    }

    참고

  • 하드 코딩 지양
    String으로 하드 코딩된 부분을 enum으로 대체하였다. 하드코딩은 의미를 파악하게 어렵게 만들어 가독성을 떨어뜨리고 유지보수를 어려게 하니 지양하자!

  • 인터페이스 이름
    기존 Command라는 이름에서 Commandable로 인터페이스 이름을 변경하였다. '~할 수 있는'식으로 이름을 지어보자.

    • 구현 클래스 is able to 인터페이스
profile
꾸준히 나아가자 🐢

0개의 댓글