-
Notifications
You must be signed in to change notification settings - Fork 301
Step2 #721
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: youlalala
Are you sure you want to change the base?
Step2 #721
Changes from all commits
ff9d43e
4795bb8
568fda8
35e53a3
0bc40f5
e91212d
a3c1961
0f43911
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,7 @@ | ||
package nextstep.courses; | ||
|
||
public class CannotEnrollSessionException extends RuntimeException { | ||
public CannotEnrollSessionException(String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package nextstep.courses; | ||
|
||
public class InvalidCoverImageException extends RuntimeException { | ||
|
||
public InvalidCoverImageException(String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package nextstep.courses.domain; | ||
|
||
import nextstep.courses.InvalidCoverImageException; | ||
|
||
public class CoverImage { | ||
|
||
private final int width; | ||
private final int height; | ||
private final int sizeInBytes; | ||
private final ImageExtension extension; | ||
|
||
public CoverImage(int width, int height, int sizeInBytes, ImageExtension extension) { | ||
this.width = width; | ||
this.height = height; | ||
this.sizeInBytes = sizeInBytes; | ||
this.extension = extension; | ||
validate(); | ||
} | ||
|
||
private void validate() { | ||
if (sizeInBytes > 1_000_000) { | ||
throw new InvalidCoverImageException("1MB를 초과하는 이미지입니다."); | ||
} | ||
if (width < 300) { | ||
throw new InvalidCoverImageException("너비는 300px 이상이어야 합니다."); | ||
} | ||
if (height < 200) { | ||
throw new InvalidCoverImageException("높이는 200px 이상이어야 합니다."); | ||
} | ||
if (width * 2 != height * 3) { | ||
throw new InvalidCoverImageException("비율은 3:2여야 합니다."); | ||
} | ||
if (extension == null) { | ||
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. null인 케이스도 있겠지만 확장자가 |
||
throw new InvalidCoverImageException("지원하지 않는 확장자입니다."); | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package nextstep.courses.domain; | ||
|
||
public enum ImageExtension { | ||
GIF("gif"), | ||
JPG("jpg"), | ||
JPEG("jpeg"), | ||
PNG("png"), | ||
SVG("svg"); | ||
|
||
private final String value; | ||
|
||
ImageExtension(String value) { | ||
this.value = value; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package nextstep.courses.domain; | ||
|
||
import nextstep.courses.CannotEnrollSessionException; | ||
import nextstep.payments.domain.EnrollmentPolicy; | ||
import nextstep.payments.domain.Payment; | ||
|
||
import java.time.LocalDate; | ||
|
||
public class Session { | ||
|
||
private final LocalDate startDate; | ||
private final LocalDate endDate; | ||
private final CoverImage coverImage; | ||
private final SessionStatus status; | ||
private final EnrollmentPolicy enrollmentPolicy; | ||
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. (반영하지 않으셔도 됩니다.) |
||
|
||
private int currentEnrolledCount = 0; | ||
|
||
public Session(LocalDate startDate, | ||
LocalDate endDate, | ||
CoverImage coverImage, | ||
SessionStatus status, | ||
EnrollmentPolicy enrollmentPolicy) { | ||
this.startDate = startDate; | ||
this.endDate = endDate; | ||
this.coverImage = coverImage; | ||
this.status = status; | ||
this.enrollmentPolicy = enrollmentPolicy; | ||
} | ||
|
||
public void enroll(Payment payment) { | ||
if (!this.status.canEnroll()) { | ||
throw new CannotEnrollSessionException("모집 중이 아닙니다."); | ||
} | ||
|
||
if (!enrollmentPolicy.canEnroll(currentEnrolledCount, payment)) { | ||
throw new CannotEnrollSessionException("수강 조건이 맞지 않습니다."); | ||
} | ||
|
||
currentEnrolledCount++; | ||
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,11 @@ | ||
package nextstep.courses.domain; | ||
|
||
public enum SessionStatus { | ||
READY, | ||
ENROLLING, | ||
COMPLETED; | ||
|
||
public boolean canEnroll() { | ||
return this == ENROLLING; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,16 @@ | ||||||||||||||||||||
package nextstep.courses.domain; | ||||||||||||||||||||
|
||||||||||||||||||||
import java.util.List; | ||||||||||||||||||||
|
||||||||||||||||||||
public class Sessions { | ||||||||||||||||||||
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. 일급컬랙션 👍 |
||||||||||||||||||||
|
||||||||||||||||||||
private List<Session> sessions; | ||||||||||||||||||||
|
||||||||||||||||||||
public Sessions() { | ||||||||||||||||||||
} | ||||||||||||||||||||
Comment on lines
+7
to
+10
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.
Suggested change
이렇게 보완이 되어야할 것 같네요 😄 |
||||||||||||||||||||
|
||||||||||||||||||||
public Sessions(List<Session> sessions) { | ||||||||||||||||||||
this.sessions = sessions; | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package nextstep.payments.domain; | ||
|
||
public interface EnrollmentPolicy { | ||
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. 각 구현체마다 잘 추상화해주셨네요 👍 |
||
boolean canEnroll(int currentEnrolledCount, Payment payment); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package nextstep.payments.domain; | ||
|
||
public class FreeEnrollmentPolicy implements EnrollmentPolicy { | ||
|
||
@Override | ||
public boolean canEnroll(int currentEnrolledCount, Payment payment) { | ||
return payment.isSameAmount(0L); | ||
} | ||
Comment on lines
+6
to
+8
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,18 @@ | ||
package nextstep.payments.domain; | ||
|
||
public class PaidEnrollmentPolicy implements EnrollmentPolicy { | ||
|
||
private final int maxEnrolledCount; | ||
private final int price; | ||
Comment on lines
+3
to
+6
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 PaidEnrollmentPolicy(int maxEnrolledCount, int price) { | ||
this.maxEnrolledCount = maxEnrolledCount; | ||
this.price = price; | ||
} | ||
|
||
@Override | ||
public boolean canEnroll(int currentEnrolledCount, Payment payment) { | ||
return currentEnrolledCount < maxEnrolledCount && payment.isSameAmount((long) price); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package nextstep.courses.domain; | ||
|
||
import nextstep.courses.InvalidCoverImageException; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; | ||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; | ||
|
||
public class CoverImageTest { | ||
|
||
@Test | ||
void 유효한_커버이미지는_예외없이_생성되고_검증_통과() { | ||
assertThatCode(() -> | ||
new CoverImage(600, 400, 500_000, ImageExtension.JPG) | ||
).doesNotThrowAnyException(); | ||
} | ||
|
||
@Test | ||
void 크기가_1MB_초과하면_예외발생() { | ||
assertThatThrownBy(() -> | ||
new CoverImage(600, 400, 2_000_000, ImageExtension.PNG) | ||
).isInstanceOf(InvalidCoverImageException.class); | ||
} | ||
|
||
@Test | ||
void 너비가_300미만이면_예외발생() { | ||
assertThatThrownBy(() -> | ||
new CoverImage(299, 400, 500_000, ImageExtension.PNG) | ||
).isInstanceOf(InvalidCoverImageException.class); | ||
} | ||
|
||
@Test | ||
void 높이가_200미만이면_예외발생() { | ||
assertThatThrownBy(() -> | ||
new CoverImage(600, 199, 500_000, ImageExtension.PNG) | ||
).isInstanceOf(InvalidCoverImageException.class); | ||
} | ||
|
||
@Test | ||
void 비율이_3대2_아니면_예외발생() { | ||
assertThatThrownBy(() -> | ||
new CoverImage(600, 500, 500_000, ImageExtension.PNG) | ||
).isInstanceOf(InvalidCoverImageException.class); | ||
} | ||
|
||
@Test | ||
void 지원하지_않는_확장자면_예외발생() { | ||
assertThatThrownBy(() -> | ||
new CoverImage(600, 400, 500_000, null) | ||
).isInstanceOf(InvalidCoverImageException.class); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package nextstep.courses.domain; | ||
|
||
import nextstep.courses.CannotEnrollSessionException; | ||
import nextstep.payments.domain.PaidEnrollmentPolicy; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.time.LocalDate; | ||
|
||
import static nextstep.payments.PaymentTest.PAYMENT_1000; | ||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; | ||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; | ||
|
||
public class SessionTest { | ||
|
||
public static final Session ReadySession = new Session( | ||
LocalDate.of(2025, 1, 1), | ||
LocalDate.of(2025, 12, 31), | ||
new CoverImage(600, 400, 500_000, ImageExtension.JPG), | ||
SessionStatus.READY, | ||
new PaidEnrollmentPolicy(100, 1000)); | ||
|
||
public static final Session EnrollingSession = new Session( | ||
LocalDate.of(2025, 1, 1), | ||
LocalDate.of(2025, 12, 31), | ||
new CoverImage(600, 400, 500_000, ImageExtension.JPG), | ||
SessionStatus.ENROLLING, | ||
new PaidEnrollmentPolicy(100, 1000)); | ||
|
||
@Test | ||
void 모집중이_아닐_때_수강신청_불가능() { | ||
assertThatThrownBy(() -> | ||
ReadySession.enroll(PAYMENT_1000) | ||
).isInstanceOf(CannotEnrollSessionException.class); | ||
} | ||
|
||
@Test | ||
void 모집중일_때_수강신청_가능() { | ||
assertThatCode(() -> EnrollingSession.enroll(PAYMENT_1000)) | ||
.doesNotThrowAnyException(); | ||
|
||
} | ||
} |
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.
👀