티스토리 뷰

정리

Dto vs VO vs Entity

du0422 2020. 9. 27. 22:02

DTO (Data Transfer Object)

 

- 데이터 전송을 위해 만들어진 클래스(객체라고 보기에는 내가 생각하는 객체와는 거리가 멀어 클래스로 표현했다.)

- getter / setter 메서드를 가지고 있고 Business 로직을 가지지 않음

- 모든 계층에서 사용하는 분들이 있지만, 필자는 Contoller와 Service 간의 전송에서만 사용

     - Dto는 변경될 가능성이 큼

     - Domain Layer까지 내려가면 Domain과 높은 의존도를 가지게 되므로 Dto 변경 시 Domain도 변할 가능성이 크기 때문

- Setter 메서드도 필요 없다면, 작성하지 않는다.

 

public class MemberDto {
    private String email;
    private String password;
    private String name;
    
    // getter, setter
}

 

VO (Value Object)

 

- 데이터 값이 같으면 같은 객체(eqauls 비교)이다.

    - equals & hash code를 재정의 해야 한다.

- 데이터를 가지고 있고 불변이다.

- Business 로직을 가질 수 있다.

- 불변이므로 thread-safe 하고, side-effect가 없다. 어느 곳에서 사용 가능하다.

 

import java.math.BigDecimal;
import java.util.Objects;

public class Money {
    private BigDecimal amount;

    public Money(BigDecimal amount) {
        this.amount = amount;
    }

    public Money add(BigDecimal amount) {
        return new Money(this.amount.add(amount));
    }

    public Money minus(BigDecimal amount) {
        return new Money(this.amount.subtract(amount));
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Money money = (Money) o;
        return Objects.equals(amount, money.amount);
    }

    @Override
    public int hashCode() {
        return Objects.hash(amount);
    }
}

 

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.math.BigDecimal;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class MoneyTest {

    @Test
    @DisplayName("동등성 확인")
    public void checkEquals() {
        Money one1 = new Money(new BigDecimal(1));
        Money one2 = new Money(new BigDecimal(1));

        assertEquals(one1, one2);
}

 

Entity

 

- 특정 값으로 객체를 구분할 수 있다. ex) id, name 등

- 객체를 테이블과 매핑할 때 주로 사용

- Business 로직을 가질 수 있다.

 

import lombok.*;

import javax.persistence.*;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@EqualsAndHashCode(of = "id")
@ToString
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 20, nullable = false)
    private String name;

    @Column(length = 20, nullable = false, unique = true)
    private String email;

    @Column(length = 20, nullable = false)
    private String password;

    @Builder
    public User(String name, String email, String password) {
        this.name = name;
        this.email = email;
        this.password = password;
    }
}

 

- 아래와 같이 name이 동일할 경우 같은 객체라고 생각한다.

      - mir라는 자동차가 0칸에 있을 때랑, 1칸 전진했을 때와 상관없이 이름이 같다면 같은 객체이다.

 

import java.util.Objects;

public class Car {
    private final String name;
    private int position;

    public Car(String name) {
        this.name = name;
    }

    public void move(int number) {
        if (number >= 4) {
            position++;
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Car car = (Car) o;
        return Objects.equals(name, car.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

 

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import per.ddu.fitness.user.Car;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class CarTest {

    @Test
    @DisplayName("이름이 동일하면 같은 객체")
    public void checkEquals() {
        Car car1 = new Car("mir");
        Car car2 = new Car("mir");

        car1.move(10);
        
        // car1 => name: mir, positoin: 1
        // car2 => name: mir, position: 0

        assertEquals(car1, car2);
    }
}

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함