생성자
- 주생성자
- 부생성자
부 생성자가 주 생성자 위에 있어야 한다.
부 생성자는 주 생성자를 호출해서 해야한다.
상속과 조합
상속은 항상 최선은 아니다.
composition이 좋다.
상속을 사용하면 확장성이 떨어진다.
유연성을 더 좋게 가져가는 방법이 컴포지션이다.
- 상속보단 컴포지션 : 검색해보기
가변 객체와 불변 객체
상태와 행위를 가지는 객체를 모두 불변으로 만드는 것보단
변경이 불필요한 것만 불변으로 하는게 좋다.
모든 것을 불변 객체로 만들지 말자
기능추가의 확장성을 보기위한 블랙잭 2단계 미 션해보기
베팅 기능 추가
로또 클래스
public class Lotto {
protected List<Integer> lottoNumbers;
public Lotto(List<Integer> lottoNumbers) {
this.lottoNumbers = new ArrayList<>(lottoNumbers);
}
public boolean contains(Integer integer) {
return this.lottoNumbers.contains(integer);
}
...
}
1등 로또 클래스
public class WinningLotto extends Lotto {
private final BonusBall bonusBall;
public WinningLotto(List<Integer> lottoNumbers, BonusBall bonusBall) {
super(lottoNumbers);
this.bonusBall = bonusBall;
}
public long compare(Lotto lotto) {
return lottoNumbers.stream()
.filter(lotto::contains)
.count();
}
...
}
위의 클래스를 예로 살펴봤을 때, 1등 로또는 로또 클래스와 강한 의존성을 가지고 결합하고 있다.
여기서 만약 로또 클래스의 lottoNumbers가 List에서 int[]배열로 바뀌는 경우
1등 로또 클래스의 모든 로직을 수정해야 할 수 있다.
그래서 이런 경우 상속은 유지보수도 어렵고, 확장성도 떨어진다.
이때 조합을 사용하면 어떨까?
public class WinningLotto {
private Lotto lotto;
private BonusBall bonusBall;
}
Lotto클래스의 메서드를 호출하여 사용하기 때문에 캡슐화를 깨지도 않고, 확장성도 유지하면서 사용할 수 있다.
조합이 무조건 좋은 것은 아니다.
조건만 맞춘다면..
- 확장을 고혀한 확실한 is-a 관계일 때
- API에 아무런 결함이 없는 경우, 결함이 하위 클래스까지 전파되도 괜찮은 경우
도메인의 DTO 의존
Controller와 service, view의 의존관계
4.1. Service가 DTO를 반환하는 경우
Article savedArticle = articleService.createArticle(article);
ArticleResponseDto articleResponseDto = ArticleResponseDto.from(savedArticle);
Service 레이어가 도메인 Model을 Controller로 반환하고, Controller가 Entity를 DTO로 변환하는 경우를 생각해봅시다. 이 때 예상되는 문제점은 무엇이 있을까요?
- View에 반환할 필요가 없는 데이터까지 Domain 객체에 포함되어 Controller(표현 계층)까지 넘어옵니다.
- Controller가 여러 Domain 객체들의 정보를 조합해서 DTO를 생성해야 하는 경우, 결국 Service(응용 계층) 로직이 Controller에 포함되게 됩니다.
- 여러 Domain 객체들을 조회해야 하기 때문에 하나의 Controller가 의존하는 Service의 개수가 비대해집니다.
하지만 Service 레이어가 DTO를 반환한다면 이러한 단점을 쉽게 상쇄할 수 있습니다.
4.2. Service가 DTO를 사용하는 경우
Article article = articleRequestDto.toEntity();
articleService.deleteArticle(article);
Controller가 View로부터 받은 DTO를 Entity로 변환한 뒤, Service 레이어가 Entity를 전달받아 일련의 비즈니스 로직을 수행한다고 가정해봅시다.
위 예제는 Controller에서 DTO를 Entity로 간단하게 변환했지만, 복잡한 어플리케이션의 경우 Controller가 View에서 전달받은 DTO만으로 Entity를 구성하기란 어렵습니다. Repository를 통해 여러 부수적인 정보들을 조회하여 Domain 객체를 구성할 수 있는 경우도 존재하기 때문입니다.
public Article createArticle(LoginUser loginUser, ArticleDto articleDto) {
//복잡한 로직이 존재한다고 가정...
Tags tags = tagService.findTagsByTagColor(articleDto.getTagColor());
List<History> history = loginUser.findFormerHistories(tags);
Article article = new Article(articleDto.getId(), articleDto.getName(), articleDto.getContent(), tags, history);
return articleRepository.save(article);
}
Controller에서 DTO를 완벽하게 Domain 객체로 구성한 뒤 Service에 넘겨주려면, 복잡한 경우 Controller가 여러 Service(혹은 Repository)에 의존하게 됩니다. 이러한 경우 DTO를 Service에게 넘겨주어 Service가 Entity로 변환시키도록 하는 것이 더 나은 방안이라 사료됩니다.
'모각코 > 어쩌다보니 박준태가 조장이조' 카테고리의 다른 글
6회차 어쩌다보니 박준태가 조장이조 - 2. 6.(화) (0) | 2024.02.06 |
---|---|
5회차 어쩌다보니 박준태가 조장이조 - 1.30.(화) (0) | 2024.02.03 |
1.17.(수) 모각코 (0) | 2024.01.22 |
4회차 어쩌다보니 박준태가 조장이조 - 1.22.(월) (0) | 2024.01.22 |
3회차 어쩌다보니 박준태가 조장이조 - 1.17.(수) (1) | 2024.01.17 |