백/spring boot

Consumer 인터페이스 구현

남승현 2024. 6. 23. 16:49

멤버 평가 구현 api를 개발하였다

-> 8가지 태그가 있으며 해당하는 태그를 복수 선택하여 해당 멤버에 대한 리뷰를 남기는 형식이다.

 

맨 처음엔 reviewDto를 통해 각 태그들에 대한 boolean 값을 받아오고, 값이 true라면 해당 멤버의 review 엔티티의 필드 값을 +1 시켜 저장하는 방식으로 구현하였다.

 

<ReviewDto>

@Getter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class ReviewDto {
    private Long id;
    @JsonProperty("no_late")
    private Boolean noLate;

    private Boolean faithful;

    private Boolean kind;

    private Boolean unkind;
    @JsonProperty("fast_answer")
    private Boolean fastAnswer;
    @JsonProperty("slow_answer")
    private Boolean slowAnswer;

    private Boolean passive;

    private Boolean absent;
    @JsonProperty("user_id")
    private Long userId;
}

 

<ReviewService>

public Boolean createReview(Long studyId, Long userId, ReviewDto reviewDto) {
        /* userId로 해당하는 review찾기 -> reviewDto에서 get한 애들값을했을 떄 true면 review 필드 +1해주기 -> reviewRepository에 갱신된 review 저장(save)*/
        Review review=reviewRepository.findByUser_id(userId).orElseThrow(()->new IllegalArgumentException("없는 유저입니다"));
        
        if(reviewDto.getNoLate().equals(true)){
            Long origin=review.getNoLate();
            review.setNoLate(origin+1);
        }
        if(reviewDto.getFaithful().equals(true)){
            Long origin=review.getFaithful();
            review.setFaithful(origin+1);
        }
        if(reviewDto.getKind().equals(true)){
            Long origin=review.getKind();
            review.setKind(origin+1);
        }if(reviewDto.getUnkind().equals(true)){
            Long origin=review.getUnkind();
            review.setUnkind(origin+1);
        }if(reviewDto.getNoLate().equals(true)){
            Long origin=review.getFastAnswer();
            review.setFastAnswer(origin+1);
        }if(reviewDto.getSlowAnswer().equals(true)){
            Long origin=review.getSlowAnswer();
            review.setSlowAnswer(origin+1);
        }if(reviewDto.getPassive().equals(true)){
            Long origin=review.getPassive();
            review.setPassive(origin+1);
        }if(reviewDto.getAbsent().equals(true)){
            Long origin=review.getAbsent();
            review.setAbsent(origin+1);
        }

        return true;
    }

 

이렇게 구현하면 너무 코드 반복이 많아서 더 간결하게 구현할 수 없나 다른 방법 찾게 됨

-> 함수를 구현하고 호출하고 싶은데 set필드명을 반복해야 하기에 구현이 막막했다

 

<필드명, .set필드명(값) 함수>를 하나의 맵에 담아 저장하고 얘를 호출하는 방식을 찾다가 Consumer 인터페이스에 대해 알게 됨!

Consumer 인터페이스 : 매개값을 받고 이 인자에 대해 일정한 작업을 하되, 아무것도 반환하지 않는 함수형 인터페이스

-> 주로 입력값을 이용한 연산/출력 등의 동작에 이용된다고 한다

-> accept(매개변수) : 실행시키는 메소드

 

이를 이용하여 코드를 간결하게 바꿔보았다

: <필드명, true/false>를 담고있는 map과 을 받아 value값이 true라면, <필드명, .set필드명(값) 함수> map의 value, 즉 메소드를 실행하기

 

<ReviewDto>

@Getter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class ReviewDto {
    private Long id;
    @JsonProperty("no_late")
    private Boolean noLate;

    private Boolean faithful;

    private Boolean kind;

    private Boolean unkind;
    @JsonProperty("fast_answer")
    private Boolean fastAnswer;
    @JsonProperty("slow_answer")
    private Boolean slowAnswer;

    private Boolean passive;

    private Boolean absent;
    @JsonProperty("user_id")
    private Long userId;
    
    public Map<String, Boolean> toMap(){
        Map<String, Boolean> dtoMap=new HashMap<>();
        dtoMap.put("noLate", noLate);
        dtoMap.put("faithful", faithful);
        dtoMap.put("kind", kind);
        dtoMap.put("unkind", unkind);
        dtoMap.put("fastAnswer", fastAnswer);
        dtoMap.put("slowAnswer", slowAnswer);
        dtoMap.put("passive", passive);
        dtoMap.put("absent", absent);
        return dtoMap;
    }
}

<ReviewService>

public Boolean createReview(Long studyId, Long userId, ReviewDto reviewDto) {
        /* userId로 해당하는 review찾기 -> reviewDto에서 get한 애들값을했을 떄 true면 review 필드 +1해주기 -> reviewRepository에 갱신된 review 저장(save)*/
        Review review=reviewRepository.findByUser_id(userId).orElseThrow(()->new IllegalArgumentException("없는 유저입니다"));

        Map<String, Consumer<Review>> updateActions=new HashMap<>();
        updateActions.put("noLate",r->r.setNoLate(r.getNoLate()+1));
        updateActions.put("faithful", r -> r.setFaithful(r.getFaithful() + 1));
        updateActions.put("kind", r -> r.setKind(r.getKind() + 1));
        updateActions.put("unkind", r -> r.setUnkind(r.getUnkind() + 1));
        updateActions.put("fastAnswer", r -> r.setFastAnswer(r.getFastAnswer() + 1));
        updateActions.put("slowAnswer", r -> r.setSlowAnswer(r.getSlowAnswer() + 1));
        updateActions.put("passive", r -> r.setPassive(r.getPassive() + 1));
        updateActions.put("absent", r -> r.setAbsent(r.getAbsent() + 1));

        reviewDto.toMap().forEach(key,value)->{
            if(Boolean.TRUE.equals(value)){
                updateActions.get(key).accept(review);
            }
        }

        reviewRepository.save(review);

        return true;
    }

 

앞으로 Map을 적극적으로 사용하고 + 반환값이 필요없지만 입력값에 대해 연산,출력을 해야 하는 경우 Consumer 인터페이스 사용하기!