Posts 학원 #28일차: 인스턴스 멤버, 생성자, 캡슐화
Post
Cancel

학원 #28일차: 인스턴스 멤버, 생성자, 캡슐화

클래스 의존 관계

  • App입장에서는 MemberHandler, Project Handler는 의존객체이다.
  • Project Handler 입장에서는 MemberHandler가 의존객체이다.
  • MemberHandler가 컴파일되면 ProjectHandler가 컴파일된다.
  • 서로 쌍방향으로 참조되면 크로스 레퍼런스로로 무한으로 컴파일이 된다.
  • 쌍방향 레퍼런스를 쓸 수밖에 없는 상황이면? 인터페이스를 통해 간접적인 관계를 만들어주자.

물론 이것은 이론 상의 상황이고 요즘은 컴파일러가 좋아서 무한으로 컴파일되지는 않는다.

v11 클래스 멤버의 한계

클래스 필드(스태틱 필드)는 클래스를 로딩할 때 생성된다. 클래스는 최초 사용 시점에 한 번만 로딩되기 때문에 스태틱 필드도 한 번만 생성된다.

실습 목표: 클래스 필드 상태에서 기능을 확장하는 방법과 그 문제점을 확인한다.

방법1 ) 각각의 스태틱 멤버를 하나씩 늘리기

BoardHandler

1
2
3
4
5
6
7
8
9
10
11
static final int LENGTH = 100;
static Board[] list = new Board[LENGTH]; 
static int size = 0;

static Board[] list2 = new Board[LENGTH]; 
static int size2 = 0;

public static void add() {}
public static void add2() {}
public static void list() {}
public static void list2() {}

결과적으로 Board 코드가 무한정 늘어나게 된다.

방법2) BoardHandler 클래스를 늘리기

App

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.eomcs.pms;

import com.eomcs.pms.handler.BoardHandler;
import com.eomcs.pms.handler.BoardHandler2;
import com.eomcs.pms.handler.BoardHandler3;
import com.eomcs.pms.handler.BoardHandler4;
import com.eomcs.pms.handler.BoardHandler5;
import com.eomcs.pms.handler.BoardHandler6;
import com.eomcs.pms.handler.MemberHandler;
import com.eomcs.pms.handler.ProjectHandler;
import com.eomcs.pms.handler.TaskHandler;
import com.eomcs.util.Prompt;

// 1) `Prompt` 클래스를 별도의 패키지로 분류한다
// 2) 핸들러 클래스들을 별도의 패키지로 분류한다
public class App {

  public static void main(String[] args) {
    
    loop:
      while (true) {
        String command = Prompt.inputString("명령> ");

        switch (command) {
          case "/board/add": BoardHandler.add(); break;
          case "/board/list": BoardHandler.list(); break;
          case "/board2/add": BoardHandler2.add(); break;
          case "/board2/list": BoardHandler2.list(); break;
          case "/board3/add": BoardHandler3.add(); break;
          case "/board3/list": BoardHandler3.list(); break;
          case "/board4/add": BoardHandler4.add(); break;
          case "/board4/list": BoardHandler4.list(); break;
          case "/board5/add": BoardHandler5.add(); break;
          case "/board5/list": BoardHandler5.list(); break;
          case "/board6/add": BoardHandler6.add(); break;
          case "/board6/list": BoardHandler6.list(); break;
          case "/member/add": MemberHandler.add(); break;
          case "/member/list": MemberHandler.list(); break;
          case "/project/add": ProjectHandler.add(); break;
          case "/project/list": ProjectHandler.list(); break;
          case "/task/add": TaskHandler.add(); break;
          case "/task/list": TaskHandler.list(); break;
          case "quit":
          case "exit": System.out.println("안녕!"); break loop;
          default: System.out.println("실행할 수 없는 명령입니다.");
        }
        System.out.println(); // 이전 명령의 실행을 구분하기 위해 빈 줄 출력
      }

    Prompt.close();
  }
}

한 클래스에서 버그가 나오면 모든 클래스를 수정해야 하므로 유지보수가 어렵다.

v12. 인스턴스 멤버의 필요성

인스턴스 필드(none-static field)는 new 명령을 통해 Heap 영역에 생성된다. 개별적으로 다뤄야 할 값이라면 인스턴스 필드로 선언한다.

인스턴스 필드를 다루는 메서드는 인스턴스 메서드로 선언한다. 인스턴스 메서드는 호출할 때 반드시 유효한 레퍼런스(인스턴스 주소)가 있어야 한다. 레퍼런스는 인스턴스 메서드의 내장(built-in) 로컬 변수인 this에 저장된다.

여러 개의 게시판을 다루기 위해 BoardHandler의 필드와 메서드를 인스턴스 멤버로 전환한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.eomcs.pms.handler;

import java.util.Date;
import com.eomcs.util.Prompt;

public class BoardHandler {
  static class Board {
    int no;
    String title;
    String content;
    String writer;
    Date registeredDate;
    int viewCount;
  }
  // 공통으로 사용할 값을 보관하는 변수는 스태틱 멤버(클래스 멤버)로 만든다.
  static final int LENGTH = 100;
  
  // 개별적으로 관리되어야할 변수는 인스턴스 멤버(non-static 멤버)로 만든다.
  Board[] list = new Board[LENGTH]; 
  int size = 0;
  MemberHandler memberHandler;
  
  public void add() {
    System.out.println("[게시물 등록]");
    
    Board board = new Board();
    board.no = Prompt.inputInt("번호? ");
    board.title = Prompt.inputString("제목? ");
    board.content = Prompt.inputString("내용? ");
    while (true) {
      String name = Prompt.inputString("작성자?(종료하려면 빈 문자열을 입력) ");
      if (name.length() == 0) {
        System.out.println("등록을 취소합니다.");
        return;
      }
      if (memberHandler.findByName(name) != null) {
       board.writer = name;
        break;
      } 
      System.out.println("등록된 회원이 아닙니다.");
    }
    board.registeredDate = new java.sql.Date(System.currentTimeMillis());
    
    System.out.println("게시글을 등록하였습니다.");
    board.viewCount = 0;
    list[size++] = board;
  }
  
  public void list() {
    System.out.println("[게시글 목록]");
    
    for (int i = 0; i < size; i++) {
      Board board = list[i];
      System.out.printf("%d, %s, %s, %s, %d\n",
          board.no, 
          board.title, 
          board.writer,
          board.registeredDate,
          board.viewCount);
    }
  }
}

기존의 MemberHandler와 ProjectHandler, TaskHandler도 필드와 메서드를 인스턴스 멤버로 전환한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.eomcs.pms.handler;

import java.sql.Date;
import com.eomcs.util.Prompt;

public class MemberHandler {

  // 회원 데이터
  static class Member {
    int no;
    String name;
    String email;
    String password;
    String photo;
    String tel;
    Date registeredDate;
  }
  
  static final int LENGTH = 100;
  Member[] list = new Member[LENGTH]; // list로 이름을 바꾼다.
  int size = 0;

  // 다른 패키지에서 이 메서드를 사용할 수 있도록 public 으로 사용 범위를 공개한다.
  public void add() {
    System.out.println("[회원 등록]");
    
    Member member = new Member();
    member.no = Prompt.inputInt("번호? ");
    member.name = Prompt.inputString("이름? ");
    member.email = Prompt.inputString("이메일? ");
    member.password = Prompt.inputString("암호? ");
    member.photo = Prompt.inputString("사진? ");
    member.tel = Prompt.inputString("전화? ");
    member.registeredDate = new java.sql.Date(System.currentTimeMillis());
    
    list[size++] = member;
  }
  
  public void list() {
    System.out.println("[회원 목록]");
    
    for (int i = 0; i < this.size; i++) {
      Member member = list[i];
      System.out.printf("%d, %s, %s, %s, %s\n",
          member.no, 
          member.name, 
          member.email, 
          member.tel, 
          member.registeredDate);
    }
  }
  
  public String findByName(String name) {
    for (int i = 0; i < this.size; i++) {
      if (this.list[i].name.equals(name)) {
        return name;
      } 
    }
    return null;
  }
}

이때, ProjectHandler와 MemberHandler가 사용할 의존 객체(MemberHandler)를 담을 MemberHanler 타입의 레퍼런스를 갖고 이에 집어넣을 인스턴스를 App클래스에서 직접 주입해준다.

이때, MemberHandler의 findByName() 메서드를 인스턴스 메서드로 변경하면, MemberHandler 의존객체로 사용해야 한다. 해당 클래스들이 직접 App 클래스에 있는 MemberHandler인스턴스를 참조하면 각 핸들러 클래스들과 App 클래스가 크로스 참조된다. 서로를 참조하게 되면 클래스가 계속 로드되는 상황에 빠진다. 그러나 이는 이론적인 상황이고 실제로는 컴파일러가 이러한 상황을 인지하여 클래스를 한 번만 로드한다. 따라서 오류는 나지 않지만 그래도 복잡해지니 이런 방법은 사용하지 말도록 하자..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package com.eomcs.pms.handler;

import java.sql.Date;
import com.eomcs.util.Prompt;

public class ProjectHandler {

  // 프로젝트 데이터
  static class Project {
    int no;
    String title;
    String content;
    Date startDate;
    Date endDate;
    String owner;
    String members;
  }
  
  final int LENGTH = 100;  // PLENGTH 를 LENGTH 로 변경한다.
  Project[] list = new Project[LENGTH]; // projects 를 list 로 변경한다.
  int size = 0; // psize 를 size 로 변경한다.
  MemberHandler memberHandler;
  
  //다른 패키지에서 이 메서드를 사용할 수 있도록 public 으로 사용 범위를 공개한다.
  public void add() {
    System.out.println("[프로젝트 등록]");
    
    Project project = new Project();
    project.no = Prompt.inputInt("번호? ");
    project.title = Prompt.inputString("프로젝트명? ");
    project.content = Prompt.inputString("내용? ");
    project.startDate = Prompt.inputDate("시작일? ");
    project.endDate = Prompt.inputDate("종료일? ");
    while (true) {
      String name = Prompt.inputString("만든이?(종료하려면 빈 문자열을 입력) ");
      if (name.length() == 0) {
        System.out.println("등록을 취소합니다.");
        return;
      }
      if (memberHandler.findByName(name) != null) {
        project.owner = name;
        break;
      } 
      System.out.println("등록된 회원이 아닙니다.");
    }
    
    StringBuilder names = new StringBuilder();
    while (true) {
      String name = Prompt.inputString("팀원?(종료하려면 빈 문자열을 입력) ");
      if (name.length() == 0) {
        break;
      }
      if (memberHandler.findByName(name) != null) {
        names.append(name + ",");
        project.members = names.toString();
      } else {
        System.out.println("등록된 회원이 아닙니다.");        
      }
    }

    this.list[this.size++] = project;
  }
  
  public void list() {
    System.out.println("[프로젝트 목록]");
    
    for (int i = 0; i < this.size; i++) {
      Project project = this.list[i];
      System.out.printf("%d, %s, %s, %s, %s, [%s]\n",
          project.no, 
          project.title, 
          project.startDate, 
          project.endDate, 
          project.owner,
          project.members);
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.eomcs.pms;

import com.eomcs.pms.handler.BoardHandler;
import com.eomcs.pms.handler.MemberHandler;
import com.eomcs.pms.handler.ProjectHandler;
import com.eomcs.pms.handler.TaskHandler;
import com.eomcs.util.Prompt;

// 1) `Prompt` 클래스를 별도의 패키지로 분류한다
// 2) 핸들러 클래스들을 별도의 패키지로 분류한다
public class App {

  public static void main(String[] args) {

    MemberHandler memberHandler = new MemberHandler();
    
    BoardHandler boardHandler = new BoardHandler();
    boardHandler.memberHandler = memberHandler;
    
    ProjectHandler projectHandler = new ProjectHandler();
    projectHandler.memberHandler = memberHandler;
    
    TaskHandler taskHandler = new TaskHandler();
    taskHandler.memberHandler = memberHandler;
    
    loop:
      while (true) {
        String command = Prompt.inputString("명령> ");

        switch (command) {
          case "/board/add": boardHandler.add(); break;
          case "/board/list": boardHandler.list(); break;
          case "/member/add": memberHandler.add(); break;
          case "/member/list": memberHandler.list(); break;
          case "/project/add": projectHandler.add(); break;
          case "/project/list": projectHandler.list(); break;
          case "/task/add": taskHandler.add(); break;
          case "/task/list": taskHandler.list(); break;
          case "quit":
          case "exit": System.out.println("안녕!"); break loop;
          default: System.out.println("실행할 수 없는 명령입니다.");
        }
        System.out.println(); // 이전 명령의 실행을 구분하기 위해 빈 줄 출력
      }

    Prompt.close();
  }
}

실무에서는 클래스의 인스턴스를 여러개 생성해 다룰 것을 대비하여(확장성을 고려하여) 처음부터 스태틱 멤버보다는 인스턴스 멤버로 선언한다.

v13. 생성자의 필요성

실습 목표: 생성자를 통해 의존 객체를 강제로 주입하게 만든다.

1
2
3
4
5
6
7
    ProjectHandler projectHandler = new ProjectHandler();
    // ProjectHandler의 의존객체 주입을 막는다.
    //projectHandler.memberHandler = memberHandler;
    
    TaskHandler taskHandler = new TaskHandler();
    // ProjectHandler의 의존객체 주입을 막는다.
    //taskHandler.memberHandler = memberHandler;

의존객체가 필요한 상황에서 생성자를 사용하지 않으면 (위의 코드와 같이) 의존객체 주입하는 것을 잊을 수 있다. 메인 메서드에서 호출되고 있는projectHandler.add() 메서드는 내부적으로 memberHandler.findByName() 메서드를 호출하고 있는데, 주입이 되지 않아 인스턴스의 주소 없이 호출을 하게 된다. 이때 인스턴스 주소 대신 null이 있기 때문에 NullPoint Exception Error가 발생하게 된다. 이 에러는 런타임 에러로, 컴파일 단계에서는 필요한 의존객체를 주입하지 않았다는 것을 알 수 없기 때문에, 주입을 강제할 방법이 필요하다.

1
2
3
4
MemberHandler memberHandler = new MemberHandler();
// 다음과 같이 기본 생성자만 있는 경우는,
// 해당 인스턴스를 생성하고 초기화시킬 때
// 외부에서 값을 받을 필요가 없다는 의미이다.

따라서 생성자를 통해서 의존 객체 주입 없이는 인스턴스를 생성하지 못하게 해야 한다. 파라미터로 MemberHandler의 객체를 받는 생성자를 지정하여 강제로 의존객체를 주입할 수 있게 있도록 한다.

ProjectHandler.class

1
2
3
public ProjectHandler(MemberHandler mamberHandler) {
	this.memberHandler = memberHandler;
}

App.class => main()

1
2
3
4
5
6
MemberHandler memberHandler = new MemberHandler();

ProjectHandler projectHandler = new ProjectHandler(memberHandler);
// ProjectHandler 를 생성할 때 필요로 하는 의존 객체를 전달한다.
// => 이렇게 생성자를 명확하게 지정하면 
// 객체를 생성하는 개발자에게 의존 객체 주입을 강제하는 효과가 있다.

v14. UI처리하는 코드와 데이터 처리하는 코드 분리

객체지향 프로그래밍을 할 때 Low Coupling과 High Cohesion을 명심해야 한다.

Low Coupling(관계도 낮추기)

한 클래스가 많은 클래스에 의존하는 구조로 작성하면 의존 클래스가 변경될 때마다 영향을 받기 때문에 유지보수에 좋지 않다. 그래서 가능한 의존하는 클래스의 접점을 줄이는 구조로 만드는 것이 좋다.

(관계도 낮추기 => 의존 클래스의 변경에 둔감 => 코드 변경이 줄어듦)

High Cohesion(응집력 강화)

한 클래스가 너무 다양한 역할을 수행하면 클래스 코드가 커지고 변경 사항이 잦아지기 때문에 유지보수에 좋지 않다. 그래서 가능한 한 클래스가 한 개의 역할만 수행하게 만드는 것이 유지보수에 좋다. 역할을 작게 쪼개게 되면 해당 클래스를 다른 프로젝트에서 재사용하기가 쉽다.

(응집력 강화 => 클래스를 잘게 쪼갬 => 교체가 용이하고 재사용성이 높아짐)

실습 내용

1단계 : BoardHandler에서 데이터 처리 코드를 분리한다. BoardHandler에서 데이터 처리 코드를 분리하여 ‘BoardList’ 클래스로 정의한다. BoardList의 기본 생성자와 배열의 초기 크기를 설정하는 생성자를 정의한다. 그리고 Board객체를 등록하는 add()와 데이터 목록을 리턴하는 toArray() 메서드를 정의한다. BoardHandler은 BoardList를 사용하여 입출력을 처리한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.eomcs.pms.handler;

import java.sql.Date;

public class BoardList {
  static class Board {
    int no;
    String title;
    String content;
    String writer;
    Date registeredDate;
    int viewCount;
  }
  
  static final int DEFAULT_SIZE = 100;
  Board[] list = new Board[DEFAULT_SIZE]; // list로 이름을 바꾼다.
  int size = 0;
  
  public BoardList() {
    this(DEFAULT_SIZE);
  }
  
  public BoardList(int size) {
    if (size < DEFAULT_SIZE) {
      this.list = new Board[DEFAULT_SIZE];
    } else {
      this.list = new Board[size];
    }
  }
  
  public void add(Board board) {
    this.list[size++] = board;
  }
  
  public Board[] toArray() {
    Board[] arr = new Board[size];
    for (int i = 0; i < this.size; i++) {
      arr[i] = list[i];
    }
    return arr;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.eomcs.pms.handler;

import com.eomcs.pms.handler.BoardList.Board;
import com.eomcs.util.Prompt;

public class BoardHandler {
  
  BoardList boardList = new BoardList();
  MemberHandler memberHandler;
  
  public BoardHandler(MemberHandler memberHandler) {
    this.memberHandler = memberHandler;
  }
  
  public void add() {
    System.out.println("[게시물 등록]");
    
    Board board = new Board();
    board.no = Prompt.inputInt("번호? ");
    board.title = Prompt.inputString("제목? ");
    board.content = Prompt.inputString("내용? ");
    while (true) {
      String name = Prompt.inputString("작성자?(취소: 빈 문자열) ");
      
      if (name.length() == 0) {
        System.out.println("프로젝트 등록을 취소합니다.");
        return;
      } else if (memberHandler.findByName(name) != null) {
        board.writer = name;
        break;
      }
      
      System.out.println("등록된 회원이 아닙니다.");
    }
    board.registeredDate = new java.sql.Date(System.currentTimeMillis());
    
    boardList.add(board);
  }
  
  public void list() {
    System.out.println("[게시물 목록]");
    Board[] boards = boardList.toArray();
    for (Board board : boards) {
      System.out.printf("%d, %s, %s, %s, %s\n",
          board.no, 
          board.title, 
          board.writer,  
          board.registeredDate,
          board.viewCount);
    }
  }
}

2단계 : Board 클래스를 패키지 멤버 클래스로 전환한다. BoardHandler와 BoardList가 둘 다 Board 클래스를 사용하므로 중첩 클래스보다 패키지 멤버 클래스로 정의하면 관리하기 쉽기 때문이다. com.eomcs.pms.domain 패키지를 새로 생성하여 넣어준다. Member, Board 처럼 데이터 타입 역할을 하는 클래스를 도메인 클래스라 부른다. 패키지 멤버 클래스는 static이 될 수 없으므로 static 을 떼고 다른 패키지에 있는 클래스가 사용해야하기 때문에 public을 붙인다.

1
2
3
4
5
6
7
8
9
10
11
12
package com.eomcs.pms.domain;

import java.sql.Date;

public class Board {
  public int no;
  public String title;
  public String content;
  public String writer;
  public Date registeredDate;
  public int viewCount;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.eomcs.pms.handler;

import com.eomcs.pms.domain.Board;

public class BoardList {
  
  static final int DEFAULT_SIZE = 100;
  Board[] list = new Board[DEFAULT_SIZE]; // list로 이름을 바꾼다.
  int size = 0;
  
  public BoardList() {
    this(DEFAULT_SIZE);
  }
  
  public BoardList(int size) {
    if (size < DEFAULT_SIZE) {
      this.list = new Board[DEFAULT_SIZE];
    } else {
      this.list = new Board[size];
    }
  }
  
  public void add(Board board) {
    this.list[size++] = board;
  }
  
  public Board[] toArray() {
    Board[] arr = new Board[size];
    for (int i = 0; i < this.size; i++) {
      arr[i] = list[i];
    }
    return arr;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.eomcs.pms.handler;

import com.eomcs.pms.domain.Board;
import com.eomcs.util.Prompt;

public class BoardHandler {
  
  BoardList boardList = new BoardList();
  MemberHandler memberHandler;
  
  public BoardHandler(MemberHandler memberHandler) {
    this.memberHandler = memberHandler;
  }
  
  public void add() {
    System.out.println("[게시물 등록]");
    
    Board board = new Board();
    board.no = Prompt.inputInt("번호? ");
    board.title = Prompt.inputString("제목? ");
    board.content = Prompt.inputString("내용? ");
    while (true) {
      String name = Prompt.inputString("작성자?(취소: 빈 문자열) ");
      
      if (name.length() == 0) {
        System.out.println("프로젝트 등록을 취소합니다.");
        return;
      } else if (memberHandler.findByName(name) != null) {
        board.writer = name;
        break;
      }
      
      System.out.println("등록된 회원이 아닙니다.");
    }
    board.registeredDate = new java.sql.Date(System.currentTimeMillis());
    
    boardList.add(board);
  }
  
  public void list() {
    System.out.println("[게시물 목록]");
    Board[] boards = boardList.toArray();
    for (Board board : boards) {
      System.out.printf("%d, %s, %s, %s, %s\n",
          board.no, 
          board.title, 
          board.writer,  
          board.registeredDate,
          board.viewCount);
    }
  }
}

3단계 : 같은 방식으로 다른 핸들러 클래스를 UI 처리와 데이터 처리 클래스로 분리한다.

  • 핸드폰은 뭐가 잘못되거나 추가하려면 메인보드 전체를 갈아야 하지만, 자동차에서 문제가 생기거나 추가하려고 하면 부품을 교체하거나 추가하면 된다. 마찬가지로 한 사람이 하나의 일을 하게 하면 그 사람이 다른 사람에 의해 쉽게 교체될 수 있다. (분업화) 코드를 경영하는 경영자 입장으로 생각하자.
  • XxxHandler 클래스는 사용자와 소통하는 역할을 수행할 뿐만 아니라 데이터를 관리하는 역할도 수행한다. 이 것을 사용자의 소통을 담당하는 UI 역할 클래스와 데이터 처리를 담당하는 DAO(Data Access Object) 역할 클래스로 분리하였다.
  • 이를 통해 추후 데이터 처리 부분을 다른 클래스로 교체하기 쉬워진다. ex) 지금은 데이터를 배열에 보관하고 있지만, 나중에는 파일이나 DBMS에 보관하는 클래스로 교체하기가 쉬워진다.
  • 또한 지금은 CLI(Command Line Interface) 방식으로 UI를 처리하고 있지만, 나중에는 웹으로 처리하는 클래스로 교체하기가 쉬워진다.

  • 여러 클래스에서 공유하는 클래스는 중첩 클래스로 정의하기 보다는 패키지 멤버 클래스로 정의하면 관리하기가 더 쉽다.
  • Board나 Member처럼 데이터 타입 역할을 하는 클래스를 도메인(domain) 클래스라 부른다.

  • Board핸들러에서만 사용할 클래스는 Board핸들러 클래스 안에 만들자. 중첩 클래스가 디폴트이다. 그러다가 다른 클래스가 사용해서 불편하다면 그때서야 분리해라.
This post is licensed under CC BY 4.0 by the author.

학원 #27일차: 자료구조(큐, 스텍, 반복자, HashSet, HashMap, Hashtable), 클래스 의존관계

[JS] 생활코딩 #18: arguments

Loading comments from Disqus ...