요구사항
- 게시글들은 모두 어떤 게시판에 속해 있어야한다.
- 게시글에는 카테고리가 반드시 필요하다.
- 각 게시판 별로 '게시글 카테고리'를 여러 개 생성할 수 있다.
- 게시판 별로 가질 수 있는 게시글 카테고리 갯수 제약이 추가될 가능성이 있긴한데 서비스 구현의 간단화를 위해 일단 당장 고려하지 않는다.
데이터베이스 테이블 설계
CREATE TABLE IF NOT EXISTS article_categories(
article_category_id BIGINT NOT NULL PRIMARY KEY,
name VARCHAR(20) NOT NULL,
slug VARCHAR(8) NOT NULL,
board_id BIGINT NOT NULL,
allow_write BOOLEAN NOT NULL,
allow_self_edit_delete BOOLEAN NOT NULL,
allow_comment BOOLEAN NOT NULL,
allow_like BOOLEAN NOT NULL,
allow_dislike BOOLEAN NOT NULL,
created_at DATETIME NOT NULL,
CONSTRAINT uq_board_id_and_name UNIQUE (board_id, name),
CONSTRAINT uq_board_id_and_slug UNIQUE (board_id, slug)
);
- article_category_id : 식별자
- name : 이름
- slug : 구분 영문자(게시판 내에서 카테고리 구분)
- 예) general ->
https://board-system.com/b/animal?category=general
- board_id : 소속 게시판
- allow_write : 일반 사용자가 게시글을 작성할 수 있는 지 여부
- allow_self_edit_delete : 일반 사용자가 자신의 게시글을 수정/삭제할 수 있는 지 여부
- 대표적인 활용례: 질문글을 올려놓고, 사용자들의 답을 받은 뒤 질문글을 삭제하는 악성 유저들을 방지하기 위한 정책
- allow_comment : 일반 사용자의 댓글 허용 여부
- allow_like : 일반 사용자의 좋아요 가능 여부
- allow_dislike : 일반 사용자의 싫어요 가능 여부
- created_at 생성일
- 유니크 제약조건
- (board_id, name) : 게시판별로 게시글 카테고리 이름은 내부적으로 중복 허용 x
- (board_id, slug) : 게시판별로 게시글 카테고리 슬러그는 내부적으로 중복 허용 x
도메인 엔티티
class ArticleCategory(
val articleCategoryId: Long,
val boardId: Long,
name: String,
val slug: String,
allowWrite: Boolean,
allowSelfEditDelete: Boolean,
allowComment: Boolean,
allowLike: Boolean,
allowDislike: Boolean,
val createdAt: AppDateTime
) {
var name: String = name
private set
var allowWrite: Boolean = allowWrite
private set
var allowSelfEditDelete: Boolean = allowSelfEditDelete
private set
var allowComment: Boolean = allowComment
private set
var allowLike: Boolean = allowLike
private set
var allowDislike: Boolean = allowDislike
private set
companion object {
fun create(
articleCategoryId: Long,
boardId: Long,
name: String,
slug: String,
allowWrite: Boolean,
allowSelfEditDelete: Boolean,
allowComment: Boolean,
allowLike: Boolean,
allowDislike: Boolean,
createdAt: AppDateTime
): ArticleCategory {
return ArticleCategory(
articleCategoryId = articleCategoryId,
boardId = boardId,
name = name,
slug = slug,
allowWrite = allowWrite,
allowSelfEditDelete = allowSelfEditDelete,
allowComment = allowComment,
allowLike = allowLike,
allowDislike = allowDislike,
createdAt = createdAt
)
}
fun restore(
articleCategoryId: Long,
boardId: Long,
name: String,
slug: String,
allowWrite: Boolean,
allowSelfEditDelete: Boolean,
allowComment: Boolean,
allowLike: Boolean,
allowDislike: Boolean,
createdAt: LocalDateTime
): ArticleCategory {
return ArticleCategory(
articleCategoryId = articleCategoryId,
boardId = boardId,
name = name,
slug = slug,
allowWrite = allowWrite,
allowSelfEditDelete = allowSelfEditDelete,
allowComment = allowComment,
allowLike = allowLike,
allowDislike = allowDislike,
createdAt = AppDateTime.from(createdAt)
)
}
}
override fun toString(): String {
return "ArticleCategory(articleCategoryId=$articleCategoryId, name='$name', slug='$slug', boardId=$boardId, allowWrite=$allowWrite, allowSelfEditDelete=$allowSelfEditDelete, allowComment=$allowComment, allowLike=$allowLike, allowDislike=$allowDislike, createdAt=$createdAt)"
}
}