일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Navigation
- Project Bee
- 노마드코더
- react
- 오블완
- FlatList
- 경우의 수
- 비트마스킹
- BFS
- 이영직
- 해외 대외활동
- React Natvive
- service 테스트
- 폴더구조
- bfs dfs
- 티스토리챌린지
- web view
- ReactNative
- React Native
- 휴대폰 기기
- 버튼 활성화
- multipart upload
- 자료구조
- 구현
- 원복
- 백준 1992
- springboot
- 완전탐색
- 상속 관계 매핑
- 창의충전소
- Today
- Total
유미의 기록들
[팀 과제 - Java] 캠프 관리 프로그램 본문
📌 요구사항
📄 기능 명세서
- 수강생 관리
1) 수강생 정보 등록 (고유번호, 이름, 과목 목록)
2) 수강생 목록 조회 (고유번호, 이름)
*수강생의 고유번호는 중복 될 수 없다
- 점수 관리
1) 수강생 과목별 시험 회차 및 점수 등록
2) 수강생 과목별 회차 점수 수정
3) 수강생 특정 과목 회차별 등급 조회
*과목의 회차 점수가 중복되어 등록될 수 없다
*회차범위는 1~10 / 점수범위는 0~100
과목에서 필수과목과 선택과목으로 이루어진다
점수에 따라 등급이 매겨진다
👤 역할 분담
A - 수강생 정보 등록 (고유번호, 이름, 과목 목록)
B - 수강생 목록 조회 (고유번호, 이름)
C - 수강생 과목별 시험 회차 및 점수 등록
D - 수강생 과목별 회차 점수 수정
E - 수강생 특정 과목 회차별 등급 조회 ✅
총 5명이기 때문에 이렇게 각 기능 별로 분담했다. 서로 다른 기능을 맡으면서 코드가 겹치지 않아 충돌 발생 가능성을 줄이고, 각 기능을 병렬도 개발하면서 전체 프로젝트의 기간이 단축될 것이라 예상했다. 또한 기능별로 모듈화된 코드 구조를 유지하거나 특정 기능에 문제가 생긴 경우, 해당 기능만 수정할 수 있어 유지보수 측면에도 훨씬 생산적일 것이라고 판단했다.
처음에는 전체 시스템의 설계없이 각 팀원이 맡은 기능에 대한 개발을 시작했는데 그러다 보니 많은 문제점이 발생했다
1. 클래스와 객체 간의 관계가 명확하지 않아서 개발하는데 시간이 오래걸림
2. 팀원 간의 코드 작성 스타일과 방식이 달라서 충돌 방생
3. 동일한 기능을 여러군데 중복 구현되어 가독성이 안좋아짐
특히 내가 조회부분을 맡았는데, 등록부분이 기능이 완료가 안되면 코드를 구현할 수 없는 상황이 발생했다 따라서 개발을 시작하기 전에 클래스 다이어그램을 포함한 설계과정이 매우 중요하다는 것을 깨달았다
⚙️ 클래스 다이어그램 설계
클래스 다이어그램
클래스 내부 구성요소 및 클래스 간의 관계를 도식화하여 시스템의 특정 모듈이나 전체를 구조화하는 UML 구조 다이어그램
클래스 다이어그램의 요소
Class
보통 3개의 구획으로 나누어 클래스의 이름, 속성, 기능을 표기함
접근 제어자를 사용해 나타낸다
+ : public 어떤 클래스에도 접근 가능
- : private 클래스에 생성된 객체들만 접근 가능
# : protected 동일 패키지에 있거나 상속 관계에 있는 하위 클래스 객체들만 접근 가능
~ : package 동일 패키지에 있는 클래스의 객체들만 접근 가능
Stereo Type (스테레오 타입)
인터페이스나 추상클래스와 같은 요소를 표기하기 위해 <<>> (길러멧) 사이에 적는다. 스테레오 타입으로 많이 사용되는 것은 <<interface>>, <<abstract>>, <<enumeration>>, <<utility>> 등이 있다
관계
클래스간의 의존 관계를 한눈에 쉽게 파악하기 위해 가장 중요한 것이 클래스간의 관계를 표기하는 것이다
위 그림은 많이 사용되는 클래스 간의 관계들의 종류와 표기법을 나타낸 것이다
Generalization
부모 클래스와 자식 클래스 간의 상속 관계를 나타낸다 - Java에서는 extends 키워드 사용
Realization
인터페이스를 상속하여 spec만 있는 메서드를 오버라이딩하여 실제 기능을 실현화 할 때 사용한다 - Java에서는 implements 키워드 사용
Dependency
일반적으로 제일 많이 사용되는 관계로, 어떤 클래스가 다른 클래스를 참조하는 것
참조의 형태는 메서드 내에서 대상 클래스의 객체 생성, 객체 사용, 메서드 호출, 객체 리턴, 매개변수로 해당 객체를 받는 것등을 말한다
Association
다른 객체의 참조를 가지고 있을 때 이러한 연관 관계를 나타낸다. 두 가지 형태로 나타낸다
1) Association : User가 Address를 참조할 수도, Address가 User를 참조할 수도, 또는 둘 다일 수도 있는 것
2) Directed Association : User가 Address를 참조하는 것
Association는 변수로 다른 클래스와 연관이 있을 때
Dependency는 메소드의 파라미터나 반환에 사용되는 클래스 관계를 나타낼 때
Aggregation
Composition과 함께 Association 관계를 조금 더 특수하게 나타낸 것. 집합이라는 의미를 가지고 있다
Composition
Aggregation보다 더 강한 집합 관계를 의미함
과제에서 구현한 코드를 바탕으로 클래스 다이어그램을 그려보았다
📝 개발 과정
내가 맡은 기능은 수강생 특정 과목 회차별 등급 조회 부분이다
구상한 전체 프로세스는 다음과 같다
1) 관리할 수강생 고유번호 입력 받기
*예외) 해당 수강생이 없음
2) 관리할 수강생의 과목 리스트(과목아이디, 과목 이름) 보여주기
3) 관리할 수강생이 조회를 원하는 과목 아이디 입력 받기
*예외) 해당 과목이 없음
4) 과목별로 시험회차와 등급 조회하기
*예외) 해당 시험회차와 등급 없음
⚠️ 문제 해결 과정
1번 2번의 예외처리는 다른 팀원이 만들어 놓은 메소드를 재사용하여 해결했다. 4번을 수행할 때, 과목별로 시험회차와 등급이 없으면 프로그램이 종료되었다
getGrades(studentId,subjectName).forEach((round,grade)->{
System.out.println(round+"회차| "+grade);
});
//회차별 등급 반환
private static Map<Integer,String> getGrades(String studentId, String subjectName){
for(Score score:scoreStore){
if(score.getStudentId().equals(studentId)&&score.getSubjectId().equals(getSubjectId(subjectName))){
return score.getGrades();
}
}
return null;
}
다음과 같이 Object.requireNonNull로 바꾸라는 경고 표시가 나왔다
requireNonNull
Object 클래스에서 제공하는 Null 체크를 위한 메소드이다. 파라미터로 입력된 값이 (즉, 여기서는 해당 시험회차와 등급 Map) null이라면 NPE(NullPointException)이 발생하고, 아니라면 입력값을 그대로 반환하는 메소드이다
첫번째 메소드는 파라미터가 null이면 메시지가 비어있는 NPE 예외를 던진다
두번째 메소드는 두번째 파라미터로 전달한 문자열을 메시지로 NPE 예외를 던진다
세번째 메소드는 두번째 파라미터로 전달한 Supplier를 구현한 익명 함수의 반환값을 NPE예외로 던진다
try{
Objects.requireNonNull(getGrades(studentId, subjectName),"등록된 회차 별 등급이 없습니다").forEach((round, grade)->{
System.out.println(round+"회차| "+grade);
});
}catch (NullPointerException e){
System.out.println(e.getMessage());
return;
}
이런 상황에서는 충분히 If문으로도 구현가능하다
Map<Integer, String> grades = getGrades(studentId, subjectName);
if (grades != null) {
grades.forEach((round, grade) -> {
System.out.println(round + "회차| " + grade);
});
} else {
System.out.println("등록된 회차 별 등급이 없습니다");
return;
}
Git 충돌
수강생 점수를 등록할 때 수강생이 선택하지 않은 과목도 점수 등록이 되는 문제가 있어서 수정을 요청하였고, CampManagementApplication.java 코드를 2명이서 수정하다보니 pull 했을 때 충돌이 발생하였다
Comfilct는 동일한 파일에 상반된 내용이 있다는 뜻이다. 로컬 저장소와 변경 대상과 remote의 변경 대상이 같을 때 Git은 두 변경 내용 중 어떤 것을 적용할 것인지 판단할 수 없기 때문에 개발자가 수동으로 수정해야 한다
<<<<<<< HEAD
Hello
=======
Hello!
>>>>>>> aab6d380aaf237a7c0aae28e00ea4607c8a7eec9
'====' 쪽 위부분이 로컬 저장소, 아래부분이 remote의 변경 내용이다
둘 중에 어떤 변경을 적용할 지 수정한 후 커밋을 수행하면 해결된다
해결완료!
'대외활동 기록 > 내일배움캠프' 카테고리의 다른 글
[개인 과제 -Spring숙련] JPA를 활용한 일정관리 앱 서버 설계 (Level 1) (0) | 2024.08.22 |
---|---|
[개인 과제 - Spring입문] 일정 관리 앱 서버 (0) | 2024.08.16 |
[개인 과제 - Java] 계산기 프로그램 (Level 3) (0) | 2024.08.02 |
[개인 과제 -Java] 계산기 프로그램 (Level 2) (0) | 2024.08.01 |
[개인 과제 -Java] 계산기 프로그램 (Level 1) (0) | 2024.07.31 |