Skip to content

Commit 26920e5

Browse files
committed
Merge branch 'main' of https://github.com/gwanhyeon/TIL
2 parents 4c66c10 + 0f77267 commit 26920e5

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

architecture/ddd-hexagonal.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# DDD Clean Architecture and Hexagonal
2+
3+
멤버십 서비스를 예를 들면, 멤버십서비스에서 사용되는 포인트를 발행하기 위한 포인트 도메인, 충전하기 위한 충전도메인, 멤버십 발급에 필요한 멤버십 도메인이 필요합니다.
4+
5+
각 도메인에는 이를 구현하기 위한 여러객체가 필요하게 되며, 예를 들면 다음과 같습니다.
6+
7+
- 포인트 도메인: 포인트, 고객, 충전수단, 결제 수단
8+
- 충전 도메인: 충전 금액, 고객, 충전수단, 결제 수단
9+
- 멤버십 카드 도메인: 고객, 멤버십카드 상품, 등급
10+
11+
서로 다른 도메인이지만, 같은 객체가 존재하는데. 이는 같은 객체가 여러개 존재할 수 있다는 도메인 주도 설계의 특징중 하나입니다.
12+
13+
같은 객체이지만, 그 객체가 속한 도메인의 문맥(Context)에 따라 각 객체의 역할과 책임이 크게 바뀌는것.
14+
즉, 서로 다른 도메인영역에 영향을 끼치기 위해서는 API를 이용하여 각각에 대한 도메인의 역할과 책임을 다하는것입니다.
15+
16+
즉, 높은 응집력과 낮은 결합도로 변경과 확장에 용이한 구조를 얻게되게 해야합니다.
17+
18+
Application Layer: 주로 도메인과 Repository를 바탕으로 실제 서비스(API)를 제공하는 계층
19+
Domain Model Layer: Entity를 활용해 도메인 로직(비즈니스 로직)이 수행되는 계층
20+
Infrastructure Layer: 외부와 통신(RDBMS, Redis, HttpClient, ...)을 담당하는 계층
21+
결국 각 도메인을 분리하고, 그 도메인을 위와 같은 Layer로 철저히 분리해서 만드는 것이 DDD라 볼 수 있습니다.
22+
Conclusion
23+
결국 Clean Architecture는 다음과 같은 이점이 있다고 정의내립니다.
24+
25+
의존성 규칙에 따름으로써 관심사가 분리된다
26+
본질적으로 테스트하기 쉬운 시스템을 만들 수 있다
27+
의존성 규칙이 가져오는 이점을 가져올 수 있다
28+
그리고 주요한 이러한 특징을 지닙니다.
29+
30+
또한 같은 상황과 이유로 변경되는 Class들은 Components로 묶인다
31+
Business Rule은 stable한 components로, 변경되기 쉬운 외부의 infrastructure components (UI, DB, web, frameworks, ... )를 알지 못한다
32+
각 components layer 간의 경계는 adapter 인터페이스를 통해 관리된다
33+
Adapter는 Layer 간의 데이터를 편한 형태로 변환시켜주고 더 stable한 inner components로 의존성을 가지도록 한다
34+
35+
# Hexagonal Architecture
36+
37+
> 그럼 헥사고날 아키텍처는 무엇이고, 왜 쓰는걸까요?
38+
39+
인프라 ← 서비스 ← 프레젠테이션의 방향으로 의존성이 설계된 MVC 아키텍쳐에서는 인프라의 변화가 곧 뷰의 변화로 이어지기 쉽습니다. 하지만 웹서비스에서의 핵심은 인프라가 아니라 실제 비즈니스 로직이 수행되는 서비스 계층, 더욱 정확하게는 개발팀의 의사소통 단위가 되는 도메인 객체들입니다.
40+
41+
도메인 객체들은 근본적으로 서비스가 지니는 바운디드 컨텍스트 안에서 독립적인 로직을 가지고 있습니다. 영속성 계층, 혹은 메시지 큐와 같은 인프라는 결국 이러한 도메인의 상태를 저장하거나 전달하기 위해 존재할 뿐입니다. 즉, 도메인 객체들은 인프라에 의존하지 않아야 한다는 것입니다.
42+
43+
그렇기 때문에 헥사고날 아키텍처는 의존의 방향이 레이어드 아키텍처와 다릅니다.
44+
45+
클린 아키텍처와 마찬가지로 어디에도 의존하지 않는 도메인 객체들이 존재하고, 이들에 의존하는 서비스계층(또는 usecase 계층)이 존재합니다. 서비스계층에서 수행되는 비즈니스 로직들은 외부와 연결된 포트를 통해 시스템 외부로 전달되며 인프라는 포트에 의존합니다.
46+
47+
한 마디로, 외부와의 통신을 인터페이스로 추상화하여 비즈니스 로직 안에 외부 코드나 로직의 주입을 막는다는 것이 헥사고날 아키텍처의 핵심입니다.

java/optional.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Optional 사용방법
2+
3+
4+
> Optional 사용시 반환 처리
5+
6+
```java
7+
Optional<MobileCarrier> mobileCarriers = mobileCarrierRepository.findAll();
8+
9+
나쁜 예)
10+
11+
if(mobileCarriers.isPresent()){
12+
MobileCarrier mobileCarrier = mobileCarriers.get();
13+
}
14+
15+
올바른 예)
16+
MobileCarrier mobileCarriers = mobileCarriers.orElse(null);
17+
18+
```
19+
20+
isPresent() 함수로 조건 체크후 get()을 통하여 엔티티를 가져오는 것보다 orElse()를 통해서 처리하는것이 유효, 그 이유는 orElse는 Optional의 여부와 관계없이 실행후 값을 처리할 수 있음.
21+
22+
orElseGet(*): *는 Optional 값이 없을때만 전달된 람다식이 실행
23+
orElseThrow(+): +는 Optional 값이 없을때 예외 발생
24+
25+
> 예외 처리 예제
26+
27+
```java
28+
// bad
29+
Optional<Member> member = ...;
30+
if (member.isPresent()) {
31+
return member.get();
32+
} else {
33+
return null;
34+
}
35+
36+
// good
37+
Optional<Member> member = ...;
38+
return member.orElse(null);
39+
40+
// bad
41+
Optional<Member> member = ...;
42+
if (member.isPresent()) {
43+
return member.get();
44+
} else {
45+
throw new NoSuchElementException();
46+
}
47+
48+
// good
49+
Optional<Member> member = ...;
50+
return member.orElseThrow(() -> new NoSuchElementException())
51+
```
52+
53+
> Optional로 감싸 반환된 null 객체보다는 비어있는 컬렉션을 반환하는게 더 좋음.
54+
55+
```java
56+
// bad
57+
public interface MemberRepository<Member, Long> extends JpaRepository {
58+
Optional<List<Member>> findAllByNameContaining(String part);
59+
}
60+
61+
// bad
62+
List<Member> members = team.getMembers();
63+
return Optional.ofNullable(members);
64+
65+
// good
66+
public interface MemberRepository<Member, Long> extends JpaRepository {
67+
List<Member> findAllByNameContaining(String part); // null이 반환되지 않으므로 Optional 불필요
68+
}
69+
70+
// good
71+
List<Member> members = team.getMembers();
72+
return members != null ? members : Collections.emptyList();
73+
74+
```
75+
76+
> of(), ofNullable 혼동 주의
77+
78+
`of(X)은` X가 null이 아님이 확실할 때만 사용해야 하며, X가 null이면 NullPointerException 이 발생한다.
79+
`ofNullable(X)은` X가 null일 수도 있을 때만 사용해야 하며, X가 null이 아님이 확실하면 of(X)를 사용해야 한다.
80+
81+
> reference
82+
83+
https://homoefficio.github.io/2019/10/03/Java-Optional-%EB%B0%94%EB%A5%B4%EA%B2%8C-%EC%93%B0%EA%B8%B0/

0 commit comments

Comments
 (0)