앞의 회고 글에서 이어서 이번에는 저번에 제시한 문제들의 해결방안들에 대해 적어보겠습니다.
앞선 회고 글에서 문제로 아래의 3가지가 있었습니다.
- 너무 비대해진 서비스 클래스 코드
- 서비스가 영속성 계층에 휘둘리게 된다는 점
- DB 테이블 구조에 의존하는 코드
제 나름대로 객체지향 서적과 레퍼런스를 읽어보고 주변 분들에게 자문을 구해 찾은 해답은
1번. 특정 객체가 너무 많은 일을 하면 안된다는 것
2번. 외부의 객체나 구조에 의존하는 코드를 만들면 안된다는 것 (의존성 역전을 하자)
3번. 도메인에서 사용하는 객체와 영속성 계층에서 사용하는 엔티티를 분리하자!
1번 문제는 서비스 객체가 너무 많은 책임을 맡고 있었기 때문에 발생한것으로 서비스 객체의 책임, 그러니까 맡은 로직을 분할해서 다른 객체들에게 나눠주어야 합니다.
유저 도메인을 담당하는 서비스 로직이라고 하면 유저 안의 커다란 기능을 여러개로 나눠서 기능을 구현해야 합니다.
가령, 회원가입을 위한 서비스
, 로그인만을 위한 서비스
와 같이 기존 서비스의 로직을 나눠서 구현하면 되는것이죠.
그러면, 1번의 두가지 문제를 해결 가능합니다.
- 코드 분석시 특정 부분의 서비스만 열어서 확인하면 되니 코드 분석에 드는 리소스가 줄어든다.
- 각자 다른 기능의 서비스를 개발하면 되니 git 동시성 문제 빈도도 줄어든다.
2번 문제는 서비스 코드가 특정 레포지토리 코드를 의존하고 있어서 생기는 문제였습니다.
그래서 레포지토리 코드에 변경이 생기면 서비스 코드에도 변경이 생기는 것이 문제였죠.
그러면, 서비스가 특정 레포지토리 코드를 의존하게 하지말고 인터페이스를 의존하게 만들고 그 인터페이스 대로 레포지토리 코드를 구현하게 만들면 됩니다.
코드는 다음과 같습니다.
public interface UserRepositoryInterface{
public User findById(Long userId);
}
public class VoteService {
private final UserRepositoryInterface userRepository;
public Long createVote(@Valid CreateVoteRequest createVoteRequest, Long userId) throws UserNotFoundException {
User findUser = userRepository.findById(userId).orElseThrow(UserNotFoundException::new);
}
... // 서비스 코드에서 인터페이스 코드를 의존하고 있음
}
1.서비스에서는 인터페이스에 의존하게 만든다.
2. 인터페이스에 맞는 레포지토리 코드를 구현한다.
3. 인터페이스를 수정하지 못하게 막는다.
위의 3가지 안을 사용하면 레포지토리 코드의 변경을 막으면서 추후에 생길 문제를 예방할 수 있습니다.
3의 문제는 JPA의 엔티티 객체를 비즈니스 로직에서 사용되는 도메인 객체와 혼동하여 사용한 것이 문제입니다.
도메인단에서 사용되는 로직은 도메인만을 위한 것이여야 합니다. 즉, 서비스단에서 사용되는 객체와 레포지토리에서 사용하는 엔티티를 각각 만들고 서비스 <-> 레포지토리가 상호작용할 때 각 객체를 변환해주는 작업이 필요한 것이죠.
비유를 든다면 미국에 가면 미국 달러를 사용하는게 맞지 미국에서 한국돈을 들고 물건을 사려고 하면 안되는 것과 비슷할까요.
이렇게 하면 도메인 계층과 영속성 계층을 커다란 객체 같은 단위로 보게 됐을 때
각 단위에서의 캡슐화가 일어나
도메인 계층과 영속성 계층이 서로 독립적인 구조를 띄고 협력하게 됩니다.
저의 프로젝트 코드를 한줄로 요약하면 생각보다 더 객체지향적이지 못하다.
네요.. ㅎㅎ
이래서 프로그래밍은 글쓰기와 같아서 초고를 작성하고 여러번 보면서 수정해야 좋은 코드가 된다는거 같네요.
새로운 코드를 작성하는 것 보다 기존에 작성한 코드를 다시 보고 문제점을 찾고 개선할 때, 성장을 많이 하는것 같습니다.
이번에 정리하면서 객체지향의 의미와 추구하는 방향성에 대해 고민해보고 보다 깊게 이해하게 된 것 같습니다.
다음에는 이전에 예고한 대로 위의 해결책을 기반으로 차근차근 프로젝트에 적용해보는 시간을 가져보겠습니다.
왜 츄즈가 토이프로젝트읺과요?
베리베리 그레이트 원더풀 뷰티풀 프로젝트입니다