Skip to content

πŸš€ 2단계 - μˆ˜κ°•μ‹ μ²­(도메인 λͺ¨λΈ) #715

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

Open
wants to merge 15 commits into
base: wlwpfh
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,25 @@
* λͺ¨λ“  ν”Όλ“œλ°±μ„ μ™„λ£Œν•˜λ©΄ λ‹€μŒ 단계λ₯Ό λ„μ „ν•˜κ³  μ•žμ˜ 과정을 λ°˜λ³΅ν•œλ‹€.

## 온라인 μ½”λ“œ 리뷰 κ³Όμ •
* [ν…μŠ€νŠΈμ™€ μ΄λ―Έμ§€λ‘œ μ‚΄νŽ΄λ³΄λŠ” 온라인 μ½”λ“œ 리뷰 κ³Όμ •](https://github.com/next-step/nextstep-docs/tree/master/codereview)
* [ν…μŠ€νŠΈμ™€ μ΄λ―Έμ§€λ‘œ μ‚΄νŽ΄λ³΄λŠ” 온라인 μ½”λ“œ 리뷰 κ³Όμ •](https://github.com/next-step/nextstep-docs/tree/master/codereview)

## 2단계 μš”κ΅¬μ‚¬ν•­
- κ°•μ˜
- [ ] κ³Όμ •(Course)은 기수 λ‹¨μœ„λ‘œ μš΄μ˜ν•˜λ©°, μ—¬λŸ¬ 개의 κ°•μ˜(Session)λ₯Ό κ°€μ§ˆ 수 μžˆλ‹€.
- [x] κ°•μ˜λŠ” μ‹œμž‘μΌκ³Ό μ’…λ£ŒμΌμ„ κ°€μ§„λ‹€.
- [x] κ°•μ˜λŠ” κ°•μ˜ 컀버 이미지 정보λ₯Ό κ°€μ§„λ‹€.
- [ ] κ°•μ˜λŠ” 무료 κ°•μ˜μ™€ 유료 κ°•μ˜λ‘œ λ‚˜λ‰œλ‹€.
- [ ] 무료 κ°•μ˜λŠ” μ΅œλŒ€ μˆ˜κ°• 인원 μ œν•œμ΄ μ—†λ‹€.
Copy link

Choose a reason for hiding this comment

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

ν•΄λ‹Ή μš”κ΅¬μ‚¬ν•­μ΄ κ΅¬ν˜„λ˜μ§€ μ•Šμ€μ΄μœ κ°€ μžˆμ„κΉŒμš”?

- [x] 유료 κ°•μ˜λŠ” κ°•μ˜ μ΅œλŒ€ μˆ˜κ°• 인원을 μ΄ˆκ³Όν•  수 μ—†λ‹€.
- [x] 유료 κ°•μ˜λŠ” μˆ˜κ°•μƒμ΄ κ²°μ œν•œ κΈˆμ•‘κ³Ό μˆ˜κ°•λ£Œκ°€ μΌμΉ˜ν•  λ•Œ μˆ˜κ°• 신청이 κ°€λŠ₯ν•˜λ‹€.
- [x] κ°•μ˜ μƒνƒœλŠ” 쀀비쀑, λͺ¨μ§‘쀑, μ’…λ£Œ 3κ°€μ§€ μƒνƒœλ₯Ό κ°€μ§„λ‹€.
- [x] κ°•μ˜ μˆ˜κ°•μ‹ μ²­μ€ κ°•μ˜ μƒνƒœκ°€ λͺ¨μ§‘쀑일 λ•Œλ§Œ κ°€λŠ₯ν•˜λ‹€.
- [ ] 유료 κ°•μ˜μ˜ 경우 κ²°μ œλŠ” 이미 μ™„λ£Œν•œ κ²ƒμœΌλ‘œ κ°€μ •ν•˜κ³  이후 과정을 κ΅¬ν˜„ν•œλ‹€.

- 이미지
- [x] 이미지 ν¬κΈ°λŠ” 1MB μ΄ν•˜μ—¬μ•Ό ν•œλ‹€.
- [x] 이미지 νƒ€μž…μ€ gif, jpg(jpeg 포함), png, svg만 ν—ˆμš©ν•œλ‹€.
- [x] μ΄λ―Έμ§€μ˜ widthλŠ” 300ν”½μ…€, heightλŠ” 200ν”½μ…€ 이상이어야 ν•˜λ©°, width와 height의 λΉ„μœ¨μ€ 3:2μ—¬μ•Ό ν•œλ‹€.

- 결제
- [ ] 결제λ₯Ό μ™„λ£Œν•œ 결제 μ •λ³΄λŠ” payments λͺ¨λ“ˆμ„ 톡해 κ΄€λ¦¬λ˜λ©°, 결제 μ •λ³΄λŠ” Payment 객체에 담겨 λ°˜ν•œλœλ‹€.
7 changes: 7 additions & 0 deletions src/main/java/nextstep/courses/CannotEnrollException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package nextstep.courses;

public class CannotEnrollException extends RuntimeException {
public CannotEnrollException(String message) {
super(message);
}
}
11 changes: 11 additions & 0 deletions src/main/java/nextstep/courses/InvalidImageException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package nextstep.courses;

public class InvalidImageException extends RuntimeException {
Copy link

Choose a reason for hiding this comment

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

λ‹¨μˆœνžˆ λ©”μ‹œμ§€λ§Œ λ°›λŠ”κ²ƒμ΄λΌλ©΄,
java κΈ°λ³Έ excpetion으둜 μ‚¬μš©ν• μˆ˜ μžˆμ—ˆμ„ 텐데,
custom exception을 λ§Œλ“  μ΄μœ κ°€ 무엇인지 κΆκΈˆν•©λ‹ˆλ‹€!

Copy link
Author

Choose a reason for hiding this comment

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

ν˜„μž¬ λ„λ©”μΈλ³„λ‘œ custom exception으둜 μ˜ˆμ™Έμ²˜λ¦¬λ₯Ό ν•˜μ—¬ 이와 κ°™κ²Œ μ§„ν–‰ν•˜μ˜€μŠ΅λ‹ˆλ‹€..!

public InvalidImageException(String message) {
super(message);
}

public InvalidImageException(){

}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package nextstep.courses.domain;
package nextstep.courses.domain.course;

import java.time.LocalDateTime;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package nextstep.courses.domain;
package nextstep.courses.domain.course;

public interface CourseRepository {
int save(Course course);
Expand Down
51 changes: 51 additions & 0 deletions src/main/java/nextstep/courses/domain/session/Enrollment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package nextstep.courses.domain.session;

import nextstep.users.domain.NsUser;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class Enrollment {
private final List<NsUser> users;
private final SessionCapacity sessionCapacity;

public Enrollment(List<NsUser> users, SessionCapacity sessionCapacity) {
this.users = users;
this.sessionCapacity = sessionCapacity;
}

public Enrollment(SessionCapacity sessionCapacity) {
Copy link

Choose a reason for hiding this comment

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

PRμš”μ²­μ‹œ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” λ©”μ†Œλ“œλŠ” 과감히 μ œκ±°ν•˜λŠ”κ²ƒμ΄ μ’‹λ‹€κ³ μƒκ°ν•©λ‹ˆλ‹€.
ν˜Ήμ‹œ μΆ”ν›„ μ°Έκ³ ν•΄μ•Όλ˜λŠ” μ½”λ“œλΌλ©΄, μ μ ˆν•œ commitλ©”μ‹œμ§€λ‘œ 남겨 λ†“λŠ”κ²ƒλ„ ν•˜λ‚˜μ˜ 방법일것 κ°™μŠ΅λ‹ˆλ‹€ πŸ€”

this(new ArrayList<>(), sessionCapacity);
}

public Enrollment(int capacity) {
this(new ArrayList<>(), new SessionCapacity(capacity));
}

public Enrollment(List<NsUser> users) {
this(users, new SessionCapacity(0));
}

public void enroll(NsUser user) {
sessionCapacity.increase();
this.users.add(user);
}

@Override
public int hashCode() {
return Objects.hashCode(users);
}

@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
Enrollment enrollment = (Enrollment) object;
return Objects.equals(enrollment.users, this.users);
}
}
43 changes: 43 additions & 0 deletions src/main/java/nextstep/courses/domain/session/Session.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package nextstep.courses.domain.session;

import nextstep.courses.CannotEnrollException;
import nextstep.courses.strategy.PaymentStrategy;
import nextstep.payments.domain.Payment;
import nextstep.users.domain.NsUser;

import java.time.LocalDate;

public class Session {
private final SessionImage image;
private final SessionDate date;
private final SessionState state;
private final Enrollment enrollment;
private final PaymentStrategy paymentStrategy;

public Session(SessionImage image, SessionDate date, SessionState state, Enrollment enrollment, PaymentStrategy paymentStrategy) {
this.image = image;
this.date = date;
this.state = state;
this.enrollment = enrollment;
this.paymentStrategy = paymentStrategy;
}

public void applySession(NsUser user, LocalDate enrollDate, Payment payment) {
if (!canApply(enrollDate, payment)) {
throw new CannotEnrollException("등둝 λΆˆκ°€λŠ₯ν•œ μƒνƒœμž…λ‹ˆλ‹€.");
}
this.enrollment.enroll(user);
}

private boolean canApply(LocalDate enrollDate, Payment payment) {
if (!state.canRecruit()) {
Copy link

Choose a reason for hiding this comment

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

Suggested change
if (!state.canRecruit()) {
if (state.cannotRecruit()) {

!ν‘œν˜„ λ³΄λ‹€λŠ” μžˆλŠ” κ·ΈλŒ€λ‘œ λ©”μ†Œλ“œλͺ…μœΌλ‘œ ν‘œν˜„ν•˜λŠ”κ²Œ 가독성에 μ’‹μ„μˆ˜λ„ μžˆλ‹€κ³ μƒκ°λ˜λ„€μš” πŸ€”

return false;
}

if (!date.isBefore(enrollDate)) {
return false;
}

return paymentStrategy.payable(payment);
}
}
57 changes: 57 additions & 0 deletions src/main/java/nextstep/courses/domain/session/SessionCapacity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package nextstep.courses.domain.session;

import nextstep.courses.CannotEnrollException;

import java.util.Objects;

public class SessionCapacity {
private static final int MIN_CAPACITY = 1;

private int capacity;
private final int maxCapacity;

public SessionCapacity(int capacity, int maxCapacity) {
this.capacity = capacity;
this.maxCapacity = maxCapacity;
checkValidCapacity();
}

public SessionCapacity(int maxCapacity) {
this(0, maxCapacity);
}

private void checkValidCapacity() {
if (maxCapacity < MIN_CAPACITY) {
throw new IllegalArgumentException();
}
isValidCapacity();
}

public void increase() {
capacity++;
isValidCapacity();
}
Comment on lines +30 to +33
Copy link

Choose a reason for hiding this comment

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

Suggested change
public void increase() {
capacity++;
isValidCapacity();
}
public void increase() {
capacity++;
isValidCapacity();
}

ν•΄λ‹Ή μ½”λ“œλ₯Ό 보고 의문점이 λ“œλŠ”κ²Œ ν•œκ°€μ§€ μžˆλŠ”λ°μš”,

        try {
            SessionCapacity sessionCapacity = new SessionCapacity(10, 5);
            sessionCapacity.increase();
        } catch (CannotEnrollException e) {
            System.out.println(e.getMessage());
        }

        // blabla

μœ„ ν…ŒμŠ€νŠΈ μ½”λ“œλŠ” 10μ–΄μ•Ό ν• κΉŒμš” 11μ΄μ–΄μ•Όν• κΉŒμš”?

κ·Έλ ‡λ‹€λ©΄ 무엇이 λ¬Έμ œμΌκΉŒμš”?

public void increase() {
    isValidCapacity();
    capacity++;
}

μœ„μΉ˜λ₯Ό μ‘°μ •ν•΄λ³΄κ±°λ‚˜, capacity λ₯Ό λΆˆλ³€κ°μ²΄λ‘œ 관점 μ „ν™˜ ν›„ ν•΄κ²°ν•΄λ³Όμˆ˜λ„ μžˆμ„κ²„κ°™λ„€μš” πŸ€”


@Override
public int hashCode() {
return Objects.hash(capacity, maxCapacity);
}

@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
SessionCapacity sessionCapacity = (SessionCapacity) object;
return sessionCapacity.capacity == this.capacity && sessionCapacity.maxCapacity == this.maxCapacity;
}

private void isValidCapacity(){
if(this.capacity > this.maxCapacity) {
throw new CannotEnrollException("μ΅œλŒ€ 수용 인원을 ν˜„μž¬ 인원이 μ΄ˆκ³Όν•  수 μ—†λ‹€.");
}
}
}
17 changes: 17 additions & 0 deletions src/main/java/nextstep/courses/domain/session/SessionDate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package nextstep.courses.domain.session;

import java.time.LocalDate;

public class SessionDate {
private final LocalDate startDate;
private final LocalDate endDate;

public SessionDate(LocalDate startDate, LocalDate endDate) {
this.startDate = startDate;
this.endDate = endDate;
Comment on lines +10 to +11
Copy link

Choose a reason for hiding this comment

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

endDateκ°€ startDate보닀 이전이면 객체가 μƒμ„±μ•ˆλ˜κ²Œ ν•˜λŠ”κ²Œ 더 ν™•μ‹€ν•˜μ§€ μ•Šμ„κΉŒμš”? μ•„λ‹ˆλ©΄, endDateκ°€ startDate보닀 이전이라도 μƒμ„±λ˜μ–΄μ•Όν•˜λŠ” κ²½μš°κ°€ μžˆλ‚˜μš”?

}

public boolean isBefore(LocalDate date) {
return date.isBefore(startDate);
}
}
59 changes: 59 additions & 0 deletions src/main/java/nextstep/courses/domain/session/SessionImage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package nextstep.courses.domain.session;

import nextstep.courses.InvalidImageException;

import java.util.Objects;

public class SessionImage {
private static final int MAX_IMAGE_SIZE = 1000000;
private static final int MIN_WIDTH = 300;
private static final int MIN_HEIGHT = 200;
private static final double WIDTH_PER_HEIGHT = 1.5;

private final int width;
private final int height;
private final int size;
private final SessionImageType imageType;

public SessionImage(int width, int height, int size, String imageType) {
this(width, height, size, SessionImageType.of(imageType));
}

public SessionImage(int width, int height, int size, SessionImageType imageType) {
this.width = width;
this.height = height;
this.size = size;
this.imageType = imageType;
checkValidSessionImage();
}

private void checkValidSessionImage() {
if (this.width < MIN_WIDTH || this.height < MIN_HEIGHT) {
throw new InvalidImageException("μ΄λ―Έμ§€μ˜ widthλŠ” 300ν”½μ…€, heightλŠ” 200ν”½μ…€ 이상이어야 ν•œλ‹€.");
Copy link

Choose a reason for hiding this comment

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

쑰건이 λ³€κ²½λ λ•Œλ§ˆλ‹€ μ˜ˆμ™Έ λ©”μ‹œμ§€κΉŒμ§€ ν•¨κ»˜ λ³€κ²½ν•΄μ•Όν•˜λŠ”κ²ƒμ€ μœ μ§€λ³΄μˆ˜μ‹œ λ¦¬μŠ€ν¬κ°€ μžˆμ§€ μ•Šμ„κΉŒμš”?

}
if ((double) this.width / this.height != WIDTH_PER_HEIGHT) {
throw new InvalidImageException("μ΄λ―Έμ§€μ˜ width, height의 λΉ„μœ¨μ€ 3:2μ—¬μ•Ό ν•œλ‹€.");
}

if (this.size > MAX_IMAGE_SIZE) {
throw new InvalidImageException("μ΄λ―Έμ§€μ˜ ν¬κΈ°λŠ” 1MB μ΄ν•˜μ—¬μ•Ό ν•œλ‹€.");
}
}

@Override
public int hashCode() {
return Objects.hash(width, height, size, imageType);
}

@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
SessionImage image = (SessionImage) object;
return Objects.equals(image.imageType, imageType) && image.width == width && image.height == height && image.size == size;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package nextstep.courses.domain.session;

import nextstep.courses.InvalidImageException;

import java.util.Arrays;

public enum SessionImageType {
gif("gif"), jpg("jpg"), jpeg("jpeg"), png("png"), svg("svg");

private final String name;

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

public static SessionImageType of(String name) {
return Arrays.stream(values())
.filter(type -> type.name.equals(name))
.findFirst()
.orElseThrow(InvalidImageException::new);

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

public enum SessionState {
PREPARING,
RECRUITING,
CLOSED;

public boolean canRecruit(){
return this == RECRUITING;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package nextstep.courses.infrastructure;

import nextstep.courses.domain.Course;
import nextstep.courses.domain.CourseRepository;
import nextstep.courses.domain.course.Course;
import nextstep.courses.domain.course.CourseRepository;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/nextstep/courses/strategy/FreePaymentStrategy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package nextstep.courses.strategy;

import nextstep.payments.domain.Payment;

public class FreePaymentStrategy implements PaymentStrategy {
@Override
public boolean payable(Payment payment) {
return true;
}
}
18 changes: 18 additions & 0 deletions src/main/java/nextstep/courses/strategy/PaidPaymentStrategy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package nextstep.courses.strategy;

import nextstep.payments.domain.Payment;

public class PaidPaymentStrategy implements PaymentStrategy {
private final long price;

public PaidPaymentStrategy(long price) {
this.price = price;
}

@Override
public boolean payable(Payment payment) {
if (payment.isSameAmount(price))
return true;
return false;
Comment on lines +14 to +16
Copy link

Choose a reason for hiding this comment

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

Suggested change
if (payment.isSameAmount(price))
return true;
return false;
return payment.isSameAmount(price);

μ‰½κ²Œ ν‘œν˜„ν• μˆ˜μžˆλŠ”κ²ƒμ€ μ‰½κ²Œ ν‘œν˜„ν•΄λ„ 쒋을것 κ°™μ•„μš”~

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

import nextstep.payments.domain.Payment;

public interface PaymentStrategy {
boolean payable(Payment payment);
}
4 changes: 4 additions & 0 deletions src/main/java/nextstep/payments/domain/Payment.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ public Payment(String id, Long sessionId, Long nsUserId, Long amount) {
this.amount = amount;
this.createdAt = LocalDateTime.now();
}

public boolean isSameAmount(long amount){
return amount == this.amount;
}
}
Loading