레벨 4로 접어들면서 톰캣 만들기 미션을 하게 되었는데 제공받은 초기 코드부터가 흥미로웠다. public class Application { private static final Logger log = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { log.info("web server start."); final var tomcat = new Tomcat(); tomcat.start(); } } 위 코드만 실행 시켜도 자바 애플리케이션이 꺼지지도 않으면서 localhost:8080으로 오는 요청을 받고 있는 것이 신기해서 소스 코드를 한 번 분석해 보았다. Application { final var ..
우아한테크코스
POST 요청은 일반적으로 데이터를 body로 보낸다 @PostMapping(value = "/boards/{boardId}", params = "command=move") public ResponseEntity movePiece(@PathVariable int boardId, @RequestBody CommendDto commendDto) { gameService.move(boardId, commendDto); return ResponseEntity.ok(gameService.gameStateAndPieces(boardId)); } 처음에 위와 같이 코드를 짰었다. boardId에 해당하는 체스판을 CommandDto 안의 위치 정보를 통해 체스 말을 움직이는 요청을 처리한다. 그런데 위와 같은 피드백..
IllegalArgumentException vs IllegalStateException @Override public State proceed(Command command) { if (command.isMove()) { throw new IllegalArgumentException(CANNOT_MOVE); } if (command.isStatus()) { throw new IllegalStateException(CANNOT_GENERATE_SCORE); } // ... } IllegalArgumentException과 IllegalStateException을 혼용하여 사용하고 있었고 리뷰어가 이를 지적했다. 각 기능을 만들 때 이 두 예외를 언제 써야 하는지 정확한 기준을 잡지 못했던 것이다. 다음 글..
최상단 directory 하위에 docker directory를 생성 하위에 docker-compose.yml 파일 생성 version: "3.9" services: db: image: mysql:8.0.28 platform: linux/x86_64 restart: always ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: practice MYSQL_USER: user MYSQL_PASSWORD: password TZ: Asia/Seoul volumes: - ./db/mysql/data:/var/lib/mysql - ./db/mysql/config:/etc/mysql/conf.d - ./db/mysql/init:/d..
step1 피드백 step2 피드백 함수형 인터페이스의 과용 입력과 출력을 담당하는 View 클래스들을 게임 흐름을 담당하는 컨트롤러에서 분리하고 싶어서 함수형 인터페이스를 사용했었다. 그럼 BlackJackGame을 사용하는 클라이언트인 컨트롤러 입장에서는 드가 매우 깔끔해진다. View의 메서드들을 람다로 함수형 인터페이스로 전달한 결과다. public static void main(String[] args) { BlackJackGame blackJackGame = new BlackJackGame( InputView.askNames(), InputView::askBet, new Deck(Card.getCards())); OutputView.printGamers(blackJackGame.getDeale..
로또 미션 로또 번호를 캐싱하여 불필요한 인스턴스 생성 방지 private static final Map lottoNumbers = new HashMap();; static { for (int number = MINIMUM_LOTTO_NUMBER; number LottoNumber.getInstance(source)) .isInstanceOf(IllegalArgumentException.class); } 테스트를 작성할 때 경곗값을 잘 정의하는 것이 중요하다. 로또 번호의 비즈니스 로직이 1부터 45 사이의 정수여야 하기 때문에 예외로 0과 46을 넣어서 테스트했더니 경곗값을 잘 활용했다며 리뷰어님이 칭찬해 주셨다. 객체 역할과 책임 설계 객체에게 역할과 책임을 알맞게 배분하는 일은 항상 어렵고 고민이 ..
자동차 경주 미션 하나의 객체가 많은 책임을 맡지 않도록 하자 public class InputView { // ... private static final Scanner scanner = new Scanner(System.in); public static List getCarNames() { System.out.println(CAR_NAMES_MESSAGE); return Converter.toCarList(scanner.next()); } // ... } 사용자에게 입력을 받는 InputView 클래스이다. 자동차의 이름을 입력받아 Converter 클래스를 통해 Car 객체의 리스트를 반환하는 메서드를 가지고 있다. 그리고 Converter 클래스 안에는 자동차 이름에 대한 검증 로직이 Valida..
우아한테크코스에 대한 설명은 다음 링크를 참고해 주시길 바랍니다. 안녕하세요 더즈입니다. 본 포스팅은 우아한테크코스 4기에 지원하고 제목에서도 알 수 있듯이 최종합격까지 할 수 있었던 저의 이야기를 풀어보고자 합니다. 최종합격을 하고 시간이 한 달 가까이 지났지만 첫 블로그 게시글을 우테코 합격 회고로 하고 싶었기에 지금에라도 회고를 작성해봅니다. 지원 동기 본전공은 문과이고 복수전공으로 프로그래밍을 전공하고 있던 저는 개발자 교육 관련으로 이리저리 찾아보고 있었고 우테코에 대해 알게 되었습니다. 마침 자바를 공부하고 있었던 저는 우테코에 관심을 가지게 되었습니다. 하지만 10월부터 12월까지 이어지는 긴 지원 프로세스도 그렇고 지원자들의 수준이 대체로 높은 것 같아 지원을 망설이기도 했습니다. (이미 ..