도메인 중심 설계와 서비스 계층 경량화

도메인 중심 설계와 서비스 계층

객체지향에서 클래스는 객체의 상태와 행동을 둘 다 정의한다.(필드, 메서드) 그런데, MVC 패턴을 적용하다보니 상태를 변경하는 행동 조차 서비스 계층에 넣고 있었다.

예를 들면, Book 클래스의 대출 여부와 대출한 사람에 대한 정보는 이미 필드에 정의되어 있는데, 서비스 계층에서 rent, unRent 메서드를 넣어서 사용했다. 이렇게 하면, 서비스 계층이 너무 비대해진다. 때문에, 이런 객체의 상태를 변경하는 내용은 도메인 모델에 상태 변경 메서드를 넣기로 했다.

기존 서비스 계층

public class BookService {
    ...

    public boolean rent(Book book, User, rentedBy) {
        ...
    }    

    public boolean unRent(Book book, User, rentedBy) {
        ...
    }

    ...
}

개선

User, Book 도메인에 각각 rent, unRent 메서드를 만들어서 User와 Book 클래스가 서로 의존하도록 했다.

public class Book {

    ...

    private boolean isRental;
    private User rentedBy;


    /**
     * 도서 대출 메서드
     * 현재 도서가 대출 중이 아니면, 대출한다.
     *
     * @param rentedBy : 대출할 유저
     * @return : 성공 여부
     */
    public boolean rent(User rentedBy) {
        if (!isRental) {
            this.rentedBy = rentedBy;
            isRental = true;
            return true;
        }

        return false;
    }

    /**
     * 도서 반납 메서드
     * 현재 도서가 대출중이라면, 대출한 유저가 요청한 유저가 맞는지 확인하고, 반납한다.
     *
     * @param rentedBy : 대출했던 유저
     * @return : 성공 여부
     */
    public boolean unRent(User rentedBy) {
        if (isRental) {
            if (this.rentedBy == rentedBy) {
                isRental = false;
                this.rentedBy = null;
                return true;
            }
        }

        return false;
    }

    ...

}

public class User {

    ...

    private int remainingRents = 3; // 남은 대출 가능 권수

    /**
     * 책 대출 메서드, 남은 권수가 0권 이상이면, book.rent 메서드 호출해서 결과 리턴
     * @param book : 빌릴 책
     * @return 성공 여부
     */
    public boolean rent(Book book) {
        if (remainingRents > 0) {
            remainingRents--;

            return book.rent(this);
        }

        return false;
    }

    /**
     * 책 반납 메서드, book.unRent 메서드 호출해서 성공하면, 대출 가능 권수 늘리고 성공 리턴
     * @param book : 반납할 책
     * @return : 성공 여부
     */
    public boolean unRent(Book book) {
        if (book.unRent(this)) {
            remainingRents++;
            return true;
        }
        return false;
    }
}

이로써 객체 자체의 상태를 변경하는 메서드는 도메인 모델 자체에 두고, 서비스 계층에서는 Repository를 호출하는 등 좀 더 큰 작업을 수행하고 경량화 할 수 있다.

같은 느낌으로 책 자체를 수정하는 modify 메서드도 서비스 계층에서 Book 도메인 모델로 넣었다.

댓글

개발자  김철준

백엔드 개발자 김철준의 블로그입니다.

주요 프로젝트