2주차 미션 회고 feat. 우테코

2023. 11. 6. 01:16·Backend/회고
반응형
1주 차의 Problem을 해결하자.

 

회고의 목적은 문제를 인식하고 개선을 하는 것입니다.

 

1주 차의 Problem

1. JDK 17을 효과적으로 활용하지 못했다.

이 문제점을 해결하기 위해 JDK 17의 Record을 사용했습니다.

public record RoundResultDto(String name, int location) {
}

public record GameResultDto(List<String> winners) {
}

Record를 사용한 이유

  1. 간결성과 불변성이라는 장점을 가지고 있다.
  2. 필드 정의와 getter 메서드 작성 등의 반복적인 작업을 한 줄로 간결하게 표현할 수 있습니다.
  3. equals, toString, hashCode 등의 메서드를 자동으로 생성해 줍니다.

 

2. 의존성 주입

    private final InputView inputView;
    private final OutputView outputView;
    private final RacingService racingService;

    public RacingController(InputView inputView, RacingService racingService, OutputView outputView) {
        this.outputView = outputView;
        this.inputView = inputView;
        this.racingService = racingService;
    }

기존의 필드 주입에서 생성자 주입으로 전환하게 된 이유

  1. 필드 주입은 객체의 불변성을 보장하기에 어려움이 있습니다.
  2. 필드 주입은 객체가 필요로 하는 의존성을 알 수 없습니다.
  3. 의존성 주입은 인자를 통해 전달해 주기 때문에 객체가 필요로 하는 의존성을 알 수 있습니다.

 

3. Controller가 아닌 Model에서 View에게 값을 넘겨주었다.

MVC패턴에서는 Controller을 통해 View에게 값을 전달해줘야 한다고 알았는데, 공부를 해보니 잘못된 말이었다.

https://solution-is-here.tistory.com/200

 

[왜?] MVC 패턴을 선택했을까? feat.우테코

MVC는 디자인 패턴일까? 아키텍처 패턴일까? 위의 질문은 내가 요즘 만나는 개발자마다 묻는 공통 질문이다. "디자인 패턴이다," "아키텍처 패턴이다"라는 의견이 주로 반반 나오는 것 같다. 1. MVC

solution-is-here.tistory.com

각 사용자에게 다르게 보이는 코드는 Model에게 데이터를 받아서 출력합니다. 

각 사용자에게 다르게 보여지는 값 외에는 Controller에서 View에게 값을 전달해서 출력합니다.

 

2주 차에서는 일급 컬렉션을 포함하고 있는 클래스에서 비즈니스 로직을 처리함으로써 Model에서 처리하지 않았습니다.

public class Cars {
    private static final int THRESHOLD = 3;
    private List<Car> carList;

    public Cars(List<String> carNames) {
        this.carList = carNames.stream()
                .map(Car::new)
                .collect(Collectors.toList());
    }

    public void playGame() {
        for (Car car : carList) {
            checkNumberAndMoveCar(car);
            printCarInfo(car);
        }
        ConsoleOutput.printNewLine();
    }
    
    private void printCarInfo(Car car) {
        OutputView outputView = new OutputView();
        outputView.printRoundResult(car.nameAndLocation());
    }
}

 

printCarInfo는 각 라운드별 정보를 출력하는 메서드인데 이때, 라운드별 정도는 각 사용자마다 다르게 보는 화면이므로 일급 컬렉션을 포함한 클래스에서 바로 View로 값을 전달해 출력했다.

 

4. 1주 차의 Problem을 해결하면서 느낀 점

1주차의 Problem을 개선하면서 참 많은 것들을 느꼈다.

"왜? 이렇게 했을까?"라는 생각을 가장 많이 했던 것 같다. 그만큼 우테코를 통해 한 주 동안 폭풍성장한 나를 볼 수 있었다.

무엇보다도 블로그를 통해 정리를 한 뒤,  사용해 보니 정리를 하기 전에 사용했던 것보다 훨씬 수월하게 사용할 수 있어 좋았다.

3주 차 문제를 풀 때도 새로 적용하고자 하는 개념이 있으면 블로그로 먼저 작성을 해야겠다는 생각을 했다.

 


Keep

1. Dto를 통한 데이터 전달

Dto가 아닌 인자를 통해 데이터를 전달할 수도 있지만 Dto를 통해 전달하는 가장 큰 이유는 "유지보수성"입니다.

인자를 통해 데이터를 전달한다고 가정했을 때 매개변수의 개수가 4~5개이면 보내야 하는 인자의 종류도 4~5개이므로 메서드가 복잡해질 수 있습니다. 또한 매개변수의 순서에 대한 의존성이 존재해, 결합도가 높아지는 단점이 있습니다.

이러한 단점을 해결하고자 Dto를 통해 데이터 전달하는 방법을 3주 차에서도 적용하려고 합니다.

 

2. MVC 패턴

MVC 패턴의 가장 큰 장점은 역할별로 클래스를 나눔으로 인해, 응집도가 높아지고 결합도가 낮아지죠.

그러므로 인해 자연스럽게 유지보수성이 높아집니다.

public class RacingController {
    private final InputView inputView;
    private final OutputView outputView;
    private final RacingService racingService;

    public RacingController(InputView inputView, RacingService racingService, OutputView outputView) {
        this.outputView = outputView;
        this.inputView = inputView;
        this.racingService = racingService;
    }

    public void run() {
        racingGameStart();
    }

    private void racingGameStart() {
        List<String> carNames = getCarNames();
        Cars cars = new Cars(carNames);

        int tries = getTries();
        racingGame(cars, tries);
    }

    private List<String> getCarNames() {
        ConsoleOutput.displayGetCarNameMessage();
        String input = inputView.getCarNames();
        List<String> carNames = racingService.stringToList(input);
        InputValidator.isLengthGreaterThanFive(carNames);
        return carNames;
    }

    private int getTries() {
        ConsoleOutput.displayTryMessage();
        int tries = inputView.getTries();
        InputValidator.isGreaterThanZero(tries);
        ConsoleOutput.printNewLine();
        return tries;
    }

    private void racingGame(Cars cars, int tries) {
        ConsoleOutput.displayRaceResultMessage();
        IntStream.range(0, tries)
                .forEach(i -> cars.playGame());
        outputView.printGameResult(cars.getWinner());
    }
}

 

위 코드는 2주 차 미션의 Controller 클래스입니다.

Controller 클래스에서 일급 컬렉션을 포함하고 있는 함수를 통해 데이터를 가공하고, View를 통해 출력하고 있는 모습을 볼 수 있습니다. 만약 일급 컬렉션을 포함하고 있는 함수 내부 로직이 변경된다고 가정했을 때 이는 Controller에게 전혀 영향을 주지 않습니다. 이처럼 MVC는 코드의 역할이 분리되어 있기 때문에 필요한 부분을 신속하게 수정할 수 있습니다.

 

3.  도메인 로직을 생성하자

public class Car {
    private String name;
    private int location;

    public Car(String name) {
        this.name = name;
    }

    public void moveCar() {
        location += 1;
    }

    public RoundResultDto nameAndLocation() {
        return new RoundResultDto(name, location);
    }

    public boolean isSameLocation(int otherLocation) {
        return this.location == otherLocation;
    }

    public String name() {
        return this.name;
    }

    public int location() {
        return this.location;
    }
}

 

위 코드는 도메인 로직을 포함하고 있는 Car 클래스입니다.

이 클래스는 Car의 상태를 변화하거나 조회하는 로직을 내부에 포함하고 있으므로, 수정이 필요할 경우 해당 클래스만을 수정하면 되어 유지보수가 편합니다. 또한 도메인 객체는 다른 부분에서 재사용될 수 있으므로 재사용성이 크게 높아집니다. 그리고 테스트를 할 때 특정 입력에 대한 올바른 출력, 상태 변화를 하는지 테스트하기에 용이해집니다.

 

Problem

1. 값을 하드코딩 하지 않는다.(공통 피드백)

public class Car {
    private String name;
    private int location;

    public Car(String name) {
        this.name = name;
    }

    public void moveCar() {
        location += 1;
    }
}

Car 클래스의 moveCar 메서드를 보면 location += 1;을 하는 모습을 볼 수 있습니다.

이때 1은 차가 움직이는 거리임으로 변하지 않는 값입니다. 

이러한 값들은 상수로 정의를 해야 합니다.

 

2.  변수 이름에 자료형은 사용하지 않는다. (공통 피드백)

private List<Car> carList;

변수 이름에 자료형, 자료구조 등을 사용하지 않습니다.

 

3.  기능 목록을 업데이트한다. (공통 피드백)

2주 차 미션의 커밋 기록을 보면 끝낸 뒤, 한꺼번에 기능 목록을 업데이트하는 커밋을 볼 수 있습니다.

시작할 때 모든 기능 목록을 완벽하게 정리해야 한다는 부담을 가지기보다는 기능을 구현해 가면서 문서를 업데이트해야 한다. (죽은 문서보다는 살아있는 문서로)

 

Try

1. 핵심 기능에 가까운 부분부터 작게 테스트를 만들어나간다.

ex) 물건을 구매했을 때 한도 내의 물건인지 확인하고, 결과를 알려준다.
-> 물건을 구매했을 때 한도내의 물건이면 구매를 진행한다.
-> 물건을 구매했을 때 한도 초과를 한다면 구매를 진행하지 않는다.

 

2. 구현 순서도 코딩 컨벤션이다.

상수 - 멤버 변수 - 생성자 - 메서드 순으로 작성해 보자.

 

3. else를 사용하지 말자

if에서 return을 사용해 else를 사용하지 말자.

 

다짐

주차를 거듭할수록 실력이 기하급수적으로 늘어나는 것을 느낄 수 있어서 너무 뿌듯했다.

하지만 공통 피드백을 보고 아직도 내가 잘못 알고 있는 게 많구나 라는 생각을 했다.

프리코스를 통해서 많은 것들을 접해서 좋고, 발전해서 좋다.3주 차도 파이팅

반응형
저작자표시 동일조건
'Backend/회고' 카테고리의 다른 글
  • 4주차 미션 회고 feat. 우테코
  • 3주차 미션 회고 feat. 우테코
  • 1주차 미션 회고 feat. 우테코
코딩하는_대학생
코딩하는_대학생
Java Developer, Open Source Enthusiast, Proud Son
  • 코딩하는_대학생
    코딩하는 대학생에서 개발자까지
    코딩하는_대학생
  • 전체
    오늘
    어제
    • 분류 전체보기 (216)
      • 코딩하는 대학생의 책 추천 (8)
        • 클린코드 (5)
        • 헤드퍼스트 디자인패턴 (3)
      • Backend (6)
        • Spring (14)
        • AWS (3)
        • 회고 (4)
        • Redis (5)
        • 다양한 시각에서 바라본 백엔드 (3)
      • Python (35)
        • 개념 및 정리 (15)
        • 백준 문제풀이 (20)
      • JAVA (17)
        • 개념 및 정리 (14)
        • 백준 문제풀이 (2)
      • 왜? (7)
      • C언어 (42)
        • 개념 및 정리 (9)
        • 백준 문제풀이 (32)
      • 개인 공부 (27)
        • 대학 수학 (5)
        • 대학 영어 (10)
        • 시계열데이터 처리 및 분석 (5)
        • 컴퓨터 네트워크 (6)
        • 운영체제 (1)
      • 솔직 리뷰 (23)
        • 꿀팁 (6)
        • IT기기 (1)
        • 국내 여행 (7)
        • 맛집 (2)
        • 알바 리뷰 (2)
      • 대외활동 (17)
        • 체리피우미 3기 (4)
        • 꿀잠이들 6기 (13)
      • 음식 평가 (1)
      • 일상 & 근황 (2)
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
코딩하는_대학생
2주차 미션 회고 feat. 우테코
상단으로

티스토리툴바