Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7836559
refactor(domain): step1 피드백 적용
Highjune May 28, 2023
49789fb
refactor(domain): setter삭제, Answers에 delete()추가
Highjune May 28, 2023
b4b0382
refactor(domain): DeleteHistory에서 정적 팩토리 메서드에서 파라미터 도메인으로 변경"
Highjune May 28, 2023
3d688c5
docs(README.md): 기능요구사항 작성
Highjune May 28, 2023
b39de98
test(domain): SessionTimeLineTest 테스트 선작성
Highjune May 28, 2023
9c735e6
feat(domain): SessionTimeLine 객체 구현
Highjune May 28, 2023
3d8a518
refactor(domain): SessionTimeLine 날짜 로직 체크 수정
Highjune May 28, 2023
45b2955
feat(domain): SessionStatus Enum 객체 구현
Highjune May 28, 2023
2e32239
feat(domain): SessionType enum 객체 구현
Highjune May 28, 2023
4e64f85
feat(domain): SessionInfo 객체 구현
Highjune May 28, 2023
08ac6b9
feat(domain): Session 객체 구현
Highjune May 28, 2023
b516e7b
feat(domain): Student 객체 구현 추가
Highjune May 28, 2023
6a684ea
test(domain): StudentTest 에서 등록시 1 증가하는 테스트 먼저 생성
Highjune May 28, 2023
38cb914
feat(domain): Student 를 Session에 등록
Highjune May 28, 2023
944cd30
feat(domain): 수강신청시 인원 수 체크 로직
Highjune May 28, 2023
25c83d2
test(domain): 수강신청시 최대 수강인원 이하면 예외 던지지 않는다
Highjune May 28, 2023
2f7a502
test(domain): StudentTest 강의 상태에 따른 테스트 추가
Highjune May 28, 2023
0312ae0
feat(domain): StudentRepository 추가
Highjune May 28, 2023
9787ed5
test(domain): 기수에 따른 강의 조회 테스트 & 프로덕션 코드 추가
Highjune May 28, 2023
6f18763
test(domain): CourseTest 존재하는 강의 조회 테스트 추가
Highjune May 28, 2023
456423e
feat(domain): Course, CourseTest에서 유효하지 않는 기수 조회시 예외를 던진다
Highjune May 28, 2023
65577c0
feat(domain): Course, CourseTest에서 유효성 추가
Highjune May 28, 2023
cefcc3e
feat(domain): SessionRepository 추가
Highjune May 28, 2023
8058c79
docs(README.md): Course 체크리스트 업데이트
Highjune May 28, 2023
aee8314
feat(domain): Session에 등록하는 메서드명 변경
Highjune May 31, 2023
39ad05a
feat(SessionEnrollment): 강의등록 객체 추가, 테스트 추가
Highjune May 31, 2023
33d7889
feat(domain): SessionEnrollment 에 유효성 체크 추가
Highjune Jun 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,43 @@
- [x] question를 add 하면 question에 대한 DeleteHistory 를 만들어 리스트에 추가한다.
- [x] answer을 add 하면 question에 대한 DeleteHistory를 만들어 리스트에 추가한다.


## 수강신청 2단계(도메인 설계) 기능 목록
### Student(학생)
- [x] 학생은 수강신청을 할 수 있다.
- [x] 수강 신청시 강의(Session)의 현재 수강 인원이 1 증가된다.
- [x] 수강신청시 최대 인원을 넘게 되면 예외를 던진다.
- [x] 수강 신청은 강의(Session) 의 상태가 `모집중` 일 때만 가능하다.
- [x] `모집중`이 아닐 경우 예외를 던진다.

### Course(과정)
- [x] 강의를 과정에 추가하고, 기수에 따라 강의를 조회할 수 있다.
- [x] 기수가 유효하지 않다면 (음수 or 초과 기수 조회) 예외를 던진다.

### Session(강의)
- [x] 시작일과 종료일을 가진다.
- [x] 강의 커버 이미지 정보를 가진다.
- type(타입)
- [x] 무료, 유료 강의 2가지 값을 가진다(enum)
- status(상태)
- [x] 준비중, 모집중, 종료 3가지를 가진다(enum)

### SessionEnrollment(등록)
- [x] 이미 등록을 한 학생은 예외를 던진다.
- [x] 수용인원이 꽉 찬 강의에 등록시도를 할 경에 예외를 던진다.
- [x] 수강신청시 최대 수강인원을 넘지 않을 경우 예외를 던지지 않는다.
- [x] 학생은 수강신청시 강의의 현재 수강인원이 1이 증가한다.
- 강의 상태에 따라 등록상태가 다르다.
- [x] 강의 상태(SessionStatus) '모집중'일 경우에 수강신청이 가능하다(예외를 던지지 않는다)
- [x] 강의 상태(SessionStatus) '준비중'일 경우에 수깅신청시 예외를 던진다.
- [x] 강의 상태(SessionStatus) '종료'일 경우에 수깅신청시 예외를 던진다.


### 수강 신청 기능 요구사항
- 과정(Course)은 기수 단위로 여러 개의 강의(Session)를 가질 수 있다.
- 강의는 시작일과 종료일을 가진다.
- 강의는 강의 커버 이미지 정보를 가진다.
- 강의는 무료 강의와 유료 강의로 나뉜다.
- 강의 상태는 준비중, 모집중, 종료 3가지 상태를 가진다.
- 강의 수강신청은 강의 상태가 모집중일 때만 가능하다.
- 강의는 강의 최대 수강 인원을 초과할 수 없다.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo list 작성 👍

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package nextstep.courses.domain;

public class AlreadyEnrollmentException extends RuntimeException{

public AlreadyEnrollmentException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package nextstep.courses.domain;

public class CannotEnrollException extends RuntimeException{

public CannotEnrollException(String message) {
super(message);
}
}
31 changes: 31 additions & 0 deletions src/main/java/nextstep/courses/domain/Course.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package nextstep.courses.domain;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

public class Course {
private Long id;
Expand All @@ -9,6 +11,8 @@ public class Course {

private Long creatorId;

private final List<Session> sessions = new ArrayList<>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


private LocalDateTime createdAt;

private LocalDateTime updatedAt;
Expand Down Expand Up @@ -40,12 +44,39 @@ public LocalDateTime getCreatedAt() {
return createdAt;
}

public Session getSession(int generation) {
validateGeneration(generation);
return this.sessions.get(generation - 1);
}

public void addSession(Session session) {
this.sessions.add(session);
}

private void validateGeneration(int generation) {
validateNegative(generation);
validateRange(generation);
}

private void validateNegative(int generation) {
if (generation <= 0) {
throw new IllegalArgumentException("기수는 1 기수 이상부터 시작합니다. 조회한 기수 = " + generation);
}
}

private void validateRange(int generation) {
if (sessions.size() < generation) {
throw new IllegalArgumentException("해당 기수의 강의는 존재하지 않습니다. 조회한 기수 = " + generation);
}
}

@Override
public String toString() {
return "Course{" +
"id=" + id +
", title='" + title + '\'' +
", creatorId=" + creatorId +
", sessions=" + sessions +
", createdAt=" + createdAt +
", updatedAt=" + updatedAt +
'}';
Expand Down
38 changes: 38 additions & 0 deletions src/main/java/nextstep/courses/domain/Session.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package nextstep.courses.domain;

import java.time.LocalDateTime;

public class Session {

private final SessionInfo sessionInfo;
private final SessionEnrollment sessionEnrollment;
private final SessionTimeLine sessionTimeLine;

public Session(Long courseId, Long ownerId, String title, String coverImageInfo,
SessionType sessionType, SessionStatus sessionStatus,
LocalDateTime createdAt, LocalDateTime closedAt, Long maxNumOfStudent) {

this(new SessionInfo(courseId, ownerId, title, coverImageInfo, sessionType),
new SessionEnrollment(sessionStatus, maxNumOfStudent),
new SessionTimeLine(createdAt, closedAt));
}

public Session(SessionInfo sessionInfo, SessionEnrollment sessionEnrollment,
SessionTimeLine sessionTimeLine){
this.sessionInfo = sessionInfo;
this.sessionEnrollment = sessionEnrollment;
this.sessionTimeLine = sessionTimeLine;
}

public void enroll(Student student) {
sessionEnrollment.enroll(student);
}

public Long totalStudentNum() {
return sessionEnrollment.totalStudentNum();
}

public boolean isPositionFull() {
return sessionEnrollment.isPositionFull();
}
}
41 changes: 41 additions & 0 deletions src/main/java/nextstep/courses/domain/SessionEnrollment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package nextstep.courses.domain;

import java.util.HashSet;
import java.util.Set;

public class SessionEnrollment {

private final SessionStatus sessionStatus;
private final Set<Student> students = new HashSet<>();
private final Long capacity;

public SessionEnrollment(SessionStatus sessionStatus, Long capacity) {
this.sessionStatus = sessionStatus;
this.capacity = capacity;
}

public void enroll(Student student) {
if (!sessionStatus.canJoin()) {
throw new CannotEnrollException("현재는 수강신청을 할 수 없는 강의 상태입니다. 현재 강의 상태 = " + sessionStatus.name());
}

if (isPositionFull()) {
throw new CannotEnrollException(
"현재 강의(Session)는 수강인원이 꽉 차서 더 이상 등록할 수 없습니다." + "최대인원 = " + capacity);
}

if (students.contains(student)) {
throw new AlreadyEnrollmentException(student + " 학생은 이미 등록한 상태입니다.");
}
this.students.add(student);
}

public Long totalStudentNum() {
return Long.valueOf(students.size());
}

public boolean isPositionFull() {
return totalStudentNum() == capacity;
}

}
18 changes: 18 additions & 0 deletions src/main/java/nextstep/courses/domain/SessionInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package nextstep.courses.domain;

public class SessionInfo {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


private final Long courseId;
private final Long ownerId;
private final String title;
private final String coverImageInfo;
private final SessionType sessionType;

public SessionInfo(Long courseId, Long ownerId, String title, String coverImageInfo, SessionType sessionType) {
this.courseId = courseId;
this.ownerId = ownerId;
this.title = title;
this.coverImageInfo = coverImageInfo;
this.sessionType = sessionType;
}
}
12 changes: 12 additions & 0 deletions src/main/java/nextstep/courses/domain/SessionRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package nextstep.courses.domain;

import java.util.List;

public interface SessionRepository {

int save(String session);

Session findById(Long id);

List<Session> findByCourseId(Long courseId);
}
20 changes: 20 additions & 0 deletions src/main/java/nextstep/courses/domain/SessionStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package nextstep.courses.domain;

public enum SessionStatus {

READY("준비중"),
OPENED("모집중"),
CLSOED("종료")
;

private String name;

SessionStatus(String name) {
this.name = name;
}

public boolean canJoin() {
return this.equals(OPENED);
}

}
21 changes: 21 additions & 0 deletions src/main/java/nextstep/courses/domain/SessionTimeLine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package nextstep.courses.domain;

import java.time.LocalDateTime;

public class SessionTimeLine {

private LocalDateTime createAt;
private LocalDateTime closeAt;

public SessionTimeLine(LocalDateTime createAt, LocalDateTime closeAt) {
validateInterval(createAt, closeAt);
this.createAt = createAt;
this.closeAt = closeAt;
}

private void validateInterval(LocalDateTime createAt, LocalDateTime closeAt) {
if (createAt.isAfter(closeAt)) {
throw new IllegalArgumentException("강의 시작일과 마감일을 잘못 입력하였습니다.");
}
}
}
13 changes: 13 additions & 0 deletions src/main/java/nextstep/courses/domain/SessionType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nextstep.courses.domain;

public enum SessionType {

FREE("무료"),
CHANGED("유료")
;

private String name;
SessionType(String name) {
this.name = name;
}
}
16 changes: 16 additions & 0 deletions src/main/java/nextstep/courses/domain/Student.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package nextstep.courses.domain;

public class Student {

private final Long studentId;
private final Long sessionId;

public Student(Long studentId, Long sessionId) {
this.studentId = studentId;
this.sessionId = sessionId;
}

public void enroll(Session session) {
session.enroll(this);
}
}
10 changes: 10 additions & 0 deletions src/main/java/nextstep/courses/domain/StudentRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package nextstep.courses.domain;

import java.util.List;

public interface StudentRepository {

int save(Student student);

List<Student> findBySessionId(Long sessionId);
}
28 changes: 3 additions & 25 deletions src/main/java/nextstep/qna/domain/Answer.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,35 +71,13 @@ public String toString() {

public DeleteHistory delete() {
isSameUser();
this.setDeleted(true);
return DeleteHistory.createAnswer(this.id, this.writer);
this.deleted = true;
return DeleteHistory.createAnswer(this);
}

private void isSameUser() {
if (!this.writer.matchUser(this.question.getWriter())) {
throw new CannotDeleteException("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다.");
}
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Answer answer = (Answer) o;
return isDeleted() == answer.isDeleted()
&& Objects.equals(getId(), answer.getId())
&& Objects.equals(getWriter(), answer.getWriter())
&& Objects.equals(question, answer.question)
&& Objects.equals(getContents(), answer.getContents())
&& Objects.equals(createdDate, answer.createdDate);
}

@Override
public int hashCode() {
return Objects.hash(getId(), getWriter(), question, getContents(), isDeleted(), createdDate);
}
}
}
6 changes: 5 additions & 1 deletion src/main/java/nextstep/qna/domain/Answers.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.util.Objects;

public class Answers implements Iterable<Answer> {

private final List<Answer> answers;

public Answers() {
Expand All @@ -24,6 +23,11 @@ public List<Answer> getAnswers() {
return this.answers;
}

public DeleteHistories delete(DeleteHistories deleteHistories) {
answers.stream()
.forEach(answer -> deleteHistories.add(answer.delete()));
return deleteHistories;
}
@Override
public Iterator<Answer> iterator() {
return answers.iterator();
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/nextstep/qna/domain/DeleteHistory.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ public DeleteHistory(ContentType contentType, Long contentId, NsUser deletedBy)
this.deletedBy = deletedBy;
}

public static DeleteHistory createAnswer(Long id, NsUser writer) {
return new DeleteHistory(ContentType.ANSWER, id, writer);
public static DeleteHistory createAnswer(Answer answer) {
return new DeleteHistory(ContentType.ANSWER, answer.getId(), answer.getWriter());
}

public static DeleteHistory createQuestion(Long id, NsUser writer) {
return new DeleteHistory(ContentType.QUESTION, id, writer);
public static DeleteHistory createQuestion(Question question) {
return new DeleteHistory(ContentType.QUESTION, question.getId(), question.getWriter());
}

@Override
Expand Down
Loading