Skip to content

feat : 레거시 리팩토링 예제#1

Open
ca1af wants to merge 1 commit intomainfrom
feat/refactor
Open

feat : 레거시 리팩토링 예제#1
ca1af wants to merge 1 commit intomainfrom
feat/refactor

Conversation

@ca1af
Copy link
Owner

@ca1af ca1af commented Jun 10, 2024

상세 구현 (예시) - 기존 레거시 vs 개선된 서비스

  • 기존 레거시 코드 (예시)
@RequiredArgsConstructor
@Service
public class LegacyService {

    private final PartnerOne partnerOne;

    private final PartnerTwo partnerTwo;

    // ...

    // 조회 (예시)
    public String retrieve(Map<String, Object> objectMap){ //
        // ...
        String identifier = (String) objectMap.get("identifier");
        switch (identifier){
            case "partnerOne" : return partnerTwo.retrieve();
            case "partnerTwo" : return partnerOne.retrieve();
            default: throw new RuntimeException("custom exception");
        }
        // ...
    }
    
    // 승인 ...
    
    // 취소 ...

기존 소스(레거시)에서 개선하고 싶었던 불편함들

  1. 제휴사가 늘어나게 되면, (혹은 삭제되면) 산재되어 있는 switch-case 문을 수정해야 한다.
  2. Map<String, Object> 형태의 데이터는 실제 디버그 전에는 어떤 데이터가 들어가있는지 흐름을 파악하기가 어렵다.
  3. 분기문의 depth 가 너무 길거나, 한 매서드가 너무 많은 일을 해서 소스 파악이 힘들다.

개선한 서비스 (예시)

  • 인터페이스를 이용하여 파트너사가 공통으로 가지는 로직을 추상화
public interface PartnerService {
    String retrieve();
    String approve();
    String cancel();
    Identifier getIdentifier();
}

// getIdentifier() 매서드를 통해 파트너사를 구분하도록 각각에 맞는 enum타입 리턴
  • 추상화된 List형태의 파트너사 서비스 Bean을 리스트로 주입받아, Map<Enum, Service> 형태로 저장 및 적절한 빈 분배
@Component
@RequiredArgsConstructor
public class PartnerServiceFactory {

    private final Map<Identifier, PartnerService> partnerServiceBeans = new HashMap<>();

    public PartnerServiceFactory(List<PartnerService> partnerServiceList) { // List 형태의 파트너서비스 beans 주입
        partnerServiceList.forEach(each -> partnerServiceBeans.put(each.getIdentifier(), each));
    }

    public PartnerService getPartnerService(Identifier identifier) {
        return partnerServiceBeans.get(identifier);
    }
}
  • 조회, 승인, 취소 등 API 별 서비스에서는 PartnerService 가 어떤 구현체를 사용하는지 알지 않고도 사용이 가능 (따라서 변경, 추가 등이 용이함)
  • Map<String, Object> 형태의 Request/Response 데이터를 DTO로 변경
@Service
@RequiredArgsConstructor
public class RetrieveService {
    
    private final PartnerServiceFactory partnerServiceFactory;
    
    public String retrieve(RequestDto requestDto){
        PartnerService partnerService = partnerServiceFactory.getPartnerService(requestDto.identifier());
        return partnerService.retrieve();
    }
}

개선함으로써 얻어낸 효과

  1. 제휴사가 추가, 수정, 삭제 될 때마다 switch-case 부분을 하나하나 찾아가며 변경 할 필요가 없다.
  2. Map<String, Object> 형태의 데이터를 DTO로 바꿔서, 어떤 요청과 응답 데이터들이 필요 한 지 코드 상에서 확인이 가능하다.
  3. 매서드가 적절히 나누어져서 로직의 흐름을 파악하는 데에 유리하다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant