not-a-gardener 개발기 13) Service 재사용

메밀·2023년 11월 23일
0

not-a-gardener

목록 보기
13/13
post-thumbnail

😡 문제상황: 더이상 Dao 코드를 참을 수 없음

🫠 이 프로젝트는 대충 이렇게 생겼었다

연관관계가 있는 Repository를 Dao에서 조합해서 엔티티를 다루는 방식이다.

예컨대, 식물 엔티티장소 엔티티, 가드너(회원) 엔티티와 연관관계를 맺고 있으므로 PlantDaoPlaceRepository, GardenerRepository, PlantRepository를 가지고 있는 것이다.

🤔 이렇게 한 이유는?

하나밖에 없다.

save, update 시 엔티티 조합 로직을 분리하고 싶었다.

😡 그렇게 발생한 문제

@Override
public int getCountByChemical_ChemicalId(Long chemicalId) {
    return wateringRepository.countByChemical_ChemicalId(chemicalId);
}

읽기, 삭제 메소드는 이유 없이 레이어만 하나 타게 된다.

🥳 해결: 중복 코드 서비스로 분리

@Service
@RequiredArgsConstructor
public class ChemicalCommandServiceImpl implements ChemicalCommandService{
    private final ChemicalRepository chemicalRepository;
    private final GardenerRepository gardenerRepository;

    @Override
    @Transactional
    public <T> T update(Long gardenerId, ChemicalDto chemicalRequest, ServiceCallBack<T> callBack) {
        Chemical chemical = chemicalRepository.findById(chemicalRequest.getId()).orElseThrow(NoSuchElementException::new);
        chemical.update(chemicalRequest.getName(), chemicalRequest.getType(), chemicalRequest.getPeriod());

        return callBack.execute(chemical);
    }

    @Override
    @Transactional
    public <T> T save(Long gardenerId, ChemicalDto chemicalRequest, ServiceCallBack<T> callBack) {
        Gardener gardener = gardenerRepository.getReferenceById(gardenerId);
        Chemical chemical = chemicalRepository.save(chemicalRequest.toEntity(gardener));

        // 서비스에서 제공하는 콜백을 호출하고 결과를 반환
        return callBack.execute(chemical);
    }
}

공통 로직을 CommandService로 분리하되, 리턴용 DTO는 콜백함수를 통해 만드는 코드로 리팩토링했다.
덕분에 Dao 레이어는 아예 삭제했다.

😗 하는 김에

  • 각 Repository가 CrudRepositoryJpaRepository 대신 Repository를 extends해 실사용하는 메소드만 가지도록한다.

    • JpaRepository에는 전혀 쓰지 않는 메소드들도 잔뜩 포함되어 있었다.

😫 다시 생겨난 의문...

결국 Command/Query 서비스가 분리된 셈인데,
그러면 Controller, Service, Repository 모두 읽기 전용과 쓰기 전용으로 분리해야 하는 것 아닌가?

만들면 만들수록 어렵다

0개의 댓글