* 밑줄: 여기서 처리할 부분
1. 게시글 작성:
- 사용자가 텍스트를 입력하고
- 사용자가 공개 대상 (예: 모두 공개, 팔로워 전용)을 선택합니다.
- 사용자가 게시물을 제출합니다.
- 단, 게시물의 글자수는 5글자 이상 500자 이하여야 합니다.
// org.communityfeed.post.domain
// Post.java
public class Post {
// 게시글 아이디
private final Long id;
// 작성자
private final User author;
// 게시글 내용
private final PostContent content;
// 공개 범위
private PostStatus status;
public Post(Long id, User author, String contentText) {
if (author == null) {
throw new IllegalArgumentException();
}
this.id = id;
this.author = author;
this.content = new PostContent(contentText);
this.status = PostStatus.PUBLIC;
}
}
// org.communityfeed.post.domain.content
// PostContent.java
public class PostContent {
private final static int MIN_CONTENT_LENGTH = 5;
private final static int MAX_CONTENT_LENGTH = 500;
// 게시글 내용
private String contentText;
public PostContent(String contentText) {
checkText(contentText);
this.contentText = contentText;
}
// 게시글 내용 길이 제한 체크
private void checkText(String contentText) {
if (contentText == null || contentText.isEmpty()) {
throw new IllegalArgumentException();
}
if (contentText.length() > MAX_CONTENT_LENGTH) {
throw new IllegalArgumentException();
}
if (contentText.length() < MIN_CONTENT_LENGTH) {
throw new IllegalArgumentException();
}
}
}
// PostStatus.java
public enum PostStatus {
PUBLIC, // 전체
ONLY_FOLLOWER, // 팔로워 한정
PRIVATE // 비공개
}
- Post
- 역할:
- 도메인 객체로, 게시글과 관련된 정보를 나타냄
- 책임:
- 고유 식별자인 id로 게시글을 식별
- 작성자 유효성 체크
- 게시글 내용 캡슐화
- 게시글의 공개범위 관리
- 역할:
- PostContent
- 역할:
- 게시글 내용을 관리
- 책임:
- 게시글 내용에 대한 유효성 체크
- 게시글 내용을 외부에서 변경 못하도록 하여 불변성 유지
- 역할:
2. 댓글 작성:
- 시용자가 텍스트를 입력하고
- 사용자가 댓글을 제출합니다.
- 단, 댓글의 글자수는 100자 이하여야 합니다.
// org.communityfeed.post.domain.comment
// Comment.java
public class Comment {
// id
private final Long id;
// 게시글
private final Post post;
// 작성자
private final User author;
// 댓글 내용
private final CommentContent content;
public Comment(Long id, Post post, User author, String contentText) {
if (author == null) {
throw new IllegalArgumentException();
}
if (post == null) {
throw new IllegalArgumentException();
}
this.id = id;
this.post = post;
this.author = author;
this.content = new CommentContent(contentText);
}
}
// org.communityfeed.post.domain.content
// CommentContent.java
public class CommentContent {
private static final int MAX_CONTENT_LENGTH = 100;
private String contentText;
public CommentContent(String contentText) {
checkText(contentText);
this.contentText = contentText;
}
// 댓글 내용 길이 유효성 체크
private void checkText(String contentText) {
if (contentText == null || contentText.isEmpty()) {
throw new IllegalArgumentException();
}
if (contentText.length() > MAX_CONTENT_LENGTH) {
throw new IllegalArgumentException();
}
}
}
- Comment
- 역할:
- 도메인 객체로, 댓글과 관련된 정보를 포함
- 책임:
- 고유 식별자인 id로 댓글을 식별
- 작성자, 게시글 유효성 체크
- 댓글 내용 캡슐화
- 역할:
- CommentContent
- 역할:
- 댓글 내용을 관리
- 책임:
- 댓글 내용에 대한 유효성 체크
- 댓글 내용을 외부에서 변경 못하도록 하여 불변성 유지
- 역할:
3. PostContent, CommentContent 추상화:
// org.communityfeed.post.domain.content
// Content.java
public abstract class Content {
String contentText;
protected Content(String contentText) {
checkText(contentText);
this.contentText = contentText;
}
// 자식 객체에서 선언할 추상 메서드
protected abstract void checkText(String contentText);
public String getContentText() { return contentText; }
}
// PostContent.java 수정
public class PostContent extends Content {
private static final int MIN_CONTENT_LENGTH = 5;
private static final int MAX_CONTENT_LENGTH = 500;
// 부모 객체 생성자 호출
public PostContent(String contentText) {
super(contentText);
}
// 추상 메서드 구현
@Override
protected void checkText(String contentText) {
if (contentText == null || contentText.isEmpty()) {
throw new IllegalArgumentException();
}
if (contentText.length() < MIN_CONTENT_LENGTH) {
throw new IllegalArgumentException();
}
if (contentText.length() > MAX_CONTENT_LENGTH) {
throw new IllegalArgumentException();
}
}
}
// CommentContent.java 수정
public class CommentContent {
private static final int MAX_CONTENT_LENGTH = 100;
// 부모 객체 생성자 호출
public CommentContent(String contentText) {
super(contentText);
}
// 추상 메서드 구현
@Override
protected void checkText(String contentText) {
if (contentText == null || contentText.isEmpty()) {
throw new IllegalArgumentException();
}
if (contentText > MAX_CONTENT_LENGTH) {
throw new IllegalArgumentException();
}
}
}
// org.communityfeed.post.domain
// Post.java
public class Post {
...
private final PostContent content;
...
public Post(..., PostContent content) {
...
this.content = content;
...
}
}
// org.communityfeed.post.domain.comment
// Comment.java
public class Comment {
...
private final CommentContent content;
...
pulic Comment(..., CommentContent content) {
...
this.content = content;
...
}
}
- Content
- 역할:
- 게시글, 댓글의 내용과 관련된 공통 로직을 제공하는 추상 클래스
- 책임:
- 유효성을 검증하는 추상 메서드 정의
- contentText 제공
- 자식 객체에서 유효성 검증 로직을 구현하도록 강제
- 역할:
- PostContent
- 역할:
- 게시글의 내용을 관리, 유효성 검증
- 책임:
- 추상 메서드를 구현하여 게시글 내용의 길이 유효성 체크
- 부모 객체(추상화 클래스)를 호출하여 contentText 초기화
- 역할:
- CommentContent
- 역할:
- 댓글의 내용을 관리, 유효성 검증
- 책임:
- 추상 메서드를 구현하여 댓글 내용의 길이 유효성 체크
- 부모 객체(추상화 클래스)를 호출하여 contentText 초기화
- 역할:
- Post
- 역할:
- 게시글과 관련된 정보를 관리
- 책임:
- 게시글의 내용, 상태, 작성자 등을 관리
- PostContent 객체를 이용하여 내용을 위임받아 처리
- 역할:
- Comment
- 역할:
- 댓글과 관련된 정보를 관리
- 책임:
- 댓글의 내용, 상태, 작성자 등을 관리
- CommentContent 객체를 이용하여 내용을 위임받아 처리
- 역할:
4. 게시물 상호작용:
- 사용자는 '좋아요' 버튼을 눌러 게시물을 좋아할 수 있습니다.
- 본인 게시글은 본인이 좋아요를 누를 수 없습니다.
- 사용자는 댓글 섹션에 메시지를 입력하여 게시물에 댓글을 달 수 있습니다.
- 좋아요 개수를 누르면 좋아요를 누른 인원들을 볼 수 있음
- 댓글 개수를 누르면 댓글 리스트가 보일 수 있음
- 글 수정 버튼을 누르면 글을 수정할 수 있음
- 본인이 작성한 글이 아니면 수정 할 수 없음
- 수정이 된 여부와 수정된 시간을 같이 저장해야 함
- 댓글 수정 버튼을 누르면 댓글을 수정 할 수 있음
- 본인이 작성한 댓글이 아니면 수정 할 수 없음
- 수정이 된 여부와 수정된 시간을 같이 저장해야 함
4-1) 좋아요 기능
좋아요를 누르는 기능과 팔로우하는 기능이 동일하므로 공통클래스를 생성하여 처리
// org.communityfeed.user.domain
// UserFollow.java 삭제
// org.communityfeed.common
// PositiveLikeCount.java
public class PositiveLikeCount {
private int count;
public PositiveLikeCount() {
this.count = 0;
}
public void increase() {
count++;
}
public void decrease() {
if (count <= 0) {
return;
}
count--;
}
}
// org.communityfeed.user.domain
// User.java 수정
public class User {
...
private final PositiveLikeCount following;
private final PositiveLikeCount follower;
public User(...) {
...
this.following = new PositiveLikeCount();
this.follower = new PositiveLikeCount();
}
...
public void follow(User targetUser) {
...
targetUser.increaseFollowerCounter();
}
public void unfollow(User targetUser) {
...
targetUser.decreaseFollowerCounter();
}
// 다른 상태의 User 객체에 스스로 처리하게 하기위해 캡슐화
private void increaseFollowerCountter() {
follower.increase();
}
private void decreaseFollowerCounter() {
follower.decrease();
}
...
}
// org.communityfeed.post.domain
// Post.java 수정
public class Post {
...
private final PositiveLikeCount likeCount;
...
public Post(...) {
...
this.likeCount = new PositiveLikeCount();
...
}
public void like(User targetUser) {
// 본인 확인
if (author.equals(targetUser)) {
throw new IllegalArgumentException();
}
likeCount.increase();
}
public void unlike() {
likeCount.decrease();
}
}
// org.communityfeed.post.domain.comment
// Comment.java 수정
public class Comment {
...
private final PositiveLikeCount likeCount;
public Comment(...) {
...
this.likeCount = new PositiveLikeCount();
}
public void like(User targetUser) {
// 본인 확인
if (author.equals(targetUser)) {
throw new IllegalArgumentException();
}
likeCount.increase();
}
public void unlike() {
likeCount.decrease();
}
}
4-2) 게시글, 댓글 내용 수정 기능
수정 기능이 동일하므로 공통 클래스로 처리
// org.communityfeed.post.domain.common
// DatetimeInfo.java
public class DatetimeInfo {
private LocalDateTime datetime;
private boolean isEdited;
public DatetimeInfo() {
this.datetime = LocalDateTime.now();
this.isEdited = false;
}
public updateEditDatetime() {
this.datetime = LocalDateTime.now();
this.isEdited = true;
}
public LocalDateTime getDatetime() { return datetime; }
public boolean isEdited() { return isEdited; }
}
// org.communityfeed.post.domain.content
// Content.java 수정
public abstract class Content {
...
final DatetimeInfo datetimeInfo;
protected Content(...) {
...
this.datetimeInfo = new DatetimeInfo();
}
public void updateContent(String updateContentText) {
checkText(updateContentText);
this.contentText = updateContentText;
this.datetimeInfo = updateEditDatetime();
}
...
}
// org.communityfeed.post.domain
// Post.java 수정
public class Post {
...
public void updatePost(User targetUser, String updateContent, PostStatus status) {
if (!author.equals(targetUser)) {
throw new IllegalArgumentException();
}
this.content.updateContent(updateContent);
this.status = status;
}
}
// org.communityfeed.post.domain.comment
// Comment.java 수정
public class Comment {
...
public void updateComment(User targetUser, String updateContent) {
if (!author.equals(targetUser)) {
throw new IllegalArgumentException();
}
this.content.updateContent(updateContent);
}
}
- PositiveLikeCount (공통 클래스)
- 역할:
- 좋아요/팔로우 등 숫자 카운트를 담당하는 클래스.
- 카운트 값의 증가/감소를 추적하고, 음수로 감소하는 것을 방지.
- 책임:
- 카운트 값을 관리 (increase(), decrease()).
- 공통적으로 사용 가능한 유틸리티 클래스로 설계되어, User, Post, Comment 등에서 재사용.
- 역할:
- User
- 역할:
- 사용자 정보를 관리하고, 다른 사용자와의 팔로우 관계를 처리.
- 책임:
- 본인의 팔로잉/팔로워 수 관리 (following, follower).
- 다른 사용자를 팔로우하거나 언팔로우 (follow(), unfollow()).
- 팔로워 수를 다른 객체에서 직접 변경하지 못하도록 캡슐화 (increaseFollowerCounter(), decreaseFollowerCounter()).
- 역할:
- Post
- 역할:
- 게시글 작성자(author), 내용(content), 상태(status) 등을 관리.
- 게시글의 좋아요와 수정 작업을 처리.
- 책임:
- 게시글 좋아요 수 관리 (likeCount).
- 게시글 내용을 수정 (updatePost()).
- 본인이 아닌 사용자가 좋아요/수정하려고 하면 예외를 발생시켜 데이터 무결성 유지.
- 역할:
- Comment
- 역할:
- 게시글에 대한 댓글 정보를 관리.
- 책임:
- 댓글 좋아요 수 관리 (likeCount).
- 댓글 내용을 수정 (updateComment()).
- 본인이 작성한 댓글만 수정할 수 있도록 제한.
- 역할:
- DatetimeInfo
- 역할:
- 작성 또는 수정된 날짜/시간 정보를 관리.
- 책임:
- 생성 시점의 시간 기록.
- 내용 수정 시 수정된 시간 업데이트 (updateEditDatetime()).
- 역할:
출처: https://fastcampus-community-feed.notion.site/883fa62553224723a74fa97654bc41e8
'개발 공부' 카테고리의 다른 글
JPA 기본 개념과 영속성 컨텍스트 (0) | 2025.02.25 |
---|---|
Spring과 객체 지향 (0) | 2025.02.25 |
커뮤니티 피드(3) - 테스트 작성 (1) | 2025.02.13 |
커뮤니티 피드(1) - User 도메인 개발 (1) | 2025.02.12 |
수강생 관리 프로그램 (1) | 2025.02.11 |