Skip to content
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

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

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

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

# μˆ˜κ°• μ‹ μ²­ κΈ°λŠ₯ μš”κ΅¬μ‚¬ν•­
### Course
κ³Όμ •(Course)은 기수 λ‹¨μœ„λ‘œ 운영, μ—¬λŸ¬ 개의 κ°•μ˜(Session)λ₯Ό κ°€μ§ˆ 수 μžˆλ‹€.
### Session
κ°•μ˜λŠ” μ‹œμž‘μΌκ³Ό μ’…λ£ŒμΌμ„ 가진닀. (Period)
κ°•μ˜λŠ” κ°•μ˜ 컀버 이미지 정보λ₯Ό 가진닀. (Image)
### Image
이미지 ν¬κΈ°λŠ” 1MB μ΄ν•˜μ—¬μ•Ό ν•œλ‹€.
이미지 νƒ€μž…μ€ gif, jpg(jpeg 포함), png, svg만 ν—ˆμš©ν•œλ‹€.
μ΄λ―Έμ§€μ˜ widthλŠ” 300ν”½μ…€, heightλŠ” 200ν”½μ…€ 이상이어야 ν•˜λ©°, width와 height의 λΉ„μœ¨μ€ 3:2μ—¬μ•Ό ν•œλ‹€.
### SessionType
κ°•μ˜λŠ” 무료 κ°•μ˜μ™€ 유료 κ°•μ˜λ‘œ λ‚˜λ‰œλ‹€.
무료 κ°•μ˜λŠ” μ΅œλŒ€ μˆ˜κ°• 인원 μ œν•œμ΄ μ—†λ‹€.
유료 κ°•μ˜λŠ” κ°•μ˜ μ΅œλŒ€ μˆ˜κ°• 인원을 μ΄ˆκ³Όν•  수 μ—†λ‹€.
유료 κ°•μ˜λŠ” μˆ˜κ°•μƒμ΄ κ²°μ œν•œ κΈˆμ•‘κ³Ό μˆ˜κ°•λ£Œκ°€ μΌμΉ˜ν•  λ•Œ μˆ˜κ°• 신청이 κ°€λŠ₯ν•˜λ‹€.
### SessionStatus
κ°•μ˜ μƒνƒœλŠ” 쀀비쀑, λͺ¨μ§‘쀑, μ’…λ£Œ 3가지 μƒνƒœλ₯Ό 가진닀.
κ°•μ˜ μˆ˜κ°•μ‹ μ²­μ€ κ°•μ˜ μƒνƒœκ°€ λͺ¨μ§‘쀑일 λ•Œλ§Œ κ°€λŠ₯ν•˜λ‹€.
유료 κ°•μ˜μ˜ 경우 κ²°μ œλŠ” 이미 μ™„λ£Œν•œ κ²ƒμœΌλ‘œ κ°€μ •ν•˜κ³  이후 과정을 κ΅¬ν˜„ν•œλ‹€.
### Payment
결제λ₯Ό μ™„λ£Œν•œ 결제 μ •λ³΄λŠ” payments λͺ¨λ“ˆμ„ 톡해 κ΄€λ¦¬λ˜λ©°, 결제 μ •λ³΄λŠ” Payment 객체에 담겨 λ°˜ν•œλœλ‹€.
3 changes: 3 additions & 0 deletions src/main/java/nextstep/courses/domain/Course.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nextstep.courses.domain;

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

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

private LocalDateTime updatedAt;

private List<Session> sessionList;

public Course() {
}

Expand Down
17 changes: 17 additions & 0 deletions src/main/java/nextstep/courses/domain/FreeSessionType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package nextstep.courses.domain;

public class FreeSessionType implements SessionType {

private static final int ZERO = 0;

private final int pirce;

public FreeSessionType() {
this.pirce = ZERO;
}

public FreeSessionType registered() {
return new FreeSessionType();
}

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

public enum ImageExtension {

Choose a reason for hiding this comment

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

ν™•μž₯μžλŠ” enum보닀 μ •κ·œμ‹μœΌλ‘œ κ²€μ‚¬ν•΄λ³΄λŠ”κ²Œ μ–΄λ–¨κΉŒμš” ?

GIF, JPG, JPEG, PNG, SVG
}
29 changes: 29 additions & 0 deletions src/main/java/nextstep/courses/domain/PaidSessionType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package nextstep.courses.domain;

import nextstep.payments.domain.Payment;

public class PaidSessionType implements SessionType {

private int maximumHeadCount;
private long price;

public PaidSessionType(int maximumHeadCount, long price) {
this.maximumHeadCount = maximumHeadCount;
this.price = price;
}

private void canRegistered(long payedPrice, int headCount) {
int nextHeadCount = headCount + 1;
if (maximumHeadCount < nextHeadCount) {
throw new IllegalArgumentException("μΈμ›μˆ˜κ°€ μ΄ˆκ³Όν–ˆμŠ΅λ‹ˆλ‹€.");
}
if (payedPrice < this.price) {
throw new IllegalArgumentException("μ§€λΆˆν•˜μ‹  κΈˆμ•‘μ΄ λͺ¨μžλžλ‹ˆλ‹€.");
}
}

public PaidSessionType registered(long payedPrice, int headCount) {

Choose a reason for hiding this comment

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

등둝 κ°€λŠ₯ν•œμ§€ ν™•μΈν•˜λŠ” 뢀뢄을 μΆ”μƒν™”ν•˜λ©΄ 쒋을 것 κ°™μ•„μš”! μ§€κΈˆμ€ μΈν„°νŽ˜μ΄μŠ€μ— λ©”μ„œλ“œκ°€ ν•˜λ‚˜λ„ μ—†λŠ” 것 κ°™μ•„μ„œμš”..!
λ‚˜μ•„κ°€μ„œ 그런 λŠλ‚Œμ΄ λœλ‹€λ©΄ sessionType을 Enum으둜 관리해도 쒋지 μ•Šμ„κΉŒμš” ?
μ§€κΈˆμ€ SessionType을 DB둜 κ΄€λ¦¬ν•˜λ €λ©΄ μ–˜λ„ λ³„λ„μ˜ 도메인이 λ˜μ–΄μ•Ό ν•  것 κ°™μ•„μš”!

canRegistered(payedPrice, headCount);
return new PaidSessionType(headCount + 1, this.price);
}
}
13 changes: 13 additions & 0 deletions src/main/java/nextstep/courses/domain/Session.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nextstep.courses.domain;

public class Session {

Choose a reason for hiding this comment

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

μƒμ„±μžλž‘ λ©”μ„œλ“œκ°€ λ‹€ μ—†κ΅°μš”..!
μˆ˜κ°• 신청에 λŒ€ν•œ μ±…μž„μ€ Session이 가지고 μžˆμ–΄μ•Ό ν•˜μ§€ μ•Šμ„κΉŒμš” ?

Copy link
Author

Choose a reason for hiding this comment

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

λ„ˆλ¬΄ λ§‰λ§‰ν–ˆμŠ΅λ‹ˆλ‹€.. 😒

  1. service에 막 κ΅¬ν˜„λ§Œ 해보고 이처럼 도메인에 μ±…μž„μ„ λ„˜κΈ°λ €λ‹ˆ 감이 잘 μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.
  2. λ„λ©”μΈμ˜ μ±…μž„μ— λŒ€ν•œ 감이 μ•ˆμ˜€λ‹ˆ λ―Έμ…˜μ„ μ΄ν•΄ν•˜κΈ° νž˜λ“€μ—ˆμŠ΅λ‹ˆλ‹€.

μ„ ν λ‹˜κ»˜μ„œλ„ 그뢀뢄을 λŠλΌμ…¨λŠ”μ§€ λ”°λœ»ν•˜κ²Œ ν”Όλ“œλ°± ν•΄μ£Όμ…”μ„œ 쑰금 κΈ°μš΄μ„ μ°¨λ¦° 것 κ°™μŠ΅λ‹ˆλ‹€.
μ •μ‹  차리고 λ‹€μ‹œ ν•΄μ„œ pr μ˜¬λ¦¬κ² μŠ΅λ‹ˆλ‹€. πŸ™‡πŸ™‡πŸ™‡πŸ™‡πŸ™‡


private Long id;
private SessionPeriod period;
private SessionImage image;
private SessionType type;
private SessionStatus status;
private int price;
private int headCount;

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

public class SessionImage {

private static final int ONE_MEGA_BYTE = 1_000_000;

Choose a reason for hiding this comment

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

파일 ν¬κΈ°λŠ” 보톡 byte λ‹¨μœ„λ‘œ, 1024*1024 μš”λŸ° μ‹μœΌλ‘œ ν‘œν˜„ν•΄μš” ~


private Integer capacity;
private ImageExtension extension;
private SessionImageSize size;

public SessionImage(int capacity, ImageExtension extension, int width, int height) {
validate(capacity);
this.capacity = capacity;
this.extension = extension;
this.size = new SessionImageSize(width, height);
}

private void validate(int capacity) {
capacityValidate(capacity);
}

private void capacityValidate(int capacity) {
if (ONE_MEGA_BYTE < capacity) {
throw new IllegalArgumentException(" 이미지 μš©λŸ‰μ€ 1MB μ΄ν•˜λ§Œ κ°€λŠ₯ν•©λ‹ˆλ‹€. ");
}
}

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

public class SessionImageSize {

private static final int WIDTH_RATIO = 3;
private static final int HEIGHT_RATIO = 2;
private static final int WIDTH_MAXIMUM = 300;
private static final int HEIGHT_MAXIMUM = 200;

private int width;
private int height;
private String ratio;

public SessionImageSize(int width, int height) {
validation(width, height);
this.width = width;
this.height = height;
this.ratio = calculateRatio();

Choose a reason for hiding this comment

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

음 ? 이걸 μ™œ 가지고 μžˆλŠ”κ±°μ£  ?

}

private void validation(int width, int height) {
widthAndHeightValidate(width, height);
ratioValidate(width, height);
}

private void ratioValidate(int width, int height) {
if (WIDTH_RATIO != calculaateWidthRatio(width) && HEIGHT_RATIO != calculaateHeightRatio(height)) {

Choose a reason for hiding this comment

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

μ–˜λŠ” width * HEIGHT_RATIO != height * WIDTH_RATIO μš”λ ‡κ²Œ ν‘œν˜„ν•  수 μžˆμ„ 것 κ°™μ•„μš”!

throw new IllegalArgumentException(" 이미지 λΉ„μœ¨μ„ 3:2만 κ°€λŠ₯ν•©λ‹ˆλ‹€.");
}
}

private void widthAndHeightValidate(int width, int height) {
if (width < WIDTH_MAXIMUM || height < HEIGHT_MAXIMUM) {
throw new IllegalArgumentException(" μ΄λ―Έμ§€μ˜ ν¬κΈ°λŠ” μ„Έλ‘œ 300, κ°€λ‘œ 200 ν”½μ…€ μ΄μƒλ§Œ κ°€λŠ₯ν•©λ‹ˆλ‹€. ");
}
}

private String calculateRatio() {
return calculaateWidthRatio(width) + ":" + calculaateHeightRatio(height);
}

private int calculaateWidthRatio(int width) {
int divided = width / 100;
if(WIDTH_RATIO != divided){
divided = divided / WIDTH_RATIO;
}
return divided;
}

private int calculaateHeightRatio(int height) {
int divided = height / 100;
if(HEIGHT_RATIO != divided){
divided = divided / HEIGHT_RATIO;
}
return divided;
}
}
11 changes: 11 additions & 0 deletions src/main/java/nextstep/courses/domain/SessionPeriod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package nextstep.courses.domain;

import java.time.LocalDateTime;

public class SessionPeriod {

private LocalDateTime startAt;

private LocalDateTime endAt;

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

public enum SessionStatus {
PREPARING, RECRUITING, END
}
4 changes: 4 additions & 0 deletions src/main/java/nextstep/courses/domain/SessionType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package nextstep.courses.domain;

public interface SessionType {
}
4 changes: 2 additions & 2 deletions src/main/java/nextstep/qna/domain/Answer.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ public String toString() {
}

public Answer delete(NsUser writer) throws CannotDeleteException {
if (!this.isOwner(writer)) {
if (!isOwner(writer)) {
throw new CannotDeleteException("λ‹€λ₯Έ μ‚¬λžŒμ΄ μ“΄ 닡변이 μžˆμ–΄ μ‚­μ œν•  수 μ—†μŠ΅λ‹ˆλ‹€.");
}
return this.setDeleted(true);
return setDeleted(true);
}
}
39 changes: 34 additions & 5 deletions src/main/java/nextstep/qna/domain/Question.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package nextstep.qna.domain;

import nextstep.qna.CannotDeleteException;
import nextstep.users.domain.NsUser;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import nextstep.qna.CannotDeleteException;
import nextstep.users.domain.NsUser;

public class Question {

private Long id;

private String title;
Expand Down Expand Up @@ -88,13 +89,41 @@ public List<Answer> getAnswers() {

@Override
public String toString() {
return "Question [id=" + getId() + ", title=" + title + ", contents=" + contents + ", writer=" + writer + "]";
return "Question [id=" + getId() + ", title=" + title + ", contents=" + contents
+ ", writer=" + writer + "]";
}

public Question delete(NsUser writer) throws CannotDeleteException {
private Question deleteQuestion(NsUser writer) throws CannotDeleteException {
if (!this.isOwner(writer)) {
throw new CannotDeleteException("μ§ˆλ¬Έμ„ μ‚­μ œν•  κΆŒν•œμ΄ μ—†μŠ΅λ‹ˆλ‹€.");
}
return this.setDeleted(true);
}

private List<Answer> deleteAnswersOfThisQuestion(NsUser writer) {
return getAnswers().stream().map(answer -> {
try {
return answer.delete(writer);
} catch (CannotDeleteException e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());
}

public List<DeleteHistory> deleteQuestionAndRelatedAnswer(NsUser writer, LocalDateTime now)
throws CannotDeleteException {
Question question = deleteQuestion(writer);
List<Answer> answers = deleteAnswersOfThisQuestion(writer);

List<DeleteHistory> deleteHistories = new ArrayList<>();
deleteHistories.add(
new DeleteHistory(ContentType.QUESTION, question.getId(), question.getWriter(), now));

for (Answer answer : answers) {
deleteHistories.add(
new DeleteHistory(ContentType.ANSWER, answer.getId(), answer.getWriter(), now));
}

return deleteHistories;
}
}
23 changes: 3 additions & 20 deletions src/main/java/nextstep/qna/service/DeleteHistoryService.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
package nextstep.qna.service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import nextstep.qna.domain.Answer;
import nextstep.qna.domain.ContentType;
import java.util.List;
import javax.annotation.Resource;
import nextstep.qna.domain.DeleteHistory;
import nextstep.qna.domain.DeleteHistoryRepository;
import nextstep.qna.domain.Question;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

@Service("deleteHistoryService")
public class DeleteHistoryService {

@Resource(name = "deleteHistoryRepository")
private DeleteHistoryRepository deleteHistoryRepository;

Expand All @@ -24,16 +19,4 @@ public void saveAll(List<DeleteHistory> deleteHistories) {
deleteHistoryRepository.saveAll(deleteHistories);
}

public void saveAll(Question question, List<Answer> answers) {
List<DeleteHistory> deleteHistories = new ArrayList<>();
deleteHistories.add(
new DeleteHistory(ContentType.QUESTION, question.getId(), question.getWriter(),
LocalDateTime.now()));
for (Answer answer : answers) {
deleteHistories.add(
new DeleteHistory(ContentType.ANSWER, answer.getId(), answer.getWriter(),
LocalDateTime.now()));
}
this.saveAll(deleteHistories);
}
}
19 changes: 5 additions & 14 deletions src/main/java/nextstep/qna/service/QnAService.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package nextstep.qna.service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import nextstep.qna.CannotDeleteException;
import nextstep.qna.NotFoundException;
import nextstep.qna.domain.Answer;
import nextstep.qna.domain.AnswerRepository;
import nextstep.qna.domain.Question;
import nextstep.qna.domain.DeleteHistory;
import nextstep.qna.domain.QuestionRepository;
import nextstep.users.domain.NsUser;
import org.springframework.stereotype.Service;
Expand All @@ -27,18 +26,10 @@ public class QnAService {

@Transactional
public void deleteQuestion(NsUser loginUser, long questionId) throws CannotDeleteException {
Question deletedQuestion = questionRepository.findById(questionId)
List<DeleteHistory> deleteHistories = questionRepository.findById(questionId)
.orElseThrow(NotFoundException::new)
.delete(loginUser);
.deleteQuestionAndRelatedAnswer(loginUser, LocalDateTime.now());

List<Answer> deletedAnswers = deletedQuestion.getAnswers().stream().map(answer -> {
try {
return answer.delete(loginUser);
} catch (CannotDeleteException e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());

deleteHistoryService.saveAll(deletedQuestion, deletedAnswers);
deleteHistoryService.saveAll(deleteHistories);
}
}
Loading