Chris940915 / geo_benchmark

0 stars 0 forks source link

dto #19

Open Chris940915 opened 3 years ago

Chris940915 commented 3 years ago

정적 메서드

2가지. 1) 클래스의 인스턴스 없이 호출이 가능하며, 인스턴스에는 호출 할 수 없다. 2) 유틸리티 함수를 만드는데 유용하게 사용된다.

클래스가 메모리에 올라갈 때, 정적 메서드가 저동적으로 생성된다. 그러므로 인스턴스를 생성하지 않고, 클래스 만으로 메소드를 호출할 수 있다.

DTO

1. 어디서 어디까지 dto 사용.

[그림] Controller - service ,, Persistence layer까지는 Entity를 사용. Service에서부터 Client까지는 dto를 사용?

Controller - Service에서 dto를 사용하게 되면

  1. 어떤 요청 필드를 받는지 명확하게 알 수 있음.
  2. Domain 로직으로 처리하기 전에 유효성 체크 가능.
  3. 두 계층 간의 의존성 제거 가능.

Presentation layer인 Contoller는 무조건 DTO. Entity 가 외부로 노출이 된다면, 양방향 매핑의 경우 외부에서 Entity를 호출하는 순간 순환참조에 걸리게 된다. 또한, Entity 안에 dto와 연관된 로직들이 들어갈 가능성이 높아진다.

지금도 고민 중. 현재는 Controller - Service에 Entity로 교환.

Why?

Entity 대신에, DTO 넘겨받을때 장점.

2. Entity, DTO 변환은 어떻게?

Chris940915 commented 3 years ago
public class ExperimentDto{
    private Long id;
    private String name;
    private String memo;
    private LocalDateTime reg_date;
    private List<CkptDto> ckpts;
    public ExperimentDto(Experiment experiment){
        id = experiment.getId();
        name = experiment.getName();
        memo = experiment.getMemo();
        reg_date = experiment.getReg_date();
        ckpts = experiment.getCkpts().stream()
                .map(getCkpt -> new CkptDto(getCkpt))
                .collect(toList());
    }
}

기존 DTO


public class ExperimentMapper {

    @Getter @Setter
    public static class All{
        private Long id;
        private String name;
        private String memo;
        private LocalDateTime reg_date;

        public static All of(Experiment experiment){
            ModelMapper modelMapper = new ModelMapper();
            All dto = modelMapper.map(experiment, All.class);
            return dto;
        }
    }

    @Getter @Setter
    public static class Basic extends All{
        private Long id;
        private String name;
        private String memo;
        private LocalDateTime reg_date;
        private List<CkptMapper.Basic> ckpts;

        public static Basic of(Experiment experiment){
            ModelMapper modelMapper = new ModelMapper();
            modelMapper.typeMap(Experiment.class, Basic.class)
                    .addMappings(mapping -> mapping.skip(Basic::setCkpts));

            Basic basicDto = modelMapper.map(experiment, Basic.class);
            List<CkptMapper.Basic> ckpts = experiment.getCkpts().stream()
                    .map(ckpt -> CkptMapper.Basic.of(ckpt))
                    .collect(Collectors.toList());

            basicDto.setCkpts(ckpts);
            return basicDto;
        }
    }

    @Getter @Setter
    public static class Param{
        private Long id;
        private String name;

        public static Param of(Experiment experiment){
            ModelMapper modelMapper = new ModelMapper();
            Param dto = modelMapper.map(experiment, Param.class);
            return dto;
        }
    }
}
Chris940915 commented 3 years ago

ModelMapper 사용.

DTO와 Entity간의 객체전환 및 매핑의 반복작업 등을 상당부분 줄일 수 있게 된다. Entity의 모든 필드를 Set을 다 안해놔도 된다. Entity에 없는 필드들은 Set으로 직접 넣어주는 방식으로 변환을 진행.

inner class로 사용.

지금 상태에서는 괜찮다고 생각, 만약 API가 더 많아지면 사용에 어려움이 있을 수도 있음. 그리고 field가 많아지면 (특정 도메인 관련 inner class가 많아지면) class가 비대해질 수도 있음. 예를 들어, 한 개의 inner class에 다양한 Response DTO가 생기면 문제가 될 수도 있음.

변환 작업은 어디서?

변환작업은 DTO inner class 내에 static 메서드를 만들어서 변환하는 방법을 선택.