게시판 관리 App 만들기(2)

hyunn·2021년 7월 5일
0

Java-basic

목록 보기
13/26
post-thumbnail

15. 메서드 문법을 이용하여 기능 별로 명령어를 묶어 관리하기

switch문의 명령어를 메서드를 이용해 분리
장점 -> 메서드로 묶어서 관리하면 코드의 재사용성, 유지보수성 높아짐
createdDates[size] = new Date(); => 현재의 날짜와 시간을 생성하여 배열에 저장

...
      switch (command) {
        case "list": list(); break;
        case "add": add(); break;
        case "update": update(); break;
        case "delete": delete(); break;
        case "view": view(); break;
        case "quit":
          break loop;
        default:
          System.out.println("지원하지 않는 명령입니다.");
      }
...
  static void list() {
    System.out.println("[게시글 목록]");
    for (int i = 0; i < size; i++) {
      System.out.printf("%d, %s, %s, %d\n", 
          i, 
          titles[i], 
          String.format("%1$tY-%1$tm-%1$td", createdDates[i]),
          viewCounts[i]);
    }
  }

  static void add() {
    System.out.println("[게시글 등록]");
    if (size == BOARD_LENGTH) {
      System.out.println("더이상 게시글을 추가할 수 없습니다.");
      return;
    }
    
    System.out.print("제목: ");
    titles[size] = keyScan.nextLine();
    System.out.print("내용: ");
    contents[size] = keyScan.nextLine();
    System.out.print("비밀번호: ");
    passwords[size] = keyScan.nextLine();
    createdDates[size] = new Date(); 
    System.out.println("게시글을 등록했습니다.");
    size++;
  }

  static void update() {
    System.out.println("[게시글 변경]");
    System.out.print("번호? ");
    int index = Integer.parseInt(keyScan.nextLine());
    if (index < 0 || index >= size) {
      System.out.println("무효한 게시글 번호입니다.");
      return;
    }
    
    System.out.printf("제목(%s)? ", titles[index]);
    String title = keyScan.nextLine();
    System.out.printf("내용(%s)? ", contents[index]);
    String content = keyScan.nextLine();
    System.out.print("정말 변경하시겠습니까?(y/N) ");
    if (!keyScan.nextLine().equals("y")) {
      System.out.println("게시글 변경을 최소하였습니다.");
      return;
    } 

    titles[index] = title;
    contents[index] = content;
    System.out.println("게시글을 변경하였습니다.");
  }

  static void delete() {
    System.out.println("[게시글 삭제]");
    System.out.print("번호? ");
    int index = Integer.parseInt(keyScan.nextLine());
    if (index < 0 || index >= size) {
      System.out.println("무효한 게시글 번호입니다.");
      return;
    }

    System.out.print("정말 삭제하시겠습니까?(y/N) ");
    if (!keyScan.nextLine().equals("y")) {
      System.out.println("게시글 삭제를 최소하였습니다.");
      return;
    } 

    for (int i = index; i < size - 1; i++) {
      titles[i] = titles[i + 1];
      contents[i] = contents[i + 1];
      viewCounts[i] = viewCounts[i + 1];
      createdDates[i] = createdDates[i + 1];
    }

    size--;
    System.out.println("게시글을 삭제하였습니다.");
  }

  static void view() {
    System.out.println("[게시글 조회]");
    System.out.print("번호? ");
    int index = Integer.parseInt(keyScan.nextLine());
    if (index < 0 || index >= size) {
      System.out.println("무효한 게시글 번호입니다.");
      return;
    }

    viewCounts[index]++;
    System.out.printf("제목: %s\n", titles[index]);
    System.out.printf("내용: %s\n", contents[index]);
    System.out.printf("조회수: %d\n", viewCounts[index]);
    System.out.printf("등록일: %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS\n", createdDates[index]);
  }

16. 클래스를 이용하여 새 데이터타입을 정의하기

static Board[] boards = new Board[BOARD_LENGTH]; -> 게시글 전체를 담을 배열 준비
한 개의 게시글 데이터를 저장할 변수 생성
Board board = new Board(); -> Board 설계도에 따라 변수를 만들고 그 주소를 리턴

...
  static class Board {
    String title;
    String content;
    String password;
    int viewCount;
    Date createdDate;
  }
  static Board[] boards = new Board[BOARD_LENGTH];
...
static void list() {
    System.out.println("[게시글 목록]");

    for (int i = 0; i < size; i++) {
      Board board = boards[i];
      System.out.printf("%d, %s, %s, %d\n", 
          i, 
          board.title, 
          String.format("%1$tY-%1$tm-%1$td", board.createdDate),
          board.viewCount);
    }
  }

  static void add() {
    System.out.println("[게시글 등록]");
    if (size == BOARD_LENGTH) {
      System.out.println("더이상 게시글을 추가할 수 없습니다.");
      return;
    }

    Board board = new Board();
    System.out.print("제목: ");
    board.title = keyScan.nextLine();
    System.out.print("내용: ");
    board.content = keyScan.nextLine();
    System.out.print("비밀번호: ");
    board.password = keyScan.nextLine();
    board.createdDate = new Date();
    boards[size++] = board;
    System.out.println("게시글을 등록했습니다.");
  }

  static void update() {
    System.out.println("[게시글 변경]");
    System.out.print("번호? ");
    int index = Integer.parseInt(keyScan.nextLine());
    if (index < 0 || index >= size) {
      System.out.println("무효한 게시글 번호입니다.");
      return;
    }

    Board board = boards[index];
    System.out.printf("제목(%s)? ", board.title);
    String title = keyScan.nextLine();
    System.out.printf("내용(%s)? ", board.content);
    String content = keyScan.nextLine();
    System.out.print("정말 변경하시겠습니까?(y/N) ");
    if (!keyScan.nextLine().equals("y")) {
      System.out.println("게시글 변경을 최소하였습니다.");
      return;
    } 

    board.title = title;
    board.content = content;
    System.out.println("게시글을 변경하였습니다.");
  }

  static void delete() {
    System.out.println("[게시글 삭제]");
    System.out.print("번호? ");
    int index = Integer.parseInt(keyScan.nextLine());
    if (index < 0 || index >= size) {
      System.out.println("무효한 게시글 번호입니다.");
      return;
    }

    System.out.print("정말 삭제하시겠습니까?(y/N) ");
    if (!keyScan.nextLine().equals("y")) {
      System.out.println("게시글 삭제를 최소하였습니다.");
      return;
    } 

    for (int i = index; i < size - 1; i++) {
      boards[i] = boards[i + 1];
    }

    size--;
    System.out.println("게시글을 삭제하였습니다.");
  }

  static void view() {
    System.out.println("[게시글 조회]");
    System.out.print("번호? ");
    int index = Integer.parseInt(keyScan.nextLine());
    if (index < 0 || index >= size) {
      System.out.println("무효한 게시글 번호입니다.");
      return;
    }

    Board board = boards[index];
    board.viewCount++;
    System.out.printf("제목: %s\n", board.title);
    System.out.printf("내용: %s\n", board.content);
    System.out.printf("조회수: %d\n", board.viewCount);
    System.out.printf("등록일: %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS\n", board.createdDate);
  }

17. 클래스를 이용하여 메서드를 분류하기

BoardHandler 클래스를 만들어 메서드들을 분리
App 클래스와 BoardHandler 클래스가 분리되면서 코드 재사용성과 유지보수성이 향상됨

[App.java]

     switch (command) {
        case "list": BoardHandler.list(); break;
        case "add": BoardHandler.add(); break;
        case "update": BoardHandler.update(); break;
        case "delete": BoardHandler.delete(); break;
        case "view": BoardHandler.view(); break;
        case "quit":
          break loop;
        default:
          System.out.println("지원하지 않는 명령입니다.");
      }
[BoardHandler.java]

public class BoardHandler {
  static final int BOARD_LENGTH = 100;
  static Board[] boards = new Board[BOARD_LENGTH];
  static int size = 0;
  static Scanner keyScan;
  ...
}

18. 데이터 목록을 다루는 코드를 재사용하기 쉽게 별도의 클래스로 분리한다.

ArrayList 클래스를 만들어 배열부분 코드를 따로 분리
데이터 목록을 다루는 코드만 따로 분리하여 재사용 가능해짐

[ArrayList.java]

public class ArrayList {
  static final int MAX_LENGTH = 100;
  static Object[] list = new Object[MAX_LENGTH];
  static int size = 0;
  static void append(Object obj) {
    list[size++] = obj;
  }

  static Object[] toArray() {
    Object[] arr = new Object[size];
    for (int i = 0; i < size; i++) {
      arr[i] = list[i];
    }
    return arr;
  }

  static Object retrieve(int index) {
    return list[index];
  }

  static void remove(int index) {
    for (int i = index; i < size - 1; i++) {
      list[i] = list[i + 1];
    }
    size--;
  }
}
[BoardHandler.java]
...
static void list() {
    System.out.println("[게시글 목록]");
    Object[] arr = ArrayList.toArray();
    int i = 0;
    for (Object item : arr) {
      Board board = (Board) item;
      System.out.printf("%d, %s, %s, %d\n", 
          i++, 
          board.title, 
          String.format("%1$tY-%1$tm-%1$td", board.createdDate),
          board.viewCount);
    }
  }
...

19. 메뉴 선택 기능을 추가

게시글 관리 기능 말고도 회원 관리 기능도 추가
메뉴선택 while문 추가
첫번째 메뉴에서 게시글/회원관리 선택할 수 있도록 함

[App.java]
...
    menuLoop: while (true) {
      System.out.println("[메뉴]");
      System.out.println("  1: 게시글 관리");
      System.out.println("  2: 회원 관리");
      System.out.print("메뉴를 선택하시오. (종료: quit) [1..2] ");
      String menuNo = keyScan.nextLine();

      switch (menuNo) {
        case "1":
          loop: while (true) {
            System.out.print("게시글 관리> ");
            String command = keyScan.nextLine();

            switch (command) {
              case "list": BoardHandler.list(); break;
              case "add": BoardHandler.add(); break;
              case "update": BoardHandler.update(); break;
              case "delete": BoardHandler.delete(); break;
              case "view": BoardHandler.view(); break;
              case "back":
                break loop;
              default:
                System.out.println("지원하지 않는 명령입니다.");
            }
            System.out.println();
          }
          break;
        case "2":
          break;
        case "quit":
          break menuLoop;
        default:
          System.out.println("메뉴 번호가 옳지 않습니다.");
      }

      System.out.println();
    }

Console
[메뉴]
1: 게시글 관리
2: 회원 관리
메뉴를 선택하시오. (종료: quit) [1..2] 1
게시글 관리> back
...
메뉴를 선택하시오. (종료: quit) [1..2] 2
...
메뉴를 선택하시오. (종료: quit) [1..2] quit
안녕히 가세요!


20. 리팩토링: extract method => 게시글 관리 메뉴 처리 코드를 별도의 메서드를 분리한다.

App.java에서 게시글 관리 코드를 별도의 execute 메서드로 분리

[App.java]
...
      switch (menuNo) {
        case "1":
          execute();
          break;
        case "2":
          break;
        case "quit":
          break menuLoop;
...

  static void execute() {
    loop: while (true) {
      System.out.print("게시글 관리> ");
      String command = keyScan.nextLine();

      switch (command) {
        case "list": BoardHandler.list(); break;
        case "add": BoardHandler.add(); break;
        case "update": BoardHandler.update(); break;
        case "delete": BoardHandler.delete(); break;
        case "view": BoardHandler.view(); break;
        case "back":
          break loop;
        default:
          System.out.println("지원하지 않는 명령입니다.");
      }
      System.out.println();
    }
...

21. 리팩토링: 메서드 이동, 클래스 이동

게시글을 다루는 일은 Board 클래스를 사용하는 BoardHandler로 옮김

[BoardHandler.java]
...
  static class Board {
    String title;
    String content;
    String password;
    int viewCount;
    Date createdDate;
  }

  static void execute() {
    loop: while (true) {
      System.out.print("게시글 관리> ");
      String command = keyScan.nextLine();

      switch (command) {
        case "list": BoardHandler.list(); break;
        case "add": BoardHandler.add(); break;
        case "update": BoardHandler.update(); break;
        case "delete": BoardHandler.delete(); break;
        case "view": BoardHandler.view(); break;
        case "back":
          break loop;
        default:
          System.out.println("지원하지 않는 명령입니다.");
      }
      System.out.println();
    }
  }
...
[App.java]
...
    // App 클래스에서 만든 Scanner 인스턴스를 BoardHandler와 같이 사용
    BoardHandler.keyScan = keyScan;
...
      switch (menuNo) {
        case "1":
          BoardHandler.execute();
          break;
...

22. 메뉴 추가하기: 계산기 기능 추가하기

ComputeHandler 클래스를 만들어 메뉴에 계산기 기능 추가

[App.java]

menuLoop: while (true) {
...
      System.out.println("  3: 계산기");
      System.out.print("메뉴를 선택하시오. (종료: quit) [1..3] ");
      String menuNo = keyScan.nextLine();
      switch (menuNo) {
...
        case "3":
          ComputeHandler.ohora();
          break;
...
[ComputeHandler.java]

public class ComputeHandler {
  static Scanner keyScan;
  
  static void ohora() {
    while (true) {
      System.out.print("계산식: (이전 메뉴: back) (예: 100 * 4) ");
      String expression = keyScan.nextLine();

      if (expression.equals("back")) {
        break;
      }

      String[] arr = expression.split(" ");
      if (arr.length != 3) {
        System.out.println("계산식의 입력이 잘못되었습니다.");
        continue;
      }

      int a = Integer.parseInt(arr[0]);
      int b = Integer.parseInt(arr[2]);
      switch (arr[1]) {
        case "+":
          System.out.printf("%d + %d = %d\n", a, b, a + b);
          break;
        case "-":
          System.out.printf("%d - %d = %d\n", a, b, a - b);
          break;
        case "*":
          System.out.printf("%d * %d = %d\n", a, b, a * b);
          break;
        case "/":
          System.out.printf("%d / %d = %d\n", a, b, a / b);
          break;
        case "%":
          System.out.printf("%d %% %d = %d\n", a, b, a % b);
          break;
        default:
          System.out.println("이 연산은 지원하지 않습니다.");
      }
    }
  }
}

Console
[메뉴]
1: 게시글 관리
2: 회원 관리
3: 계산기
메뉴를 선택하시오. (종료: quit) [1..3] 3
계산식: (이전 메뉴: back) (예: 100 4) 250 4
250 * 4 = 1000

0개의 댓글