2022.07.21 목요일/자바 정리/스태틱 필드의 한계/인스턴스 필드, 인스턴스 메서드, 생성자 사용법

Jimin·2022년 7월 22일
0

비트캠프

목록 보기
6/60

아침 알고리즘




스태틱 필드의 한계: 클래스 복제(노가다)

1단계 - 독서록 게시판을 추가한다.

  • ReadingHandler CLass 추가
  • BoardHandler class를 추가하고 코드 수정
  • App class 변경 -> 독서록 클래스 실행될 수 있도록 수정

2단계 - 방명록을 추가한다.

  • VisitHandler class 추가
  • BoardHandler class 복제, 코드 수정
  • App class 변경

3단계 - 공지사항 게시판을 추가

  • NoticeHandler class 추가

4단계 - 게시판의 글목록 크기를 자동으로 증가 시킨다.

  • BoardHandler 클래스 변경
    • processInput() 메소드 변경
    • 설정된 배열의 크기를 초과하여 게시글을 저장하고 싶기 때문에 항상 초과해서 게시글을 저장할 때마다, 현재 게시글의 총 개수의 50%씩 추가해준다.

      나누기 2 --> >> 1 과 동일하다!

  • 배열 크기 증가
    • 배열은 크기를 수정할 수 없다.
    • 따라서 배열의 크기를 수정하고 싶다면,
      원하는 크기를 갖는 새 배열을 만들어 기존 배열의 값을 복사해야 한다.
      ==> Gargabe가 과다 생산되는 문제 발생

5단계 - 나머지 게시판의 글목록 크기를 자동으로 증가시킨다.

- 중복코드의 문제점

  • 기능변경(버그 수정)시, 해당 코드를 복사해간 모든 쪽에도 변경(버그 수정)해야 한다.
  • 복사해간 코드 중에서 변경을 안하는 실수를 할 수 있다.
    ==> 유지보수가 매우 어렵다.

- 기술 부채

https://yozm.wishket.com/magazine/detail/1331/

인스턴스 필드, 인스턴스 메서드, 생성자 사용법

  • BoardHandler에서 게시글 목록을 저장과 관련된 필드를 인스턴스 필드로 변경한다.
  • BoardHandler의 기존 메서드를 인스턴스 필드를 다룰 수 있게 인스턴스 메서드로 변경한다.
  • 게시판을 추가할 때 인스턴스를 생성한다.

1단계 - BoardHandler의 필드와 메서드를 인스턴스 멤버로 전환한다.

- 변수 선언

-- 클래스 변수

  • 모든 게시판이 공유하는 데이터는 클래스 변수에 저장한다.
  • 왜? -> 클래스 변수클래스를 로딩할 때 한 번만 생성되기 때문이다.

-- 인스턴스 변수

  • 각 게시판이 별도로 관리해야 할 데이터는 인스턴스 변수에 저장한다.
  • 왜? -> 인스턴스 변수는, 게시판 별생성할 수 있기 때문이다.
  • BoardHandler 클래스 변경
    • 관련 필드를 인스턴스 필드로 변경한다.
    • 인스턴스 필드를 다루는 메서드는 인스턴스 메서드로 변경한다.

      this는 인스턴스 필드에 원래 붙여야 하는건데,
      안 붙여도 컴파일러가 자동으로 붙여주는 것이다.

    • App 클래스에서 BoardHandler에 있는 execute 메서드를 호출할 때, 만들어둔 BoardHandler의 인스턴스 변수, boardHandler를 통해 excute 메서드에 접근하게 되는데, 이때 이 boardHandler의 주소는 this라는 내장변수에 저장이 된다.
    • 로컬 필드는 노란색, 인스턴스 필드는 파란색으로 표시된다.
    • 인스턴스 필드에게는 인스턴스 주소를 넘겨주어야 한다!(같은 클래스 내부라 this를 생략할 수 있을지라도!)
    • static 필드는 이탤릭체로 표시된다.
    • static 필드는 인스턴스 주소로 접근이 가능하지만, 그렇게 되면 instance 필드와 헷갈리기 때문에 그렇게 접근하지 않고, 클래스 이름을 통해 접근하거나 아예 생략한다.
  • App class 변경
    • BoardHandler 인스턴스 변수 생성
    • 게시판 종류별로 변수들을 생성해서 이용한다.
    • 변수는 while 밖에 만들어 준다.
      -> 한 번 만든 거 계속 사용해야 heap에 저장되어 있는 메모리를 사용할 수 있기 때문이다.

2단계 - 각 게시판의 제목을 따로 다룰 수 있게 한다.

  • BoardHandler 클래스 수정
    • 게시판 제목을 저장할 인스턴스 필드 title을 추가한다.
    • 게시판 제목을 출력할 수 있도록 관련 메서드를 변경한다.
    • 메뉴 처리 메서드에서 작업 메뉴를 출력할 때 게시판 제목을 사용하도록 변경한다.(생성자 사용X, 인스턴스로 접근)

3단계 - 게시판의 제목을 설정하지 않으면 쓸 수 없도록 제한을 가한다.

  • BoardHandler 클래스 변경

    • 생성자를 사용하면, 메서드를 실행할 때 필요한 필수 입력값강제로 설정하게 만들 수 있다.
    • 기본 생성자의 접근 범위는, 무조건 public으로 선언된다.
    • 인스턴스를 생성할 떄, 게시판 제목을 저장하는 title 필드의 값을 반드시 입력하도록 생성자를 추가한다.
      (제목을 반드시 입력하도록 생성자를 추가한다.)
    • 인스턴스 메서드가 제대로 작업할 수 있도록 인스턴스 필드를 유효한 값으로 설정하기 위해 생성자를 이용한다.

4단계 - 리팩토링: 사용자의 명령을 처리하는 메서드의 이름을 적절하게 변경한다.

  • BoardHandler 클래스 변경

    원래 메소드명은 동사구로 생성하는데, 가끔 전치사구로 on으로 시작하게 만드는 경우가 있다.

    • processList() -> onList()
    • processDetail() -> onDetail()
    • processInput() -> onInput()
    • processDelete() -> onDelete()
    • processUpdate() -> onUpdate()

5단계 - 다양한 상황에서 사용할 생성자를 추가한다.

  • BoardHandler class 변경
    • Board() 기본 생성자 추가
    • Board(int) 생성자 추가
    • Board(String) 생성자 추가

인스턴스 목록을 다루는 코드를 분리: High Cohesion 구현(재사용성 강화)

1단계 - BoardHandler에서 인스턴스 목록을 다루는 코드를 분리한다.

  • 하나의 클래스는 하나의 역할만을 맡는 것이 좋다!

  • BoardHandler 클래스

    • 목록과 관련된 필드를 BoardList 클래스로 옮긴다.
    • 각 메서드에서 데이터 목록을 다루는 코드를 BoardList 클래스로 옮긴다.(분리한다.)
      ==> High cohesion을 위해서
  • BoardList 클래스 추가하기

    • toArray()라는 메서드를 만들어서 새로 늘어난 게시글 개수만큼 늘어난 게시글들이 들어있는 Board 객체 배열을 다시 BoardHandler로 돌려준다.
      --> 이 경우, board 배열에는 결론적으로 실제 게시글 개수만큼 들어 있기 때문에 밑에와 같이 for문을 이용할 수 있다.
  • 그냥 boards를 리턴해버리면, 게시글 등록 가능 최대 배열 범위수, 예를 들면, 1개 등록했는데 사이즈는 3인 배열이 리턴돼서 1개 이외의 나머지 배열 즉, 인덱스 1, 0에는 null 값이 들어가서 오류가 나게 된다.

처음부터 끝까지 for문을 돌릴 경우 밑에와 같이 for문을 이용해주자!

Board[] list = this.bordList.toArray();
for(Board board:list){
}

내가 작성한 onUpdate()가 작동하지 않았던 이유

  • 잘못됐던 코드: 파라미터로 받아오는 변수도 결국 로컬 변수인데, 나는 로컬 변수의 값만을 바꿨었다.
void onUpdate() {
    //------------------- menu 5 --------------------------
    System.out.printf("[%s 수정]\n", this.title);
    if(boardList.boardCount ==0) {
      System.out.println("현재 존재하는 게시글이 없습니다!");
      return;
    }
    int editNo = Prompt.inputInt("변경할 게시글 번호?");
    Board board = this.boardList.get(editNo);
    if(board == null) {
      System.out.println("잘못된 번호를 입력하셨습니다. 해당 게시글 번호는 존재하지 않습니다.\n올바른 번호를 입력해 주십시오.");
      return;
    }else {
      edit(board);
      this.onList();
      System.out.println(board.title + board.content + board.writer);
    }
  }

  void edit(Board board) {
    String title= Prompt.inputString("제목? " + "("+board.title+")");
    String content= Prompt.inputString("내용? "+ "("+board.content+")");
    String writer = Prompt.inputString("작성자? "+ "("+board.writer+")");
    String password = Prompt.inputString("암호? "+ "("+board.password+")");
    if(isEdit()) {
      board = makeBoard(title, content, writer, password);
     System.out.println("성공적으로 변경되었습니다!");
    }else {
      System.out.println("변경을 취소하였습니다.");
      return;
    }
  }
  static boolean isEdit() {
    char ans = Prompt.inputChar("변경하시겠습니까?(y/n) ");
    if(ans=='y')return true;
    else if(ans=='n') return false;
    return ans =='y'? true:false;
  }
  Board makeBoard(String title, String content, String writer, String pwd) {
    Board board2 = new Board();
    board2.title =title;
    board2.content =content;
    board2.writer=writer;
    board2.password = pwd;
    
    return board2;
  }
  • 수정한 코드: 파라미터로 주소 값을 받아와서 바로 직접적으로 변경해버렸다.
void edit(Board board) {
    String title= Prompt.inputString("제목? " + "
    ("+board.title+")");
    String content= Prompt.inputString("내용? "+ "
    ("+board.content+")");
    String writer = Prompt.inputString("작성자? "+ 
    "("+board.writer+")");
    String password = Prompt.inputString("암호? "+ 
    "("+board.password+")");
    if(isEdit()) {

      makeBoard(board, title, content, writer, password);
      System.out.println("성공적으로 변경되었습니다!");

    }else {
      System.out.println("변경을 취소하였습니다.");
      return;
    }
  }
  static boolean isEdit() {
    char ans = Prompt.inputChar("변경하시겠습니까?(y/n) ");
    if(ans=='y')return true;
    else if(ans=='n') return false;
    return ans =='y'? true:false;
  }

  Board makeBoard(Board board, String title,
  String content, String writer, String pwd) {
    board.title =title;
    board.content =content;
    board.writer=writer;
    board.password = pwd;
    return board;
  }
profile
https://github.com/Dingadung

0개의 댓글