๋ชฉ์ฐจ
- ์๋ก
- entity ๋ ๋ฌด์์ธ๊ฐ
- ๋๋ฉ์ธ ์ธ์ ์ด์ผ๊ธฐ
- vo ์ entity ๊ฐ ์๋ค
- ๋ฌด์์ด entity ๋ฅผ ๊ฒฐ์ ํ๋๊ฐ?
- entity ์ ์์ฑ
- invariant
- immutable
- entity ์ ํ์
- object autonomy
- self encapsulation
์๋ก
DDD ์์๋ ์ ๋น์ฟผํฐ์ค ๋ญ๊ท์ง๋ฅผ ํตํ์ฌ ์ฌ๋ฌ ์ดํด๊ด๊ณ์๋ค๊ณผ ๋น์ฆ๋์ค ์์ญ์ ๋ํด ํฉ์ (Cosensus) ๋ฅผ ๋ง์ถ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฌผ๋ก ๋๋ฉ์ธ์ ๋ํ ๋ชจ๋ธ๋ง ์ฆ, domain model
์ด ์ฐ์ถ๋๋ค.
์ด domain model
์ ์ฌ๋ฌ ์ํธ์์ฉ์ ํตํด ๋น์ฆ๋์ค๋ฅผ ์งํฑํ๊ฒ ๋๋๋ฐ, domain model ์ ๊ฐ์ฅ ๊ธฐ์ด๊ฐ ๋๋ ๋๊ฐ์ง ํ์
์ ๊ฐ์ฒด๊ฐ ์กด์ฌํ๋ค.
- Entity
- Value Object
์ค๋์ ์ด Entity ์ ๋ํด์ ์์๋ณด๋๋ก ํ์
Entity ๋ ๋ฌด์์ธ๊ฐ?
์ํฐํฐ entity, spring ์ ์ด์ฉํ๋ ๊ฐ๋ฐ์๋ entity ์ ๋ํด์ ์ตํ ๋ค์ด์๊ณ ์ฌ์ฉํด ์์ ๊ฒ์ด๋ค.
๋ฐ๋ก Spring Data JPA ์์ ์ฌ์ฉ๋๋ ๊ฐ๋
ํน์ ์ด๋
ธํ
์ด์
์ผ๋ก, Database Table ์ ๋์๋๋ ORM ์ ํต์ฌ์ด ๋๋ ๊ฐ์ฒด๋ฅผ ๋ฐ๋ก Entity ๋ผ๊ณ ํํํ๊ณ ์ฝ๋๋ ๋ฒจ์์ ์ด๋ฅผ @Entity
์ด๋
ธํ
์ด์
์ผ๋ก ์ง์ ํ๋ค.
DDD ์์ ๋งํ๋ Entity ์ JPA ์์ ์ด์ผ๊ธฐํ๋ Entity ๊ฐ ํฌ๊ฒ ๋ค๋ฅผ๋ฐ๋ ์์ง๋ง, ์์ฆ ์น ๊ฐ๋ฐ์ ํ๋ฆ์์ ๋ณด๋ฉด ๋ค๋ฅด๋ค๋ ๊ฒ์ ๋๋ผ๊ณ ์๋ค.
๊ทธ๋ผ entity ๋ ๋ฌด์์ธ๊ฐ?
Entity ์์ฒด์ ๊ฐ๋ ์ ์์์ฑ ์ฅ์น์ ๋ฌด๊ดํ๊ณ DB field ๋ฅผ mapping ํ๋ java ๊ฐ์ฒด๊ฐ ์๋๋ค.
์ฐ๋ฆฌ๊ฐ ํต์ฌ ๋๋ฉ์ธ ๊ฐ์ฒด๋ผ ๋ถ๋ฅด๋ ๊ฒ๋ค์ ๋๋ถ๋ถ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ํ๋ฅผ ํ๋๋ฐ, ์ด์ ๊ฐ ๋ฌด์์ธ์ง ์ดํด๋ณผ ํ์๊ฐ ์๋ค.
์ ์ฐ๋ฆฌ๋ ์์ํ๋ฅผ ํ๋ ๊ฒ์ผ๊น?
์์ํ์ ๋ณธ์ง์ ๋ฐ๋ก ์ฐ์์ฑ์ด๋ค.
์ด๋ค ๊ฐ์ฒด๊ฐ ๊ฐ์ ธ์ผ ํ๋ ์ฑ ์์ ์ฐ์์ ์ผ๋ก ์ถ์ ํ๊ณ ๊ด์ฐฐํ๊ณ ์ถ์ ๊ฒ์ด๋ค.
์ด๋ ์๊ฐ์๋ ๊ทธ ํต์ฌ ๊ฐ์ฒด์๊ฒ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ผ๋ ๋ช ๋ น(command) ๋ฅผ ํ ๊ฒ์ด๊ณ , ๊ทธ ํ์๋ ๊ฐ๋ฅํ ์์ํ ์ฐ์์ ์ด์ด์ผ ํ๋ค.
๊ฐ๋ฅํ ์ฐ์์ ์ด๊ธฐ ์ํด์๋ ์๋ง์ ๊ฐ์ฒด๋ค์ ๊ฐ๊ฐ ์๋ณํ ์ ์์ด์ผ ํ๋ค.
๊ทธ๋ ์ฐ๋ฆฌ๋ ๊ทธ ํต์ฌ ๊ฐ์ฒด์๊ฒ ์๋ณ์ ๋ผ๋ ๊ฒ์ ํ ๋นํ๊ฒ ๋๊ณ , ์ด๊ฒ์ ๋ฐ๋ก Entity ๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์ด๋ฌํ entity ๋ค์ ์์ํ ์คํ๋ ์ ์๋ ํ์ค์ computing engine ์์ ์์ ํ๊ฒ ์ ์ง์ํค๊ธฐ ์ํด์ ์ฐ๋ฆฌ๋ database ๋ก ์์ํ๋ผ๋ ๊ณผ์ ์ ํ๋ ๊ฒ์ด๋ค.
์ฆ, entity ๋, ๋๋ฉ์ธ ๊ฐ์ฒด๊ฐ ์ฐ์์ฑ์ ๊ฐ์ง๊ธฐ ์ํด์ ์๋ณ์๋ฅผ ๋ถ์ฌ๋ฐ์, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ํ๊ฐ ๋๋ ๊ฒ์ด๋ค.
๋ค์ ๋งํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ฐ์ ๊บผ๋ด์ค๊ธฐ ์ํ ์๋ณ์๊ฐ ์๊ธฐ์ entity ๊ฐ ์กด์ฌํ๋ ๊ฒ์ด ์๋๋ผ๋ ๊ฒ์ด๋ค
Entity ์ ์๋ณ์์ ๋ํด์๋ ํ ์ด์ผ๊ธฐ๊ฐ ๋ง๊ธฐ ๋๋ฌธ์, Entity ์ Identifier(์๋ณ์) ์ ๋ํ ์ด์ผ๊ธฐ ์์ ๋ฐ๋ก ์ด์ผ๊ธฐํ๋๋ก ํ๊ฒ ๋ค.
์ ๋ฆฌ
- Domain Model ์ ํฌ๊ฒ 2๊ฐ์ง ๊ฐ์ฒด๋ก ๋๋จ
- Entity
- Value Object
- Entity ์ Value Object ๋ฅผ ๊ตฌ๋ถ์ง๋ ๊ฒ์ ์๋ณ์ฑ์
- Entity: ๋๋ฉ์ธ ๋ชจ๋ธ ๋ด์์ ์๋ณ์ด ๋์ด์ผ ํ๋ ๊ฐ์ฒด
- Value Object: ๋๋ฉ์ธ ๋ชจ๋ธ ๋ด์์ ์๋ณ์ด ๋์ง ์์๋ ๋๋ ๋จ์ํ ๊ฐ ๊ฐ์ฒด
- Entity ์ ํต์ฌ์ DB Table ์ Relation Mapping Object ๊ฐ ์๋
๋ด๊ฐ ๋ง๋ Entity ๋ DTO ๊ทธ ์์ฒด
๋ด๊ฐ ์งํํ๋ ๋ง์ ์์ ํ๋ก์ ํธ๋ค์ ์์ค์ฝ๋๋ฅผ ๋ค์ ๋ณด๋ฉด Entity ๊ฐ์ฒด๋ Database ์ Field ์ 1:1 ๋์๋๋ ๋จ์ DTO ๊ทธ ์ด์๋, ์ดํ๋ ์๋์๋ค.
@Entity
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "Username ์ด ํ์ํจ")
@Size(min = 3, max = 20, message = "3 ์ด์ 20 ์ดํ")
private String username;
@NotBlank(message = "Email ์ด ํ์ํจ")
@Email(message = "email ํ์์ด ์๋")
private String email;
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime modifiedAt;
// ํ์ ๋ฉ์๋
}
DTO ๋ ํ์๊ฐ ์กด์ฌํ์ง ์๋ ๋ฉ์๋๋ค, ๋ญ DTO ๋ setter ๊ฐ ์์ด์ผ ํ๋ค, ์ด๋ฐ ์ฌ๋ฌ ์ด์ผ๊ธฐ๋ฅผ ๋ค์์ง๋ง, ํ์๊ฐ ์กด์ฌํ๋ setter ๊ฐ ์กด์ฌํ๋ ์ค์ํ๊ฒ ์๋๋ค.
๊ฐ์ฒด๋ค ์ฌ์ด์์ ์ถฉ๋ถํ ์์จ์ฑ๊ณผ ์ฑ ์์ ๊ฐ์ง ๋ชปํ ๊ฐ์ฒด๋ ๋๋ ๋ชจ๋ Value ํน์ DTO ๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์ด DTO ๋ฅผ Database ์ ํต์ ํ๊ธฐ ์ํ ์ฉ๋๋ก๋ง ์ฌ์ฉํ๊ณ ์ค์ ํ์๋ ๋ชจ๋ Service ๋ผ๊ณ ๋ถ๋ฅด๋ ์ด์ํ ๊ฐ์ฒด์์ transactional script ๋ก ๊ตฌํํ๊ณ ์์๋ค.
ํ๋ก์ ํธ๋ฅผ ์์ํ๋ฉด ๋จผ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ค๊ณํ๊ณ Entity ๊ฐ์ฒด ๋ง๋๋๋ผ ๋ง์ ์๊ฐ์ ํ๋นํ์๋๋ฐ, ์ด๋ฐ ํ์์ ์๊ฐ ์์ฒด๊ฐ ๊ธธ์ด์ง ์๋ก anemic ํ ๋ชจ๋ธ์ด ๋์ค๊ฒ ๋๋ ๊ฒ์ด๋ค.
Entity ๋ฅผ ์ค๊ณํ๋ ์์ ์๋ Database ์ ์ ํ ๋ฌด๊ดํ๋ค.
Entity ์ ํ์์ ์์ฑ์ ํ์ ํ๊ธฐ ์ํด์๋ ์ฌ๋ฌ ์ดํด๊ด๊ณ์๋ค๊ณผ์ ํ์์ Event Storming ์ ๋น๋กฏํ ๋๋ฉ์ธ ํ๊ตฌ ๊ณผ์ ์ ๊ฑฐ์ณ ํ์ํ๋ Ubiqutious Language ๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋ฐ๋์ด์ผ ํ๋ค.
์ด๋ฌํ UL ์ ๋ง๋ค๊ณ , ๊ทธ ์ธ์ด๋ค ์์ฒด๋ฅผ ์์ค์ฝ๋์ ๋ น์ด๋ ๊ฒ์ด๋ค.
๊ทธ๋ผ ์์ฐ์ค๋ฝ๊ฒ ๋๋ฉ์ธ ๊ฐ์ฒด์ ํ์๊ฐ ๋ ์ค๋ฅผ ๊ฒ์ด๊ณ , ์ ์ ํ ๊ฐ์ฒด์ field ๊ฐ ๋ ์ค๋ฅด๊ฒ ๋๋ค.
Entity ์ ์์ฑ, entity field
๋๋ฉ์ธ ๋ ์ด์ด์ ์์นํ๋, ๋๋ฉ์ธ ๋ชจ๋ธ์ ์กด์ฌํ๋ Entity ๋ Value Object ๋ ์์จ์ฑ์ ๊ฐ์ง๊ณ ์ฑ ์์ ๊ฐ์ ธ์ผ ํ๋ค.
์ด๋ฌํ Field ์ ํน์ฑ์ ํ ๋ฒ ์ดํด๋ณด์.
field ํน์ฑ 1. Invariant
๋๋ฉ์ธ์ ๋ชจ๋ธ๋งํ๋ฉด ์ํฐํฐ์ ์ด๋ค ์์ฑ๋ค์ invariant ํ ํน์ฑ์ ๊ฐ์ง๊ณ ์๋ค.
์๋ฅผ ๋ค๋ฉด, ๋๋ฉ์ธ ๊ท์น์ค ๋ค์๊ณผ ๊ฐ์ ์ํฉ์ด ์๋ค๊ณ ๊ฐ์ ํ์
- ์ ์ ๋ ๋ก๊ทธ์ธ์ ์ํด์ ๋ํ ์ด๋ฉ์ผ์ ์ค์ ํ ์ ์์ด
- ์ด ๋ํ ์ด๋ฉ์ผ์ ํ๋ฒ ์ค์ ๋๋ฉด ๋ณ๊ฒฝ๋ ์ ์์ด
- ์ ์ ์ ์ด๋ฆ์ ์ธ์ ๋ ์ง ๋ณ๊ฒฝ๋ ์ ์์ด
์ฌ๊ธฐ์ ๋ํ ์ด๋ฉ์ผ์ ๋ณ๊ฒฝ๋ ์ ์๊ธฐ ๋๋ฌธ์ Invariant ์ด๋ค. ํ ๋ฒ ๊ฐ์ฒด๊ฐ ์์ฑ๋ ์์ ์์ ์ ๋ ๋ณ๊ฒฝ๋์ด์๋ ์๋๋ ์ค์ํ ๋น์ฆ๋์ค ๊ท์น์ธ ๊ฒ์ด๋ค.
๋ณดํต ์ด๋ฐ ๋ถ๋ณ์์ด ํ์ํ ๊ฐ์ฒด๋ ๋ณ๊ฒฝํ์ง ์๋ ์์๋ก ์ทจ๊ธํด์ผํ๋ค.
java ์์๋ final ํค์๋๋ฅผ ํตํด์ ํน์ ํ๋ ๋ฐ์ดํฐ๋ฅผ ์์๋ก ๋ง๋ค ์ ์๋ค.
final field ๋ฅผ ์ถ๊ฐํ๋ค๋ฉด ์์ฑ๋จ๊ณ๋ถํฐ ๊ฐ์ ํ ๋นํ์ง ์์ผ๋ฉด ์ปดํ์ผ ํ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์, ํด๋นํ๋ ๊ฐ์ฒด๊ฐ ์์ฑ๋์๋ค๋ ๋ป์, ๊ฐ์ด ์กด์ฌํ๋ค๋ ๋ป์ผ๋ก ํด์ํ ์ ์๋ค
public class User {
private final UserId id; // ์๋ณ์ ์์ ์ฑ
private final Email email; // ์์ ์ทจ๊ธ
private UserName username; // immutable ํ reassign
}
์๋ณ์๋ ๋ถ๋ณ์์ด๋ค.
์๋ณ์ ์์ ์ฑ
์ด๋ ์๋ณ์ ์์ ์ฑ์ด๋ผ๊ณ ๋ถ๋ฅด๋๋ฐ, ํ ๋ฒ ๊ฐ์ฒด๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ธ์คํด์คํ๊ฐ ๋์๋ค๋ฉด ๊ทธ ๊ฐ์ฒด๋ ๊ณผ๊ฑฐ๋ถํฐ ๋ฐ์ํ๋ ๋ชจ๋ ์ฌ๊ฑด์ ์ฐ์์ฑ์ ๋ํ ์ด ํฉ์ด๋ฉฐ ํ์ฌ ์ํ๋ฅผ ํํํ๋ค
ํ์ง๋ง ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ธ์คํด์คํ๊ฐ ๋ ์ํฐํฐ์ ์๋ณ์๊ฐ ๊ฐ์๊ธฐ ๋ฐ๋๋ค๋ฉด?
์ด๋ฅผํ ๋ฉด ๋ด ์ฃผ๋ฏผ๋ฑ๋ก๋ฒํธ๊ฐ ๋ณ๊ฒฝ๋์ด ๊ทธ๊ฐ ์ด์์๋ ์ธ์์ด ํ๋ฃจ์์นจ์ ๋ค๋ฅธ ์ฌ๋์ด ๋๋ ๊ฒ๊ณผ ๋ง์ฐฌ๊ฐ์ง์ด๋ฏ๋ก ์๋ณ์์ ์์ ์ฑ์ ์ค์ํ๋ค.
์ด๋ ์ญ์ invariant ํ๊ฒ ๋ถ๋ณ์์ ๋ถ์ฌํ์ฌ ์์๋ก ๋ง๋๋ ๊ฒ์ ๊ถ์ฅํ๋ค
field ํน์ฑ 2. Immutable
๋ฐ๋ฉด์ ์ ์ ์ด๋ฆ์ ์ธ์ ๋ ์ง ๋ณ๊ฒฝ๋ ์ ์๊ธฐ ๋๋ฌธ์ ๋ณ๊ฒฝ๋ ์ ์๋๋ก ์์๋ก ์ทจ๊ธํด์๋ ์๋๋ค.
field ์์ฒด๋ฅผ ์์๋ ์๋์ง๋ง ๋จ์ immutable ํ ๊ฐ ๊ฐ์ฒด๋ก ์ทจ๊ธํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค. (๊ฐ ๊ฐ์ฒด์ ๋ํด์๋ ์ดํ ์์ธํ ์ค๋ช ํ๋๋ก ํ๊ฒ ๋ค)
field ๋ฅผ Immutable ํ๊ฒ ์ ์งํ๋ค๋ฉด ์ฌ๋ฌ๊ฐ์ง ์ด์ ์ด ์๋ค.
์ฐ๋ฆฌ๋ ๋ฉ๋ชจ๋ฆฌ์ ์ฐธ์กฐ๊ฐ์ ์ด์ฉํ๋ ์ฐ์ฐ์ ์ฃผ๋ก ํ๋ Reference-oriented programming ์ธ์์ ์ด๊ณ ์๋ค.
๋ง์ฝ ํน์ field ์ reference ๊ฐ ์์ํ์ง ๋ชปํ ๊ณณ์ ๋จ์์๊ณ , ๋ค๋ฅธ operation ์ ์ํด์ ๋ณ๊ฒฝ๋๋ ๊ฒ์ ๋ง์์ค ์ ์๋ค.
์๋ฅผ ๋ค์ด๋ณด๋ฉด ๋ณด์
public class User {
private Age age;
public User(int i) {
this.age = new Age(i);
}
}
public class Age {
private int age;
void plus() {
this.age++;
}
}
์ ์ฝ๋์์ Getter ๋ Equals Hashcode ์ฌ์ ์ ์ฝ๋๋ ์ ๊ฑฐํ์๋ค.
๋ค์ ํ ์คํธ์ฝ๋๋ ์ฑ๊ณตํ ๊น?
@Test
void name() {
User user = new User(0);
Age age = user.getAge();
age.plus();
assertThat(user.getAge()).isEqualTo(new Age(0));
assertThat(age).isEqualTo(new Age(1));
}
์คํจํ๋ค.
testcode ๋ด์์ ์ฐธ์กฐ๋ฅผ ํตํ ์ฐ์ฐ์ด ์ํ๋์ด user ๊ฐ ์์ ํ age ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ดํฐ ์์ฒด๊ฐ ๋ณ๊ฒฝ๋์ด๋ฒ๋ ธ์ ๊ฒ์ด๋ค.
์ด๋ฐ ์ํฉ์ ๋๋นํ์ฌ Field ์ ๋ชจ๋ ์ฐ์ฐ์ Immutable ํ๊ฒ ์ค๊ณํ๋ค๋ฉด ์์ํ ์ ์๋ side effect ์ ๋ํด ์์ ํ entity ๋ฅผ ์ค๊ณํ ์ ์๋ค
์ ๋ฆฌ
- entity ์ ์์ฑ์ db field ์ ์ํด ๊ฒฐ์ ๋์ง ์๋๋ค.
- ๊ฐ์ฒด์ ์ฑ ์๊ณผ ์ญํ ์ ๋ฐ๋ผ ๊ฒฐ์ ๋๋ค
- entity ์ ์์ฑ์ 2๊ฐ์ง ๋ํ ํน์ฑ
- invariant
- immutable
Entity ์ ํ์
entity ๋ ๋๋ฉ์ธ ๋ชจ๋ธ์ ํต์ฌ ๊ฐ์ฒด์ด๋ค.
๊ทธ ์ญํ ๊ณผ ์ฑ ์์ด๋ผ๋ ๊ฒ์ ์์ ์์ฑ์ ์ด์ผ๊ธฐํ ๋์ ๋์ผํ๊ฒ Ubiqutious Language ๋ก ๋ถํฐ ์ถ๋ฐํ๋ ๊ฒ์ด๋ค
entity ๋ ํต์ฌ์ด๋ผ๋ ์ด๋ฆ์ ๊ฑธ๋ง๊ฒ ์ ์ ํ ์ญํ ๊ณผ ์ฑ ์์ด ์กด์ฌํด์ผ ํ๋ค.
์ง๊ธ๋ถํฐ ์ด์ผ๊ธฐํ ๋ด์ฉ์ DDD ๋ณด๋ค ๋ ์์ด์ ์ธ OOP ์ ๊ฐ์ฒด๊ฐ ์ํธ์์ฉ์ ์ด์ผ๊ธฐํ๋ ๋ด์ฉ์ด๋ค.
Entity ํ์์ ํน์ฑ 1. ์์จ์ ์ธ ๊ฐ์ฒด, object autonomy
๊ฐ์ฒด์ ์์จ์ฑ์ ๊ฐ์ฒด๊ฐ ์ค์ค๋ก ๊ฒฐ์ ์ ๋ด๋ฆฌ๊ณ ํ๋ํ ์ ์๋ ๋ฅ๋ ฅ์ ์๋ฏธํ๋ค.
๊ฐ์ฒด๋ ์์ ์ ์์ฑ๊ณผ ์ํ์ ๋ํด์ ์บก์ํ๋ฅผ ํตํด์ ์ค์ค๋ก ํ์ํ ์ ์์ด์ผ ํ๋๋ฐ, getter ์ setter ๋ค๋ก ์ฌ์ฉํ๋ฉด์ ๊ฐ์ฒด์ ์์จ์ฑ์ ๋นผ์๋ ๋์ ๊ณผ๊ฑฐ ์ฝ๋๋ฅผ ๋ด๋ณด์
public class AbcService {
//...
public void changeUserName(long userId, String newUsername) {
User user = repository.findBy(userId);
UserName username = user.getName();
if (!username.length() > 0) {
throw new IllegalArgumentException("์ด๋ฆ์ 0์ ์ด์์ด์ด์ผ ํฉ๋๋ค")
} else if (!username.length() <= 6) {
throw new IllegalArgumentException("์ด๋ฆ์ 6์ ์ดํ์ฌ์ผ ํฉ๋๋ค")
}
user.setUsername(newUsername);
repository.save(user);
}
//...
}
ํด์ผํ๋ ์ผ์ด ์ผ์ข ์ ์์๋์ฒ๋ผ ๋์ด๋์ด์๊ณ , ๊ฐ์ฒด ์ค์ค๋ก๊ฐ ๋ฌด์ธ๊ฐ๋ฅผ ์ ํ ํ์ง ๋ชปํ๋ค.
Entity ์ค์ค๋ก ํ์๋ฅผ ํ ์ ์๋๋ก ์์จ์ฑ์ ๋ถ์ฌํ๋ค๋ ๊ฒ์ ๊ฐ๋จํ๋ค.
์์ ํ์๋ค์ Entity ๊ฐ ์ค์ค๋ก ํ ์ ์๋๋ก public interface ๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด๋ค.
public class AbcService {
//...
public void changeUserName(long userId, String newUsername) {
User user = repository.findBy(userId);
user.changeUsername(newUsername);
repository.save(user);
}
//...
}
์ด๋ ๊ฒ ์์จ์ฑ์ ๋์ด๋ฉด ๊ฐ์ฒด ์ค์ค๋ก๊ฐ ์ผ๊ด์ฑ์ ๋ํด์ ์ฑ ์์ง ์ ์๊ฒ ๋๋ค.
์ด๋ ๊ฒ Entity ์๊ฒ ํ์๋ฅผ ๋ถ์ฌํ๋ฉด ๋ถ์ฌํ ์๋ก, ์ฆ ์์จ์ฑ์ ๋์ผ์๋ก Service Layer ์ ์ฝ๋๊ฐ ์ค์ด๋๋ ๋๋ค๋ฅธ ๋ถ์ํจ๊ณผ๋ฅผ ์ผ์ผํฌ ์ ์๋ค.
Entity ํ์์ ํน์ฑ 2. ์๊ธฐ ์บก์ํ, self encapsulation
martin fowler ๋ ๋ณธ์ธ์ ๋ธ๋ก๊ทธ์ Self Encapsulation ์ด๋ผ๋ ๊ธ์ ์ผ๋ค.
์ฆ, ๊ฐ์ฒด์ ์ํ์ ํ์๋ฅผ ์บก์ํํ์ฌ ์ธ๋ถ์ ๋ ธ์ถ๋๋ ๊ฒ์ ์ต์ํํ์ฌ ๊ฐ์ฒด ์ค์ค๋ก๊ฐ ์ฑ ์์ ์ํํ๋ ์์น์ด๋ค.
์์ ์์จ์ฑ๊ณผ ๋น์ทํ ๋งฅ๋ฝ์ด์ง๋ง ์ค์ํ ๊ฒ์ ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถ๋ค๋ ๊ฒ์ด๋ค.
public class AbcService {
//...
public void changeUserName(long userId, String newUsername) {
User user = repository.findBy(userId);
UserName username = user.getName();
if (!username.length() > 0) {
throw new IllegalArgumentException("์ด๋ฆ์ 0์ ์ด์์ด์ด์ผ ํฉ๋๋ค")
} else if (!username.length() <= 6) {
throw new IllegalArgumentException("์ด๋ฆ์ 6์ ์ดํ์ฌ์ผ ํฉ๋๋ค")
}
user.setUsername(newUsername);
repository.save(user);
}
//...
}
์ด ์ฝ๋์์ AbcService ๋ ๋ค์๊ณผ ๊ฐ์ import ๋ฅผ ๊ฐ์ง๊ณ ์์ ๊ฒ์ด๋ค.
import com.github.dhslrl321.User.UserName;
์ด ๋ง์ Service ๊ฐ UserName ์ ์์กดํ๋ค๋ ๊ฒ์ด๋ค. ์ฆ, UserName ์ด ๋ณ๊ฒฝ๋๋ฉด Service ๊น์ง ๊ทธ ๋ณ๊ฒฝ์ด ์ ํ๋ ์ ์๋ค๋ ๋ป์ด๋ค.
๋ค์๊ณผ ๊ฐ์ด User ๊ฐ Self Encapsulation ์ ํตํด์ ์์กด ๊ด๊ณ๋ฅผ ์ฐจ๋จํ ์ ์๊ฒ ๋๋ค.
public class User implements Entity {
// ...
private UserName username;
// ๊ฐ์ฒด์ ํ์, self encapsulation
public void changeUserName(String target) {
username = username.change(target);
}
// ...
}
public class UserName {
String value;
public UserName change(String target) {
validate(target.length() > 0, IllegalArgumentException.class);
validate(target.length() <= 6, IllegalArgumentException.class);
return new UserName(target);
}
}
์ด๋ entity ๋ง์ ํน์ฑ์ด๋ผ๊ธฐ ๋ณด๋ค Value Object ์๋ ํด๋น๋ ์ ์๋ ๋๋ฉ์ธ ๋ชจ๋ธ ๊ฐ์ฒด์ ํน์ฑ์ด๋ผ๊ณ ํ ์ ์๋ค.
์ด๋ ๊ฒ ํ๋ ฅํ๋ ๊ฐ์ฒด๋ค์ ๊ณต๋์ฒด๋ฅผ ์ ๋ง๋ค๋ฉด rich domain model ์ ๊ตฌํํ ์ ์๋ค.
๊ฐ์ฒด๋ฅผ ๋์ด์ DTO ๋ก ์ฌ์ฉํ์ง ๋ง์. ๊ฐ์ฒด๊ฐ์ ํ์๋ฅผ ์ ๋ถ์ํ๊ณ ์ฑ ์์ ๋ถ์ฌํ๋ฉด, ๊ทธ๋ค๊ฐ์ ํ๋ ฅ์ ํตํด์ transactinal script ๋ฐฉ์์ ๋ฒ์ด๋ ์ ์๊ฒ ํด์ค๋ค.
์ ๋ฆฌ
- entity ์ ํ์ ์ญ์ domain modeling ๊ณผ ubiqutious language ์ ์ํด ๊ฒฐ์ ๋๋ค.
- entity ์ ๋๊ฐ์ง ํ์ ํน์ฑ (์ด๋ entity ๋ฟ๋ง ์๋๋ผ value object ์์๋ ๋์ผํ๋ค)
- object autonomy: ๊ฐ์ฒด์ ๋์์ ์ง์ค
- self encapsulation: ๊ฐ์ฒด์ ์ ๋ณด ์๋๊ณผ ์บก์ํ์ ์ง์ค
๋ง์น๋ฉฐ
์ด๋ ๊ฒ ์ค๋์ Entity ์ ๋ํด์ ์ด์ผ๊ธฐํด๋ณด๋ ์๊ฐ์ ๊ฐ์ก๋ค.
Entity ๋ db table ์ ์์กดํ์ง ์๋๋ค.
entity ๋ ์ด์์๋ ๋๋ฉ์ธ ๊ฐ์ฒด ๊ทธ ์์ฒด๋ฅผ ์๋ฏธํ๊ณ , ์๋ณ์ ํตํด ์ฐ์์ฑ์ ๊ฐ์ง๊ฒ ๋๋ค.
์๋ณ์ ๋ํด์๋ ํ ์ด์ผ๊ธฐ๊ฐ ๋ง๋ค.
์๋ณ์๊ฐ ๋ฌด์์ด๊ณ ์ด๋ค ํน์ฑ์ ๊ฐ์ ธ์ผ ํ๋์ง ๋ถํฐ ์์ํด์ ์ธ์ ์์ฑํ๋๋ ๋๊ฐ ์์ฑํ๋๋๊น์ง.
์ด์ ๊ด๋ จ๋ ์ด์ผ๊ธฐ๋ ๋ค์ ์๊ฐ์ ์งํํด๋ณด๋ ค ํ๋ค.
Entity ์ธ Value Object ์ ๋ํด์๋ ์ฐจ์ด์ ์ด ๋ช ํํ์ง ์์๋ฐ, ์ดํ์ ๋ ์ด์ผ๊ธฐ๋ฅผ ํ๋ ์๊ฐ์ ๊ฐ์ ธ๋ณผ ๊ฒ์ด๋ค
'๐ฌweb application > - DDD' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
DDD ์ aggregate ์ ๋ํ ์ด์ผ๊ธฐ (1) | 2024.04.10 |
---|---|
[DDD] Value Object ์ ๋ํ ์ฌ๋ฌ ์ด์ผ๊ธฐ (0) | 2023.07.23 |
[DDD] Entity ์ ์๋ณ์(identifier) ์ ๋ํ ์ฌ๋ฌ ์ด์ผ๊ธฐ (2) | 2023.07.15 |
Repository Pattern - ์ค์ ํธ (Spring ์์ DIP ๋ฅผ ํตํด Repository ์ ์ ์ธ๊ณผ ๊ตฌํ ๋ถ๋ฆฌ์ํค๊ธฐ) (6) | 2022.08.28 |
[DDD] Repository Pattern ์ด๋, ์ด๋ก ํธ (0) | 2022.08.23 |
๋๊ธ