Enum과 함수형인터페이스(Predicate, Function)를 활용한 리팩토링 + 다국어 관리 - 2

Y_Sevin·2023년 10월 24일
0
post-thumbnail
post-custom-banner

😅 필자가 개인적으로 공부하고 남기는 것이기 때문에 정보가 미흡할 수 있습니다. 잘못된 내용이 있을경우 지적해주신다면 감사히 받겠습니다.

3차 리팩토링 ✨

3차 리팩토링은 한국어로 하드코딩되어있던 부분을 다국어로 확장함에 따라 언어가 추가되더라도 비즈니스 로직에 영향을 주지 않는 구조로 변경하는 부분이다.

사실 이부분은 자신없는 부분이기에 어느순간 내용이 바뀔 수도 있다...😭

다국어 관리에 있어 어떻게 관리할 것인가를 고민하였다.

  • 하드코딩 🧨
  • Spring Message
  • Enum ✔

이중 필자가 선택한 것은 Enum이다. 현재 서비스에서 가지고있는 얼굴분석 요소는 매우 많다. 때문에 실수로 번역하지 않은 값들이 존재할 수 있겠다는 생각이 들었다.
하지만 Enum을 통해 관리한다면 컴파일 단계에서 에러를 잡을 수 있다는 장점이 있었기에 실수를 줄일 수 있지 않을까..?라는 생각으로 이를 선택했다.

public enum ValidFaceFeatureMessage {
    ROUND_FACE("Round face", "둥근형 얼굴")
    ...
    private final String messageInEnglish;
    private final String messageInKorean;

    ValidFaceFeatureMessage(String messageInEnglish, String messageInKorean) {
        this.messageInEnglish = messageInEnglish;
        this.messageInKorean = messageInKorean;
    }

    // 필자는 해당부분이 매우 마음에 들지 않는다. 때문에 enum을 사용하는게 맞나? 라는 의문이 들었다..
    public String getMessage(Language language) {
        return (language == Language.KO) ? messageInKorean : messageInEnglish;
    }
}    
public enum ValidFaceFeature {
    ROUND_FACE(value -> value.getFaceShapeType() == FaceShapeType.ROUND, EffectOfStyle::getRoundFaceShape, ValidFaceFeatureMessage.ROUND_FACE)
    ...
    
    private final Predicate<ProcessedFaceValue> type;
    private final Function<EffectOfStyle, Float> effectValueGetter;
    private final ValidFaceFeatureMessage message;
    
    ValidFaceFeature(Predicate<ProcessedFaceValue> type, Function<EffectOfStyle, Float> effectValueGetter, ValidFaceFeatureMessage message) {
        this.type = type;
        this.effectValueGetter = effectValueGetter;
        this.message = message;
    }
    
    public boolean isValidFeature(ProcessedFaceValue processedFaceValue, EffectOfStyle effectValues) {
        return type.test(processedFaceValue) && effectValueGetter.apply(effectValues) != 1.0;
    }
    
    public String getMessage(Language language){
        return message.getMessage(language);
    }
    

하지만 코드를 보면 ValidFaceFeatureMessage는 언어가 증가할 수 록 필드가 늘어난다..
문론 필드가 늘어났기에 빈값이 존재하면 컴파일 에러가 발생한다. 하지만 과연 이게 좋은 코드인지에 대한 의문은 아직도 존재한다.
또한 getMessage의 코드는 언어가 늘어남에따라 if문 또한 늘어난다..


최종 ✨

95 * 2(같은 로직의 다른 메서드) = 190줄

9 * 2 = 18줄 😎

이전코드는 if문이 너무 많아 해당 로직이 어떻게 동작하는지 판단하기 어려웠었다.
현재는 비즈니스 로직에 대한 코드만 들어있기에 분석요소를 가져오고 유효한 요소인지 판단한 후 값을 포함하는 로직임을 파악할 수 있다.

또한 enum을 통해 관리함에 따라 이후 분석요소에대한 추가가 필요할때 비즈니스 로직에대한 변경없이 enum에 값만 추가하면 되는 코드로 변경할 수 있었다.

리팩토링시 목표했던 것을 다시한번 확인해보자

🟢1. 향후 얼굴 분석의 요소가 늘어나더라도 비즈니스 로직을 건들이고 싶지 않다.

  • enum을 통해 관리하기에 로직을 건들이지 않아도 된다

🟢2. 비즈니스 로직의 역할과 과정이 무엇인지 명확하게 보이는 코드가 필요하다.

  • 수많은 if문으로 인해 가독성이 떨어졌던 이전과 달리 역할과 과정에 집중한 로직으로 변경됐다.

🔴3. 다국어를 추가하기 용이한 구조로 변경하고 싶다.

  • 노력은 했지만 사실 실패라고 생각한다... getMessage 코드를 보면 언어가 늘어날수록 if문이 증가한다.....😥

🟢4. 나머지 서비스에 영향을 주지 않도록 최대한 현재 로직의 구조만 변경할 것

  • enum을 추가해 현재 로직에만 영향이 가도록 변경했다.

후기
사실 리팩토링을 하기는 했지만.. 솔직히 혼자 생각하고 구성했기에 이 과정이 옳은지 판단하기 어려웠다.
또한 프로젝트를 진행하며 지금 리팩토링을 진행하는건 사치야..!!!
라고 생각했던 적이 있었다.
하지만 비즈니스로직이 190 -> 9 로 줄어들고 코드에 대한 가독성이 올라가는 과정을 경험은 코드 설계의 중요성과 리팩토링의 중요성을 스스로 깨달을 수 있었던 계기가 아닐까 싶다.

profile
매일은 아니더라도 꾸준히 올리자는 마음으로 시작하는 개발블로그😎
post-custom-banner

0개의 댓글