개발자 성장 일지

2022.03.08 수업일지

NEWDODORIPYO 2022. 3. 8. 19:23

오늘은 수업에 많은 이론 설명이 있었습니다 

가장 처음 나왔던 이야기는 도메인에 관한 이야기였습니다 

어제 만들었던 맛집 데이터 로직은 1차 도메인 

오늘 새롭게 만들었던 맛집 리뷰 로직은 2차 도메인이라고 설명해주셨습니다 

하지만 아직 도메인이 정확하게 무엇인지는 이해하지 못한것 같아 오늘 이해한 부분만 말해보자면 

 

1차 도메인 : 장부로 떨어지는 단계 

 

2차 도메인 : 1차 도메인이 있어야 행동할수있는것 

 

이라고만 이해하고 넘어가도록 하겠습니다 !!! 

 

 

그리고 로직의 설명에 앞서 이해해야 하는 중요한 키워드는 

 

DTO 였던것 같습니다 

 

DTO

데이터를 주고받기 위해 만들어준 것!! <독자적인 로직을 가지고 있지 않는다> 

 

DTO를 만들 때 2가지 방법이 있는데 그 DTO의 사용 용도에 따라 나뉘는 것 같습니다 

 

DTO

읽기 : 생성자로 객체를 생성할때 데이터 전달 , geetter만 처리해준다 

< private 로 지정하였을 때 (기본, 문자열)은 안전하지만 배열 같은 경우는 안전하지 못했다 >

 

읽고 쓰기 : 생성자 ,빌더패턴(Builder) getter , setter 등을 생성 

<빌더 패턴 - 생성자 대신 사용 , 생성자는 제약과 제한이 있지만 빌더 패턴은 거기서 자유롭다 > 

 

맛집 리뷰 로직 

본격적으로 오늘 진도를 나간 리뷰관련 로직을 만들어 보겠습니다 

 

⭐로직 설계 단계

                                                                   

 

                     < 맛집 데이터 >

이름  번호 위도 경도 
........
.......
.......
........
.......
.......
........
.......
.......
........
.......
.......

맛집 데이터 로직 <1차 도메인> 

1.StoreDOT

2.StoerLoader

3.Mani

 

                      <리뷰 데이터> 

리뷰번호  식당번호  점수
........
.......
.......
........
.......
.......
........
.......
.......

리뷰 데이터 로직 <2차 도메인>

1.ReviewDTO

2.ReviewSave

3.ReviewUI

4.Main

 

완성된 로직은 이렇게 서로에게 의존하게 된다 

 

⭐리뷰 로직 시작!!

ReviewDTO

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Builder
@Getter
@Setter
@ToString
public class ReviewDTO {
    private int rno; //리뷰 번호 
    private int sno; //식당번호
    private int score; //점수


}

DTO에서는 주고받는데 필요한 데이터들을 입력해주었습니다 

 

ReviewSave -> 리뷰UI 에서 받은 값들을 저장하는 역할

//리뷰 UI 에서 얻은 정보들은 저장하는 공간
public class ReviewSave {
    //DTO 의 리뷰를 담는 배열
    private  ReviewDTO[] arr;
    //idx는 리뷰저장 공간을 만들어주기위해 만든 변수
    private  int idx;
   //생성자
    public  ReviewSave(){
        this.arr=new ReviewDTO[10];
        this.idx= 0;
    }

 리뷰를 담을 배열과 그리고 그 리뷰들을 저장할 공간을 만들어주기 위한 변수를 만들고 생성자를 만들어 주었습니다 

//배열안에 내용을 보여주는 방법 idx 의 1번부터 차례로 보여주기
    public  int add(ReviewDTO reviewDTO){
        //리뷰 등록을 1번부터 하기위해 만든 로직
        int index = idx;
        //set.Rno 복사된 Rno의 값을 수정한다 그래서 뒤에 <index+1> 가능
        reviewDTO.setRno(index +1);

        //arr배열에 증강연산자를 사용해서 리뷰 데이터축적을 할수있게 공간을 만들어줌
        this.arr[idx++] = reviewDTO;
        System.out.println(Arrays.toString(arr));
        //위에서 증가된 Rno 값을 리턴해준다
        return  reviewDTO.getRno();
    }

이 부분을 이해하는데 시간이 오래 걸렸던 것 같습니다 

add는 UI에서 받은 리뷰를 저장하는 공간입니다 

리뷰 저장공간을 위한 만들었던 idx 를 index로 연결해주었고 

리뷰 데이터들이 1번에서부터 저장되게 만들기 위해  reviewDTO에 setRno(index +1)을 해주었습니다 

그리고 arr의 공간을 리뷰가 들어올때마다 한 공간에 저장되는 것이 아닌 각각의 arr의 index에 저장될 수 있도록 

증강 연산자를 사용했습니다 

//람다식 정렬
    public ReviewDTO[] sortByScore(){
        Arrays.sort(arr,(a,b)->{
            if(a==null || b ==null){
                return 0;
            }
            return b.getScore() - a.getScore();
        });
        return arr;
    }
}

ReviewSave의 마지막 로직인 람다식 정렬....이 친구는 새롭게 배운 개념이다 

하지만 강사님이 아직은 이해할 필요없고 우선은 우리가 원하는 방식의 정렬을 하기 위해 일단은 사용한다고 말씀해주셨습니다 그래서 저도 자세한 설명은 추후 강의를 수강하고 정리해보겠습니다 

이렇게 ReviewSave 로직은 완성되었습니다 

ReviewSave

//리뷰 UI 에서 얻은 정보들은 저장하는 공간
public class ReviewSave {
    //DTO 의 리뷰를 담는 배열
    private  ReviewDTO[] arr;
    //idx는 리뷰저장 공간을 만들어주기위해 만든 변수
    private  int idx;
   //생성자
    public  ReviewSave(){
        this.arr=new ReviewDTO[10];
        this.idx= 0;
    }
//배열안에 내용을 보여주는 방법 idx 의 1번부터 차례로 보여주기
    public  int add(ReviewDTO reviewDTO){
        //리뷰 등록을 1번부터 하기위해 만든 로직
        int index = idx;
        //set.Rno 복사된 Rno의 값을 수정한다 그래서 뒤에 <index+1> 가능
        reviewDTO.setRno(index +1);

        //arr배열에 증강연산자를 사용해서 리뷰 데이터축적을 할수있게 공간을 만들어줌
        this.arr[idx++] = reviewDTO;
        System.out.println(Arrays.toString(arr));
        //위에서 증가된 Rno 값을 리턴해준다
        return  reviewDTO.getRno();
    }
    //람다식 정렬
    public ReviewDTO[] sortByScore(){
        Arrays.sort(arr,(a,b)->{
            if(a==null || b ==null){
                return 0;
            }
            return b.getScore() - a.getScore();
        });
        return arr;
    }
}

ReviewUI 

import lombok.AllArgsConstructor;
import store.StoreDTO;
import store.StoreLoader;

import java.util.Scanner;

@AllArgsConstructor
public class ReviewUI {
   //유저 입력을 위한 Scanner 호출
    private Scanner scanner;
   //ReviewUI는 ReviewSave 없이는 일할수없다 (의존성이 강함) 그래서 호출
    private ReviewSave reviewSave;
   //사용자에게 전체 가게를 보여주기위해 StoreLoader 을 호출 !!
    private StoreLoader storeLoader;

ReviwUI 는 혼자서 할 수 있는 게 별로 없다 Scanner 도 필요하고 ReviewSave도 있어야 일을 할 수 있다 

//리뷰등록 로직
public  void play(){
   //사용자의 선택  여기서 inputstr은 밑에 로직으로 구현되어있음
    String oper = inputstr("1.리뷰등록 , 2.조회 , 3.종료");

    switch (oper){
        //case 1 일때는 리뷰 등록 로직을 호출
        case "1":
            makeReview();
            break;
           //case 2 일때는 리뷰 조회 로직을 호출
            case "2":
        findReview();
            break;
        //case 3 일때는 종료
            case "3":
            return;

    }
    //재귀 호출 사용으로 로직을 간략화 시킴 (로직이 종료된후 다시 Play로 돌아간다)
    play();
}

사용자의 선택에 따라 리뷰를 등록할지 조회할지 종료할지 switch 로 상황을 주었다 

마지막 play(); 이것이 처음 보는 로직인데 재귀 호출이라고 한다 원래 같으면 루프로 돌리거나 해서 다시 일을 수행할 수 있게 만들어 주었는데 기존에는 저렇게 이 리뷰 등록 자체를 호출함으로 상황이 끝나도 다시 시작할 수 있게 만들어 주었습니다 

// 리뷰 조회 로직
   private  void findReview(){
       System.out.println("=======find review========");
      //람다식 정렬 부르는 로직
       ReviewDTO[] reviewDTO = reviewSave.sortByScore();
      //저장된 리뷰기록이 없을때 되돌리는 로직
       for(ReviewDTO review:reviewDTO){
           if(review==null){
               continue;
           }
           System.out.println(review);
       }
   }

ReviewSave에서 만들었던 람다식 정렬을 호출해주고 

 

저장된 리뷰의 기록이 없을때 다시 선택 상황으로 갈 수 있게 continue를 해주었습니다 

 

//리뷰 등록 로직
private void makeReview(){
    System.out.println("----------------");
    //가게 전체 리스트 호출
    StoreDTO[] stores = storeLoader.getStores();
     //가게 번호랑 이름만 전부 호출
    for(StoreDTO store:stores){
        System.out.println(store.getSno()+":"+store.getName());

    }

    int sno = inputItr("가게 번호를 입력하세요");
    int score = inputItr("5점만점에 몇점?");

    ReviewDTO reviewDTO = ReviewDTO.builder()
            .sno(sno)
            .score(score)
            .build();

    int num = reviewSave.add(reviewDTO);
    System.out.println(num+"번 리뷰가 등록되었습니다 ");
    String oper = inputstr("계속하시겠습니까? y/n");

    if(oper.equals("n")){
        return;
    }
    makeReview();
}

ReviewDTO reviewDTO = ReviewDTO.builder()
        .sno(sno)
        .score(score)
        .build();

 

이 코드도 오늘 처음 다룬 빌더입니다 빌더는 생성자 대신해서 사용 가능하며 생성자 같은 경우는 생성하게 되면 모든 내용이 있어야 만들 수 있는 제약이 강한다 빌더는 거기서부터 자유롭습니다 위 상황에서는 빌더를 사용해 사용자에게 

sno , score 만 꺼내와서 보여주고 있습니다 

 

여기서도 마찬가지로 모든 상황이 끝나고 나서 재귀 호출 (makeReview)을 사용해서 다시 시작할 수 있게 만들어 주었습니다 

 

//유저의 입력값을 받아주는 로직들 
    private int inputItr(String msg) {
        int value = Integer.parseInt(inputstr(msg));
        return  value;
    }
    private  String inputstr(String msg){
        System.out.println(msg);
        String value = scanner.nextLine();
        return  value;
    }
}

  마지막으로 유저가 입력하는 값을 받아주는 로직을 만들어 

UI로직도 마무리되었습니다 

 

ReviewUI

import lombok.AllArgsConstructor;
import store.StoreDTO;
import store.StoreLoader;

import java.util.Scanner;

@AllArgsConstructor
public class ReviewUI {
   //유저 입력을 위한 Scanner 호출
    private Scanner scanner;
   //ReviewUI는 ReviewSave 없이는 일할수없다 (의존성이 강함) 그래서 호출
    private ReviewSave reviewSave;
   //사용자에게 전체 가게를 보여주기위해 StoreLoader 을 호출 !!
    private StoreLoader storeLoader;

    //리뷰등록 로직
    public  void play(){
       //사용자의 선택  여기서 inputstr은 밑에 로직으로 구현되어있음
        String oper = inputstr("1.리뷰등록 , 2.조회 , 3.종료");

        switch (oper){
            //case 1 일때는 리뷰 등록 로직을 호출
            case "1":
                makeReview();
                break;
               //case 2 일때는 리뷰 조회 로직을 호출
                case "2":
            findReview();
                break;
            //case 3 일때는 종료
                case "3":
                return;

        }
        //재귀 호출 사용으로 로직을 간략화 시킴 (로직이 종료된후 다시 Play로 돌아간다)
        play();
    }
 // 리뷰 조회 로직
    private  void findReview(){
        System.out.println("=======find review========");
       //람다식 정렬 부르는 로직
        ReviewDTO[] reviewDTO = reviewSave.sortByScore();
       //저장된 리뷰기록이 없을때 되돌리는 로직
        for(ReviewDTO review:reviewDTO){
            if(review==null){
                continue;
            }
            System.out.println(review);
        }
    }
    //리뷰 등록 로직
    private void makeReview(){
        System.out.println("----------------");
        //가게 전체 리스트 호출
        StoreDTO[] stores = storeLoader.getStores();
         //가게 번호랑 이름만 전부 호출
        for(StoreDTO store:stores){
            System.out.println(store.getSno()+":"+store.getName());

        }

        int sno = inputItr("가게 번호를 입력하세요");
        int score = inputItr("5점만점에 몇점?");

        ReviewDTO reviewDTO = ReviewDTO.builder()
                .sno(sno)
                .score(score)
                .build();

        int num = reviewSave.add(reviewDTO);
        System.out.println(num+"번 리뷰가 등록되었습니다 ");
        String oper = inputstr("계속하시겠습니까? y/n");

        if(oper.equals("n")){
            return;
        }
        makeReview();
    }

    //유저의 입력값을 받아주는 로직들
    private int inputItr(String msg) {
        int value = Integer.parseInt(inputstr(msg));
        return  value;
    }
    private  String inputstr(String msg){
        System.out.println(msg);
        String value = scanner.nextLine();
        return  value;
    }
}

 

마지막으로 Main을 만들어주어서 실행만 시켜보면 될 것 같습니다! 

 

import store.StoreLoader;

import java.io.FileNotFoundException;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws FileNotFoundException {
        Scanner scanner = new Scanner(System.in);
        ReviewSave save = new ReviewSave();
        StoreLoader storeLoader = new StoreLoader();
        ReviewUI reviewUI = new ReviewUI(scanner,save,storeLoader);

        reviewUI.play();
    }
}

 이렇게 위에서 설계했던 그림처럼 맛집 데이터와 리뷰 데이터를 연결하여 맛집 리뷰 로직을 만들어 보았습니다 

아직 이해 못 하는 부분도 많아서 만들기는 했지만 이해하기 위해서는 더 많은 반복 봐 공부가 필요할 것 같습니다 

하루하루 엄청난 정보들을 배워가면서 머리가 터질 것 같지만 그만큼 재미도 있는 것 같아 묘~한 기분이 드네요