ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 우아한 테크코스 - 3기 3주 차 프리코스 후기
    생각과 일상/혼자의 생각 2020. 12. 18. 23:35

    3주 차답게 가장 오랜 시간 걸리고 어렵게 느껴졌던 3주 차 미션.

    처음 미션을 받고 기능 구현 목록만 적어두고 며칠을 고민했다. 어떻게 구현해야 할지 고민하면서 enum에 대해 알게 됐고, 해당 기능을 써서 완성해보자 마음먹었다. 이번 글은 내일 최종 테스트인 관계로 미션에 대한 리뷰는 가볍게 넘어가고 전체적인 프리코스 후기에 대해 적어본다.

     

     

     

    1. enum을 활용한 메인화면 구현

    package subway.view;
    
    import subway.domain.LineRepository;
    
    import java.util.Arrays;
    import java.util.function.Supplier;
    
    public enum MainMenu {
        STATION_MANAGEMENT("1", "역 관리", () -> StationConsole.selectMenu()),
        LINE_MANAGEMENT("2", "노선 관리", () -> LineConsole.selectMenu()),
        SECTION_MANAGEMENT("3", "구간 관리", () -> SectionConsole.selectMenu()),
        PRINT_SUBWAY_MAP("4", "지하철 노선도 출력", () -> OutputViewOfInfo.printSubwayMap(LineRepository.lines)),
        QUIT("Q", "종료");
    
        private String title;
        private String menuName;
        private Supplier<Boolean> next;
    
        MainMenu(String title, String menuName) {
            this.title = title;
            this.menuName = menuName;
        }
    
        MainMenu(String title, String menuName, Supplier<Boolean> next) {
            this.title = title;
            this.menuName = menuName;
            this.next = next;
        }
    
        public static boolean isValidTitle(String input) {
            return Arrays.stream(values())
                    .anyMatch(menu -> menu.getTitle().equals(input));
        }
    
        public boolean move(String title) {
            return next.get();
        }
    
        public static MainMenu moveByKey(String input) {
            return Arrays.stream(values())
                    .filter(menu -> menu.getTitle().equals(input))
                    .findAny()
                    .get();
        }
    
        public String getTitle() {
            return title;
        }
    
        public String getMenuName() {
            return menuName;
        }
    }
    
    package subway.view;
    
    import java.util.Arrays;
    
    public class MainConsole {
        private static final String CURRENT_MENU = "## 메인화면";
        public void showMenu() {
            System.out.println(CURRENT_MENU);
            Arrays.stream(MainMenu.values())
                    .forEach(menu -> {
                        System.out.println(menu.getTitle() + ", " + menu.getMenuName());
                    });
        }
    
        public MainMenu selectMenu() {
            while (true) {
                String input = InputView.getSelectMenu();
                if (!MainMenu.isValidTitle(input)) {
                    OutputViewOfError.cannotSelectMenu();
                    continue;
                }
                return MainMenu.moveByKey(input);
            }
        }
    }
    
    enum과 함수형 인터페이스를 활용해 title과 같은 입력이 들어오는 경우 next를 실행하도록 했다. stream을 배우고 적용하며 아직 중개 오퍼레이션인지 종료 오퍼레이션인지 헷갈리는 부분들이 많았다. 

     

     

    2. 사용자 입력과 출력 부분

    package subway.view;
    
    import java.util.Scanner;
    
    public class InputView {
        private static final String ENTER = "\n";
        private static final String SELECT_MENU = ENTER + "## 원하는 기능을 선택하세요.";
        private static final String REGISTER_STATION = ENTER + "## 등록할 역 이름을 입력하세요.";
        private static final String DELETE_STATION = ENTER + "## 삭제할 역 이름을 입력하세요.";
        private static final String REGISTER_LINE = ENTER + "## 등록할 노선 이름을 입력하세요.";
        private static final String REGISTER_UPSTREAM_STATION = ENTER + "## 등록할 노선의 상행 종점역 이름을 입력하세요.";
        private static final String REGISTER_DOWNSTREAM_STATION = ENTER + "## 등록할 노선의 하행 종점역 이름을 입력하세요.";
        private static final String DELETE_LINE = ENTER + "## 삭제할 노선 이름을 입력하세요.";
        private static final String LINE_IN_SECTION = ENTER + "## 노선을 입력하세요.";
        private static final String STATION_IN_SECTION = ENTER + "## 역이름을 입력하세요.";
        private static final String ORDER_IN_SECTION = ENTER + "## 순서를 입력하세요.";
        private static final String DELETE_LINE_IN_SECTION = ENTER + "## 삭제할 구간의 노선을 입력하세요.";
        private static final String DELETE_STATION_IN_SECTION = ENTER + "## 삭제할 구간의 역을 입력하세요.";
    
        private static Scanner scanner = new Scanner(System.in);
    
        public static String getSelectMenu() {
            System.out.println(SELECT_MENU);
            String input = scanner.nextLine();
            return input;
        }
    
        public static String getRegisterStation() {
            System.out.println(REGISTER_STATION);
            String input = scanner.nextLine();
            return input;
        }
    
        public static String getDeleteStation() {
            System.out.println(DELETE_STATION);
            String input = scanner.next();
            return input;
        }
    
        public static String getRegisterLine() {
            System.out.println(REGISTER_LINE);
            String input = scanner.next();
            return input;
        }
    
        public static String getRegisterUpstreamStation() {
            System.out.println(REGISTER_UPSTREAM_STATION);
            String input = scanner.next();
            return input;
        }
    
        public static String getRegisterDownstreamStation() {
            System.out.println(REGISTER_DOWNSTREAM_STATION);
            String input = scanner.next();
            return input;
        }
    
        public static String getDeleteLine() {
            System.out.println(DELETE_LINE);
            String input = scanner.next();
            return input;
        }
    
        public static String getLineInSection() {
            System.out.println(LINE_IN_SECTION);
            String input = scanner.next();
            return input;
        }
    
        public static String getStationInSection() {
            System.out.println(STATION_IN_SECTION);
            String input = scanner.next();
            return input;
        }
    
        public static String getOrderInSection() {
            System.out.println(ORDER_IN_SECTION);
            String input = scanner.next();
            return input;
        }
    
        public static String getDeleteLineInSection() {
            System.out.println(DELETE_LINE_IN_SECTION);
            String input = scanner.next();
            return input;
        }
    
        public static String getDeleteStationInSection() {
            System.out.println(DELETE_STATION_IN_SECTION);
            String input = scanner.next();
            return input;
        }
    
    }
    package subway.view;
    
    public class OutputViewOfError {
        private static final String ERROR = "\n" + "[ERROR] ";
        private static final String CANNOT_SELECT_MENU = "선택할 수 없는 기능입니다.\n";
        private static final String DUPLICATED_STATION = "이미 등록된 역 이름입니다.\n";
        private static final String DUPLICATED_LINE = "이미 등록된 노선 이름입니다.\n";
        private static final String NAME_LENGTH_ERROR = "이름은 2글자 이상이어야 합니다.\n";
        private static final String STATION_IN_LINE = "노선에 등록되어 있는 역은 삭제할 수 없습니다.\n";
        private static final String NOT_IN_STATION = "종점역은 이미 등록된 역만 추가 가능합니다.\n";
        private static final String CANNOT_FIND_LINE = "등록되어 있지 않은 노선입니다.\n";
        private static final String CANNOT_FIND_STATION = "등록되어 있지 않은 역입니다.\n";
        private static final String NOT_VALID_ORDER = "올바르지 않은 순서입니다.1부터 현재 노선의 길이+1 까지만 입력 가능합니다.\n";
        private static final String CANNOT_DELETE_UNDER_TWO_STATION = "2개 이하의 역이 등록된 노선은 삭제할 수 없습니다.\n";
    
        public static void cannotSelectMenu() {
            System.out.println(ERROR + CANNOT_SELECT_MENU);
        }
    
        public static void isDuplicatedStation() {
            System.out.println(ERROR + DUPLICATED_STATION);
        }
    
        public static void isDuplicatedLine() {
            System.out.println(ERROR + DUPLICATED_LINE);
        }
    
        public static void isNotValidNameLength() {
            System.out.println(ERROR + NAME_LENGTH_ERROR);
        }
    
        public static void isInLine() {
            System.out.println(ERROR + STATION_IN_LINE);
        }
    
        public static void isNotInStationList() {
            System.out.println(ERROR + NOT_IN_STATION);
        }
    
        public static void notInLineList() {
            System.out.println(ERROR + CANNOT_FIND_LINE);
        }
    
        public static void notInStationList() {
            System.out.println(ERROR + CANNOT_FIND_STATION);
        }
    
        public static void isNotValidOrder() {
            System.out.println(ERROR + NOT_VALID_ORDER);
        }
    
        public static void lineLengthError() {
            System.out.println(ERROR + CANNOT_DELETE_UNDER_TWO_STATION);
        }
    
    }
    
    intputview에서는 개행 문자를 상수로 처리해 메서드 내에서 메시지만 표시할 수 있도록 만들었다. 상수가 많다 보니 오히려 안 좋았던 점이 네이밍을 하는 부분이었다. 특히 에러를 출력하는 부분에선 정확한 네이밍을 하지 않고 약간 추상적으로 네이밍을 하다 보니 실제 오류 내용을 출력해야 하는 부분에서 잘못된 내용의 오류 메시지가 출력되기도 했다. 
    예외 처리를 하는 부분에선 이게 여기 클래스에서 처리하는 게 맞을까? 하는 의심들이 계속 들었다. 

     

    이번 미션도 역시나 MVC 디자인으로 구현하고자 했다. 미션을 진행하는 동안 기능을 구현하는 대로 커밋하는 게 익숙하지 않아서 적어놓은 구현 목록 순서대로 커밋하지 못한 부분들이 많았고, 오타가 있는데도 그냥 커밋한 흔적들도 보여서 제출한 코드를 다시 봤을 때 많이 부끄러웠다. 사용하지 않은 메서드들이나 상수들은 지우긴 했지만 분명 중복되는 기능을 하는 메서드들도 있었다. 그리고 정확하게 MVC 모델로 구현하지도 못했고 한 클래스가 너무 많은 책임을 지고 있다기도 하고.. 여전히 많이 부족함을 느낀다. 다른 사람들이 짠 코드들을 보면서 잘하는 사람들이 정말 많다는 것을 느껴 같이 붙어서 좀 많이 배우고 싶다는 생각도 했다.

     

    아직 OOP 방식의 프로그래밍은 참 어렵게만 느껴진다. 특히 설계하는 부분에서 제대로 설계했는지 판단이 잘 서지 않았고, 프로그램을 돌렸을 때 에러가 나거나 원하는 대로 작동하지 않으면 어떤 부분이 문제가 됐는지 찾는데서 시간을 많이 보냈다. 다른 분들은 테스트 코드까지 작성해가면서 제출하던데 많이 부럽다..

     

    인스턴스를 활용하거나 상속이나 인터페이스를 활용해서 OOP가 가진 장점들을 활용하고 싶었는데, 알고 있는 것과 프로그래밍하며 적용시키는 것은 완전 다른 것이란 생각이 들었다.

    그리고 드디어 내일 원래는 오프라인 코테지만 상황이 상황이다보니 온라인으로 변경이 되었고, 최종 테스트가 기다리고 있다.

    잘하시는 분들이 워낙 많다 보니 솔직히 좋은 결과를 기대는 못 한다. 프리코스 기간에 비하면 굉장히 짧은 시간 내에 모든 기능을 구현하고 오류도 없어야 할 것이므로 목표는 한 가지라도 제대로 구현하자는 것으로 잡아야겠다. 

     

    3주간의 프리코스 기간 동안이라도 많이 배우고, 성장할 수 있었다. 스스로 성장하는 방법을 조금이나마 알게 되어 값진 시간이었다 ! 좋은 결과가 있다면 좋겠지만 욕심이고, 잘하시는 분들이 너무 많다.... 

Designed by Tistory.