본문 바로가기

개발 이야기/CC-Java

[2주차] 로또게임 - Step2. Merge 후 최종 피드백 반영하기

 - 7월에 교육 마치면서, 이것 저것 일정이 겹친 덕분에 이제서야 소스코드 머지 된 것을 반영하고 다음 단계로 넘어간다. 

 step3로 넘어가기 전에 리뷰어님의 리뷰를 최대한 반영했다. 개인적으로 소스코드가 마음에 안들어서 확..뒤집고 싶지만 일단 점진적으로 바꿔보자는 말씀에 그러기로 했다. 

 

 - 리뷰어님이 말씀주신 개선 할 점은 두 가지로 하기에 그 내용과 해결과정을 정리해 두었다.

1
2
3
4
5
6
7
8
9
 public static Set<List<Integer>> purchasedLottos(int lottoCount) {
    Set<List<Integer>> collectAutoLotto = new HashSet<>();
    while (collectAutoLotto.size() < lottoCount) {
         List shuffleLottoNumbers = generateAutoLotto();
         collectAutoLotto.add(new ArrayList<>(shuffleLottoNumbers));
     } 
    
     return collectAutoLotto;
 }

1. 해당 코드 중 List 부분을 Class로 빼내기

- 결국, 일급콜렉션을 쓰라는 것과 일맥상통하는 이야기 같다. 

- Set<List<Integer>> 처럼.. 특정 자료형 안에 또 어떤 자료형을 넣는게 굉장히 보기싫다..

- 분리하고 싶지만 어떻게 분리해야하는 걸까?

- class로 나도 빼고 싶은데, 방법을 모르겠다..

- 본 포스팅 내용과 소스코드는 [점프 투 자바 - 클래스] 편을 바탕으로 포스팅 함. ( 클릭하면 사이트 이동 )


List<Integer> 부분을 class로 빼냈다.. 이게 이소리였구나..

1
2
3
4
5
6
7
8
9
10
11
12
public class Lotto {
 
    static final int LOTTO_NUMBER_MIN = 1;
    static final int LOTTO_NUMBER_MAX = 45;
 
 
    private List<Integer> lotto;
 
    public Lotto (List<Integer> lotto) {
        this.lotto = new ArrayList<>(lotto);
    }
}

▶이렇게 Lotto.java 의 클래스를 만들고, 하기 LottoGenerator.java에서 사용했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class LottoGenerator {
 
// 소스코드 중략..
 
    public static Set<Lotto> purchasedLottos(int lottoCount) {
       Set<Lotto> collectAutoLotto = new HashSet<>();
 
        while (collectAutoLotto.size() < lottoCount) {
            List<Integer> shuffleLottoNumbers = generateAutoLotto();
            collectAutoLotto.add(new Lotto(shuffleLottoNumbers));
        }
        return collectAutoLotto;
    }
 
    private static List<Integer> generateAutoLotto() {
        Collections.shuffle(standardLotto);
        List<Integer> shuffleLottoNumbers = standardLotto.subList(06);
        Collections.sort(shuffleLottoNumbers);
 
        return shuffleLottoNumbers;
    }
}
 

 


1) 클래스

- java class 파일을 만들면 클래스 생성 된 것 아닌가?  

: 클래스의 선언만 있고 내용이 없기 때문에, 껍데기만 있는 클래스를 생성한 것이다.

(cat이라는 객체가 없으면 Animal 이라는 클래스는 껍데기)

- 하지만, 이 껍데기가 있어야 객체를 만들 수 있다.

1
2
3
4
public class Animal {
    
    Animal cat = new Animal();
}

- cat이라는 객체가 없으면 Animal 이라는 클래스는 껍데기

- Animal cat = new Animal(); : new는 객체를 생성할 때 사용하는 키워드이다. 이 코드로 Animal 클래스의 인스턴스인 cat이 생성된다. 즉, Animal의 객체가 만들어 진다.

cat + @ 객체와 인스턴스

cat 은 객체다.

cat 은 Animanl의 인스턴스이다.

cat은 Animal 클래스의 인스턴스이다.

 Animal이라는 클래스 안에 다양한 동물 객체들을 만들 수 있다.

Animal monkey = new Animal();

Animal rabbit = new Animal();

...

- 클래스에 의해서 만들어진 객체를 인스턴스라고도 한다. (객체 ≒ 인스턴스)

- 인스턴스: 특정 객체가 어떤 클래스의 객체인지 관계 위주로 설명할 때 사용한다. 하기 표현을 예로 어떤 표현이 더 적합한지 참고하자. (부등호 방향 = 더 적합한 표현)

 cat 은 인스턴스 <<< cat 은 객체

 cat 은 Animal의 인스턴스 >>> cat 은 Animal의 객체

 

2) 객체 변수( Instance Variable )

-  Animal이라는 껍데기 클래스를 좀 더 발전시켜 보자

- Animal 클래스에 의해 만들어지는 동물들에 이름을 지어주자.

1
2
3
public class Animal {
    String name;
}

- String name 처럼 클래스에 선언 된 변수를 객체 변수라고 부른다. (= 인스턴스 변수, 멤버변수, 속성)

- 클래스에 의해 생성 되는 것은 객체, 그리고 그 클래스에 선언 된 변수는 객체 변수라고 생각하면 쉽다.

- 객체.객체변수 : 객체 변수는 도트연산자(.)을 이용하여 접급 할 수 있다. (예: cat.name;)

1
2
3
4
5
6
7
public class Animal {
    String name;
    public static void main(String[] args) {
        Animal cat = new Animal();
        System.out.println(cat.name); // 대입한 값이 없으므로, 실행 시 null 출력
    }
}
 

 

객체 변수는 공유되지 않는다. 객체 변수의 값은 독립적으로 유지 된다.

- 아래 코드에서 cat과 dog의 name은 각각 boby, happy로 다름을 알 수 있다. 즉, name이라는 객체변수는 공유되지 않는다는 것을 알 수 있다. 이것은 객체 변수의 값이 독립적으로 유지됨을 보여주는 것이다. 이 점이 클래스의 존재 이유다.

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
   Animal cat = new Animal();
   cat.setName("boby");
 
   Animal dog = new Animal();
   dog.setName("happy");
 
   System.out.println(cat.name);
   System.out.println(dog.name);
}
 

 

▶여기까지 했다면? 객체변수에 접근하는 방법/ 값이 할당 되어 있지 않은 상태에 대해서 알게 되었다.


3) 메소드 

- 객체 변수에 값을 대입하는 방법 중 하나.

- 클래스 내에 구현된 함수.

- Animal 클래스의 객체 변수인 name 에 값 대입해 보기

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Animal {
    String name;
 
    public void setName(String name) {
        this.name = name;
    }
 
    public static void main(String[] args) {
        Animal cat = new Animal();
cat.setName("boby");
        System.out.println(cat.name);
    }
}
 

- cat.setName("boby"); 객체가 메소드를 호출하기 위해서는 '객체.메소드' 로 호출 가능하다.

- this.name = name  ▶ cat.name = "boby"; 나 마찬가지다. 

- this는 Animal 클래스에 의해서 생성된 객체를 지칭한다.


1
2
3
4
5
6
7
8
9
public class LottoApplication {
 
    // 소스코드 중략..
 
    int[] winningNumbers = inputWinningNumbers();
    List<Integer> resultMatcing = Lotto.lotteryStatics(purchasedLottos, winningNumbers);
 
    // 이하 생략
}

2. '이펙티브자바 아이템 28. 배열보다는 리스트를 사용하라' 를 참고하여, 리팩토링하기

- winningNumbers를 배열이 아닌 리스트로 사용하란 이야기

- 그럼 winningNumber랑 연계 된 다른 메소드까지 쫙 바꿔주어야 한다. 

- 배열보다 리스트를 사용하라고 권고하는 이유는 뭘까? 하기 링크를 참고하면 좋다

https://github.com/ryudung/effective-java3-E/tree/master/src/test/java/ch05/item28

https://sjh836.tistory.com/171

대충 내용을 요약하자면, 리스트를 쓰면 타입의 안정성을 얻을 수 있고, 컴파일 단계에서 오류를 쉽게 발견할 수 있다.


1번 해결시간보다는 덜 걸렸고, 애초에 입력받을 때 Array로 받기 때문에 입력받고 값을 넘겨주는 부분에서 수정 할 수 밖에 없었다.

- scanner 로 입력받음 -> trim을 이용해서 값을 쪼개어 저장하는 형식이 입력값에 대한 처리를 가장 수월하게 하는 방법이라 생각

- 더 유용한 방법이 있을 수 있지만 로또 프로그램의 전체적인 그림에서 값 입력 처리부분이 핵심 코드가 아니므로.. 여기에 시간을 많이 할애하지 않기로 했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static ArrayList<Integer> inputWinningNumbers1() {
  System.out.println("지난 주 당첨 번호를 입력해 주세요.");
  String[] inputWinningNumbers = scan.nextLine().split(",");
  String[] trimWinningNumbers = new String[LottoGenerator.WINNING_NUMBERS_LENGTH];
  for (int i = 0; i < LottoGenerator.WINNING_NUMBERS_LENGTH; i++) {
      trimWinningNumbers[i] = inputWinningNumbers[i].trim();
  }
  InputValidationCheck.checkWinningNumberLength(trimWinningNumbers);
  InputValidationCheck.checkOverlapWinningNumber(trimWinningNumbers);
  int[] winningNumbers = InputValidationCheck.checkWinningNumberRange(trimWinningNumbers);
  Arrays.sort(winningNumbers);
 
  // 추가한 소스코드 
  ArrayList<Integer> inputWinningNumberList = new ArrayList<>();
  for(int i = 0; i < LottoGenerator.WINNING_NUMBERS_LENGTH; i++)  {
      inputWinningNumberList.add(winningNumbers[0]);
  }
  return inputWinningNumberList;
}
 

 

* ArrayList와 List 차이 알아두기