<aside>

Entity를 바라봅시다.

우리는 Entity = 테이블 처럼 받아들이는 경우가 많아요.

Entity 는 테이블 매핑의 역할만 수행하는걸까요 ? 아니면 도메인의 중심, 즉 비즈니스 규칙을 알고 있는 살아있는 객체일까요.

한번 고민해봅시다.

</aside>

DB 테이블과 동일시할 것이 아니라 살아있는 객체로 비즈니스 규칙을 집어 넣어 줘야 한다.

Domain 영역에서는 기술적인 유효성 검사(DB에 접근해야 하는 영역)을 진행해야 한다고 판단했다. 예를 들어 전달받은 postId가 우리가 갖고 있는 postId인지와 같은..

Entity는 “유효한 상태” 로만 존재해야 한다.

= 생성된 시점부터 잘못된 객체는 존재해서는 안된다.

앞서 Service, DTO에서 생각한 data type이 맞는지와 비즈니스 규칙에 맞추어진 데이터인지 유효성 검증을 끝마쳤다.

여기서 테이블에 들어갈 수 없는 친구들을 확실히 솎아내 줘야한다.

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String email;
    private Integer age;

    @OneToMany(mappedBy = "user")
    private List<Post> posts = new ArrayList<>();

    protected User() {
    }

    public User(String name, String email, Integer age) {
        this.name = name;
        this.email = email;
        this.age = age;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

->

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;
    @Column(nullable = true)
    private String email;
    @Column(nullable = true)
    private Integer age;

    @OneToMany(mappedBy = "user")
    private final List<Post> posts = new ArrayList<>();

    protected User() {
    }

    public User(String name, String email, Integer age) {
        this.name = name;
        this.email = email;
        this.age = age;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

@Entity
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String content;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;

    protected Post() {
    }

    public Post (String title, String content, User user) {
        this.title = title;
        this.content = content;
        this.user = user;
    }

    public Long getId() {
        return this.id;
    }

    public String getTitle() {
        return this.title;
    }

    public String getContent() {
        return content;
    }

    public User getUser() {
        return user;
    }

    public void renameTitle(String newTitle) {
        this.title = newTitle;
    }

    public void validateIdIsSame(Long requestUserId) {
        if (!user.getId().equals(requestUserId)) {
            throw new CustomException(ErrorMessage.UNAUTHORIZED_ERROR);
        }
    }
}

->

@Entity
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String title;
    @Column(nullable = false)
    private String content;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false)
    private User user;

    protected Post() {
    }

    public Post (String title, String content, User user) {
        this.title = title;
        this.content = content;
        this.user = user;
    }
    
    public String getTitle() {
        return this.title;
    }

    public String getContent() {
        return content;
    }

    public User getUser() {
        return user;
    }

    public void renameTitle(String newTitle) {
        this.title = newTitle;
    }

    public void validateIdIsSame(Long requestUserId) {
        if (!user.getId().equals(requestUserId)) {
            throw new CustomException(ErrorMessage.UNAUTHORIZED_ERROR);
        }
    }
}

위와 같이 Post, User Entity를 수정했는데 고민이 생겼다.

내가 처음에 생각했던 유효성 검증 위치가 맞는 걸까?

유효성 검증부가 Domain, Service, DTO에 산재되어 있는데 이게 과연 SRP를 잘 지키고 있는 건지 모르겠다.