본문 바로가기
☁︎KOSTA/☂︎KOSTA-JAVA

[KOSTA] Spring 기반 Cloud 서비스 구현 개발자 양성 (Day 16) - mini project : schoolproject-IO

by 하_센세 2022. 8. 22.

2022.08.22 [MON]

- Day 16- 

 

수업 주요 목차

  • IO
  • mini project : schoolproject-IO

🤖Review

 

Error : 구조개선, 환경 개선이 필요한 심각한 문제

Exception : 프로그램적으로 제어가 가능한  문제 (메세지 발생 JVM 즉시 종료) -> 예외 처리(Exception Handling)

 

예외 처리(Exception Handling) -> 대처방안 & 프로그램 정상 실행이 목적

 

try : 예외발생 예상영역 지정

catch : 예외 발생시 대처방안/대처흐름을 실행시켜 예외를 처리하는 영역

finally : 예외 발생여부, 처리여부와 상관없이 무조건 실행

throws : 예외를 호출한 측으로 전파(던지는 것)

throw : 필요시 예외를 의도적으로 발생시키는 것 (checked, unchecked 상관없음)

 

Checked : runtime 계열을 제외한 모든 exception (compile시 예외 체크 가능)

UnChecked : runtime 계열의 exception (throws 명시할 필요 없이 자동적으로 전파됨)

 

Polymorphism(다형성) : 하나의 메세지로 다양한 객체 참조할 수 있는 성질

Inheritance(상속) : 단일계층형성으로 다형성 환경을 지원한다. 부모의 멤버를 자식에게 물려준다.

Encapsulation(캡슐화) : 구현부, 소통부를 나누어 개발 / 소통부 공개 구현부 은닉 / 높은 응집도와 낮은 결합도의 고급 프로그램 개발/구현 가능하다.

Coupling(결합도) : 모듈간 상호 의존도

Cohesion(응집도) : 모듈 내 기능 집중도

 

 

Interface: 다양한 계층구조

abstract: 단일 계층구조 / 멤버 물려줌

 

공통점:

1) 직접 객체화될 수 없다.(단, 자식으로 부터 객체화 가능)

2) 부모 || 상위 타입으로 구조 계층 형성하여 다형성을 지원한다.

3) 자식에게 구현을 강제할 수 있다.

 

 

java memory

heap : 객체의 정보 저장(i.v)

stack : 로컬변수 저장 (l.v)

meta-space : 클래스 static

 

Overloading : 하나의 메소드, 다양한 매개변수 why? 클라이언트 편의성 

Overriding : 부모의 method 상속받아 자신에 맞게 재정의

 

super - 부모를 가리킬 때

this - 나(자식)을 가리킬 때

 

Set : 중복 인정 안하는 데이터 관리 

List: index로 데이터 관리

 

refactoring : 입출력 변화 없이 내부 구조를 바꾸는 것 ; 가독성을 높이기 위함

분석설계시 사용하는 기초 언어 : UML  

 



** 15day **

 

if기반 ConsoleIO2를 switch구문으로 변경해보는 예제 제어문에서 label을 사용해본다.

Label : 반복문을 탈출 할 때 사용

label 을 지정하여 while문을 벗어나고 싶을 때 break label명을 써주면 된다.(label명은 자유롭게 지정)

package step1;

import java.util.Scanner;

public class TestConsoleIO3 {
	Scanner scanner = new Scanner(System.in);
	public void showMenu() {
		exit: 
		while (true) {
			System.out.println("***주종을 선택하세요 1.맥주 2.소주 3.막걸리 4.종료***");
			String info = scanner.nextLine();
			switch (info) {
			case "1":
				System.out.println("맥주 선택 완료");
				break;
			case "2":
				System.out.println("소주");
				break;
			case "3":
				System.out.println("막걸리");
				break;
			case "4": //label을 이용한다.
				System.out.println("주문종료");
				break exit; // 지정한 레이블이 명시된 제어문을 벗어난다.
				//scanner.close(); -> 여기에 넣었더니 에러뜸
			default:
				System.out.println("입력값 오류");
			}
			//scanner.close(); -> 여기에 이걸 넣었더니 반복이 안되었었음
		}
		scanner.close(); 
	}

	public static void main(String[] args) {
		new TestConsoleIO3().showMenu();
	}
}

 

scanner.close() 위치 때문에 에러가 자주 났다. 위의 경우 메소드 밖에서 종료시켜줘야 함(계속 반복되어야 하는 곳에서 닫을 수 없고 선언 된 곳에서 끝내야 함)

 

근데 exit을 통해서 반복이 끝나고 종료가 되었는데 굳이 scanner까지 닫아줘야 하는 이유는 뭘까? 인터넷에 검색해보니 사용하지 않는 입출력 stream이 열리지 않도록 하기 위함이라고 하는데 저 예제에서 종료를 시켜 더 이상 입력이 불가능하게 되었는데도 굳이 닫아줘야하는 건 그냥...그냥 하는 건가...ㅋ.. 의례적인 그런..? stream 따로 한번 봐야겠다.

 

 


 

🔎 Eclipse 실습 내용

 

 

만들어뒀던 UML에 ConsoleUI 클래스를 따로 만들어서 어떻게 구현할지 다 같이 만들어봤다. 우선 매개변수로 scanner와  schoolservice 객체 생성해주고 method는 4가지로 나누었다. execute는 약간 메뉴같은 느낌이고 선택에 따라 SchoolService에 있는 method를 사용할 수 있도록 만들어 준다. 그 밑에 3가지는 메뉴의 구성요소(?) 

 

 

Console class

package step2;

import java.util.Scanner;

import model.exception.DuplicateTelException;
import model.exception.MemberNotFoundException;
import model.service.SchoolService;
import model.vo.Employee;
import model.vo.Member;
import model.vo.Student;
import model.vo.Teacher;

public class ConsoleUI {
	private SchoolService ss = new SchoolService();
	private Scanner scanner = new Scanner(System.in);

 

execute method

public void execute() {
	System.out.println("*******학사관리프로그램을 시작합니다******");
	exit: while (true) {
		System.out.println("1. 추가 2. 삭제 3. 검색 4. 전체회원보기 5.종료");
		String info = scanner.nextLine();
		switch (info) {
		case "1":
			addView();
			break;
		case "2":
			deleteView();
			break;
		case "3":
			findView();
			break;
		case "4":
			ss.printAll();
			break;
		case "5":
			System.out.println("******학사관리프로그램을 종료합니다******");
			break exit;
		default:
			System.out.println("잘못된 입력값입니다.");
			break;
		}
	}
	scanner.close();
}
  1. 실행하자마자 "*******학사관리프로그램을 시작합니다******"메세지가 뜨고 메뉴 선택지가 "1. 추가 2. 삭제 3. 검색 4. 전체회원보기 5.종료" 이렇게 주어진다.
  2. 사용자가 입력하면 각각 그에 맞는 method가 실행될 수 있도록 만든다.
  3. 입력은 String으로 설정한 다음 "1~4"까지 각각 method를 실행할 수 있도록 써준다.
  4. "5"는 종료이기 때문에 반복문을 빠져나가도록 해야하는데 label을 이용하여 빠져나갈 수 있도록 한다.
  5. scanner는 프로그램이 종료하면서 입/출력할 수 없게 닫아줘야 하는데 scanner가 선언된 부분에서 닫아줘야 한다.

 

deleteView method

public void deleteView() {
	while (true) {
		System.out.println("삭제할 구성원의 전화번호를 입력하세요.");
		String tel = scanner.nextLine();
		try {
			ss.deleteMemberByTel(tel);
			System.out.println(tel + "에 해당하는 구성원을 삭제했습니다.");
		} catch (MemberNotFoundException mnfe) {
			System.out.println(mnfe.getMessage());
		}
		break;
	}
}
  1.  사용자가 2번 삭제를 입력창을 통해 선택하면 "삭제할 구성원의 전화번호를 입력하세요" 메세지가 가장 먼저 뜨도록 한다.
  2.  try, catch로 SchoolService에 있는 deleteMemberByTel method를 사용해서 삭제하고 만약 일치하는 정보가 없다면 catch 블럭에서 메세지를 호출한 측으로 전달

🤮실수🤮

while로 묶어놨었는데 그럴 필요가 없었음(삭제 메소드 안에 또 선택지가 있거나 메뉴가 있는게 아니니까!)

 

 

findView method

public void findView() {
		System.out.println("조회할 구성원의 전화번호를 입력하세요.");
		String tel = scanner.nextLine();
		try {
			ss.findMemberByTel(tel);
			System.out.println(tel + " 조회결과: " + ss.findMemberByTel(tel));
		} catch (MemberNotFoundException mnfe) {
			System.out.println(mnfe.getMessage());
	}
}
  1. 사용자가 3번 검색을 입력창을 통해 선택하면 "조회할 구성원의 전화번호를 입력하세요" 메세지가 가장 먼저 뜨도록 한다.
  2. 마찬가지로 try, catch 사용해서 SchoolService에 있는 findMemberByTel method를 사용해 결과를 출력해주도록 한다.
public void findView() {
		System.out.println("조회할 구성원의 전화번호를 입력하세요.");
		String tel = scanner.nextLine();
		try {
			Member member=ss.findMemberByTel(tel);
			System.out.println(tel + " 조회결과: " + member);
		} catch (MemberNotFoundException mnfe) {
			System.out.println(mnfe.getMessage());
	}
}

이렇게 member 변수 안에 참조시켜서 해도 됨!

 

자, 이제 대망의

addView method

public void addView() {
	String tel, name, adress, id, sub, department, type = null;
	while(true) {
		System.out.println("입력할 구성원 종류를 선택하세요 1.학생 2.선생님 3.직원");
		type=scanner.nextLine();
		if(type.equals("1")||type.equals("2")||type.equals("3")) {
			break;
		}else {
			System.out.println("1.학생 2.선생님 3.직원 중 하나를 선택하세요");
		}
	}
		while (true) {
			System.out.println("1. 전화번호를 입력하세요");
			tel = scanner.nextLine();
			if (ss.findIndexByTel(tel) != -1)
				System.out.println("중복임");
			else
				break;
		}
		System.out.println("2. 이름를 입력하세요");
		name = scanner.nextLine();
		System.out.println("3. 주소를 입력하세요");
		adress = scanner.nextLine();
		Member member = null;
		switch (type) {
		case "1":
			System.out.println("4. 학번을 입력하세요");
			id = scanner.nextLine();
			member = new Student(tel, name, adress, id);
			break;
		case "2":
			System.out.println("4. 과목을 입력하세요");
			sub = scanner.nextLine();
			member = new Teacher(tel, name, adress, sub);
			break;
		case "3":
			System.out.println("4. 부서를 입력하세요");
			department = scanner.nextLine();
			member = new Employee(tel, name, adress, department);
			break;
			}
		try {
			ss.addMember(member);
			System.out.println("리스트에 추가: " + member.toString());
		} catch (DuplicateTelException e) {
			System.out.println(e.getMessage());
	} 
}
  1. add의 경우 이 안에서 3가지의 경우의 수(학생, 교사, 직원)가 생기기 때문에 while문으로 반복해서 돌려주고 "1", "2", "3" 이 선택되면 그만 반복되게, 그 외 다른 입력을 하게 되면 선택을 유도하는 메세지가 나오도록 한다.
  2. 전화번호 입력+중복확인은 3가지 경우의 수라도 모두 공통적으로 행해지는 과정이기 때문에 따로 빼서 중복이 아닐 때까지 반복해준다.
    1. SchoolService에 만들어뒀던 findIndexByTel을 이용한다.
    2. 중복 여부를 비교한 뒤 만약 있으면 메세지를, 없으면 반복을 중단한다.
  3. 전화번호로 중복 체크를 한 뒤 이름, 주소, 입력하는 것은 공통적이기 때문에 작성해주고 멤버객체를 생성한 뒤 null로 초기화해준다.
  4. case " 1"은 학생 저장용으로 학번을 마저 입력한다. ("2"는 교사/과목, "3"은 직원/부서)
  5. 모여진 데이터를 리스트에 추가하려고 할 때 중복을 다시 한 번 체크하고(사실상 불필요) 만약 예외가 있으면 catch에서 메세지를 전달하도록 해준다.

 

 

//오늘의 뿌듯한 점

멤버 리스트에 추가하고 확인 메세지 뜰 때 정보들 하나하나 써주는 걸로 맨 처음에 작성했다가 조금 생각해보니 이미 toString오버라이드 한게 있어서 그거 써먹어보려고 좀 끙끙댔더니 성공 멤버따로 생성자 생성해서 참조해주고 member.toString했더니 성공했다ㅏㅏㅏㅏ

 

// 오늘의 단축키

X

 

//오늘의 질문 

X

 

//오늘의 숙제

복습+코드 한번 쳐보기