-
Notifications
You must be signed in to change notification settings - Fork 301
feat : course, session 로직 구현 #745
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: jhm9595
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package nextstep.courses.domain; | ||
|
||
public interface Conditional { | ||
public boolean test(int currentNum); | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,16 +4,25 @@ | |
|
||
public class Course { | ||
private Long id; | ||
|
||
private String title; | ||
|
||
private Long creatorId; | ||
|
||
private LocalDateTime createdAt; | ||
|
||
private LocalDateTime updatedAt; | ||
|
||
private int classNo; | ||
private Sessions sessions; | ||
|
||
public int getClassNo() { | ||
return classNo; | ||
} | ||
|
||
public Sessions getSessions() { | ||
return this.sessions; | ||
} | ||
Comment on lines
+12
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
요구사항 속 기수는 하나의 과정에서 생성되는 N 개의 강의를 나타내는 걸로 보이네요. 😄
|
||
|
||
public Course() { | ||
classNo = 0; | ||
sessions = new Sessions(); | ||
} | ||
|
||
public Course(String title, Long creatorId) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package nextstep.courses.domain; | ||
|
||
public class CoverImage { | ||
|
||
private int width; | ||
private int height; | ||
private ImageType imageType; | ||
private long size; | ||
|
||
CoverImage(){ | ||
|
||
} | ||
Comment on lines
+10
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 기본 생성자를 default package private 접근제한자로 만드신 이유가 있을까요? |
||
|
||
public CoverImage(String imageType, long size, int width, int height) { | ||
if (size > 1_000) { | ||
throw new IllegalArgumentException("이미지 크기는 1MB 이하여야 합니다."); | ||
} | ||
if (width < 300) { | ||
throw new IllegalArgumentException("Width는 300픽셀 이상이여야 합니다."); | ||
} | ||
if (height < 200) { | ||
throw new IllegalArgumentException("Height는 200픽셀 이상이여야 합니다."); | ||
} | ||
if ((double) width / (double) height < 1.5) { | ||
throw new IllegalArgumentException("Width와 Height의 비율은 3:2여야 합니다."); | ||
} | ||
this.size = size; | ||
this.width = width; | ||
this.height = height; | ||
this.imageType = ImageType.getCoverImageType(imageType); | ||
} | ||
|
||
public long getSize() { | ||
return size; | ||
} | ||
|
||
public ImageType getImageType() { | ||
return this.imageType; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package nextstep.courses.domain; | ||
|
||
import java.util.Arrays; | ||
|
||
public enum ImageType { | ||
|
||
GIF("GIF"), | ||
JPG("JPG"), | ||
JPEG("JPEG"), | ||
PNG("PNG"), | ||
SVG("SVG"); | ||
|
||
Comment on lines
+5
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 상수의 나열을 enum 으로 풀어내기 💯 👍 |
||
private String imageType; | ||
|
||
ImageType(String imageType) { | ||
this.imageType = imageType; | ||
} | ||
|
||
public static ImageType getCoverImageType(String imageType) { | ||
imageType = imageType.toUpperCase(); | ||
isCoverImageType(imageType); | ||
return valueOf(imageType); | ||
} | ||
|
||
public String getImageType() { | ||
return imageType; | ||
} | ||
|
||
public static boolean isCoverImageType(String imageType) { | ||
return Arrays.stream(values()) | ||
.anyMatch(type -> type.getImageType().equals(imageType.toUpperCase())); | ||
} | ||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package nextstep.courses.domain; | ||
|
||
import nextstep.users.domain.NsUser; | ||
|
||
import java.math.BigDecimal; | ||
import java.time.LocalDate; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class Session { | ||
|
||
private final CoverImage coverImage; | ||
private final LocalDate startDt; | ||
private final LocalDate endDt; | ||
|
||
private int capacity; | ||
private Conditional conditional; | ||
private BigDecimal cost; | ||
private SessionStatus status; | ||
private List<NsUser> students; | ||
|
||
public Session() { | ||
this(new CoverImage(), LocalDate.now(), LocalDate.now()); | ||
} | ||
|
||
public Session(CoverImage coverImage, LocalDate startDt, LocalDate endDt) { | ||
this.coverImage = coverImage; | ||
this.startDt = startDt; | ||
this.endDt = endDt; | ||
this.status = SessionStatus.READY; | ||
this.students = new ArrayList<>(); | ||
} | ||
|
||
Comment on lines
+22
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 생성자 체이닝 활용 👍 |
||
public void asFree() { | ||
this.capacity = Integer.MAX_VALUE; | ||
this.cost = BigDecimal.ZERO; | ||
conditional = (currentNum) -> true; | ||
} | ||
|
||
public void asPaid(int capacity, BigDecimal cost) { | ||
this.capacity = capacity; | ||
this.cost = cost; | ||
conditional = (currentNum) -> currentNum < this.capacity; | ||
Comment on lines
+34
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 처음 Session 이 생성될 때부터 유/무료가 나뉠 수 있도록 팩터리 메서드를 제공하는 것도 방법일거 같네요 😄 |
||
} | ||
|
||
public boolean isAvailable() { | ||
return conditional.test(students.size()); | ||
} | ||
|
||
public boolean isExactCost(BigDecimal cost) { | ||
return cost.compareTo(this.cost) == 0; | ||
} | ||
|
||
public CoverImage getCoverImage() { | ||
return this.coverImage; | ||
} | ||
|
||
public LocalDate getStartDt() { | ||
return startDt; | ||
} | ||
|
||
public LocalDate getEndDt() { | ||
return endDt; | ||
} | ||
|
||
public SessionStatus getSessionStatus() { | ||
return status; | ||
} | ||
|
||
public void apply(NsUser nsUser) { | ||
SessionStatus.isReady(status); | ||
|
||
if (this.isAvailable()) { | ||
students.add(nsUser); | ||
} | ||
} | ||
|
||
public void open() { | ||
status = SessionStatus.open(); | ||
} | ||
|
||
public void close() { | ||
status = SessionStatus.close(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package nextstep.courses.domain; | ||
|
||
public enum SessionStatus { | ||
READY, OPEN, CLOSE; | ||
|
||
public static void isReady(SessionStatus status) { | ||
if(!status.equals(READY)){ | ||
throw new IllegalArgumentException("강의 수강신청은 강의 상태가 모집중일 때만 가능합니다"); | ||
} | ||
} | ||
|
||
public static SessionStatus open(){ | ||
return OPEN; | ||
} | ||
|
||
public static SessionStatus close(){ | ||
return CLOSE; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package nextstep.courses.domain; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class Sessions { | ||
private List<Session> sessions; | ||
|
||
public Sessions() { | ||
sessions = new ArrayList<>(); | ||
} | ||
|
||
public List<Session> getSessions() { | ||
return sessions; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
package nextstep.qna.domain; | ||
|
||
import nextstep.qna.CannotDeleteException; | ||
import nextstep.users.domain.NsUser; | ||
|
||
import java.time.LocalDateTime; | ||
|
@@ -90,7 +91,12 @@ public boolean hasOthersAnswers() { | |
return answers.hasOthersAnswers(writer); | ||
} | ||
|
||
public List<DeleteHistory> delete() { | ||
public List<DeleteHistory> delete() throws CannotDeleteException { | ||
|
||
if(this.hasOthersAnswers()){ | ||
throw new CannotDeleteException("다른 사람이 쓴 답변이 있어 삭제할 수 없습니다."); | ||
} | ||
|
||
List<DeleteHistory> deleteHistories = new ArrayList<>(); | ||
deleteHistories.add(new DeleteHistory(this)); | ||
if(!answers.isEmpty()) { | ||
|
@@ -100,4 +106,7 @@ public List<DeleteHistory> delete() { | |
return deleteHistories; | ||
} | ||
|
||
public boolean isNotOwner(NsUser loginUser) { | ||
return !this.isOwner(loginUser); | ||
} | ||
Comment on lines
+109
to
+111
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 부정형 질의문 제공 👍 👍 |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package nextstep.courses.domain; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import java.math.BigDecimal; | ||
|
||
import static org.assertj.core.api.Assertions.*; | ||
|
||
class CourseTest { | ||
|
||
Course course = new Course(); | ||
|
||
@Test | ||
void 기수를_가진다() { | ||
assertThat(course.getClassNo()).isNotNull(); | ||
} | ||
|
||
@Test | ||
void 여러개의_강의를_가진다() { | ||
assertThat(course.getSessions()).isNotNull(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package nextstep.courses.domain; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.assertj.core.api.Assertions.*; | ||
|
||
class CoverImageTest { | ||
|
||
@Test | ||
void 이미지_크기는_1MB_이하() { | ||
assertThat(new CoverImage("jpg", 1000, 300, 200).getSize()).isEqualTo(1000); | ||
} | ||
|
||
@Test | ||
void 이미지_크기_1MB_초과() { | ||
assertThatThrownBy(() -> { | ||
new CoverImage("jpg", 1100, 300, 200); | ||
}).isInstanceOf(IllegalArgumentException.class); | ||
} | ||
|
||
@Test | ||
void 이미지_타입은_peg_입력_에러() { | ||
assertThatThrownBy(() -> { | ||
new CoverImage("peg", 300, 300, 200); | ||
}).isInstanceOf(IllegalArgumentException.class); | ||
} | ||
|
||
@Test | ||
void 이미지_타입은_jpg_타입_성공() { | ||
assertThat(new CoverImage("jpg", 300, 300, 200).getImageType()).isEqualTo(ImageType.JPG); | ||
} | ||
|
||
@Test | ||
void width_300_이상_height_200_이상() { | ||
assertThat(new CoverImage("jpg", 300, 300, 200)).isNotNull(); | ||
} | ||
|
||
@Test | ||
void width_300_이하() { | ||
assertThatThrownBy(() -> new CoverImage("jpg", 300, 299, 200)) | ||
.isInstanceOf(IllegalArgumentException.class); | ||
} | ||
|
||
@Test | ||
void width_200_미만() { | ||
assertThatThrownBy(() -> new CoverImage("jpg", 300, 300, 199)) | ||
.isInstanceOf(IllegalArgumentException.class); | ||
} | ||
|
||
@Test | ||
void 비율이_3대2가_아닐때() { | ||
assertThatThrownBy(() -> new CoverImage("jpg", 300, 300, 300)) | ||
.isInstanceOf(IllegalArgumentException.class); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@FunctionalInterface
어노테이션을 명세하는 것과 하지 않는 것에는 어떤 차이가 있을까요?