[우아한테크코스] 7일차 TIL

4 minute read

오늘 배운 것

  1. 자동차 경주 게임 제이슨 피드백
  2. 제이슨의 라이브코딩
  3. 자동차 경주 게임 리뷰어 피드백의 피드백
  4. 내가 피드백을 통해 검색하고 배운 것

내일 할 일

  1. 2단계 pr 보내기

TIL

  1. 자동차 경주 게임 제이슨 피드백
    • Code convention, format 맞추기: 이름을 통해 의도를 드러내라
      추상화된 이름이 더 좋을 것이다. randomNumber라고 명시한 순간 사용자는 randomNumber만 넣어야하는줄 안다.
      • 패키지명도 이해하기 쉽도록 하자.
      • car의 입장에서는 넘겨 받는 인자가 randomNumber인지 알 필요 없다.
    • 상수 값은 static final, 대문자로 이름 작성
    • 구현 순서는 상수, 클래스 변수, 인스턴스 변수, 생성자, 메서드 순
    • 공백 라인을 의미있게 문맥을 분리할 때 사용하자.
      그래야지 여러 공백이 들어오면 여러 일을 하구있구나, 분리해야할까? 알 수 있다.
    • space는 ctrl+alt+L 로 관리. 패키지 누르고 하면 패키지내 전부 정렬
    • 변수 이름에 자료형을 사용하지 않도록 한다(list, string)
    • Final 키워드를 사용해 값의 변경을 막아라
      최근에 등장하는 프로그래밍 언어들(ex 코틀린)의 추세는 기본이 불변 값이다.
      최대한 final로 값의 변동을 막도록 하자.
      final인 곳에 final을 사용하는 것을 습관화하자.
    • 객체의 상태 접근을 제한한다 인스턴스 변수의 접근 제한자는 private으로 구현한다.
    • 객체를 객체스럽게 사용하라
      car가 변수로 가진 name과 position에 대해서 조작할 일이 있으면 car가 하도록 해야한다.
      데이터를 가지는 객체가 일하도록 한다
    • 단위 테스트하기 어려운 코드르 단위 테스트하기 move에 인자값을 넘겨서 테스트할 수 있도록.. 인터페이스를 사용해 테스트할 수 있다.
    • 인스턴스 변수의 수를 최소화한다 decorator field?? 굳이 불필요한 인스턴스 변수를 만들지 말자.
    • Setter 메서드 사용을 자제하자 인스턴스를 초기화한 후에 값을 변경할 수 있는 setter를 생성하지 말고 생성자를 사용해 초기화하고 바퀴가 있는 자동차를 만들자
    • 비즈니스 로직과 UI 로직의 분리 domain 안에서 값을 만들어주면 view의 요구사항이 바뀜에 따라 view가 아닌 domain을 수정해야하는 부분이 생긴다. 또한 domain에게 출력이라는 책임까지 지우게 되는 것이다.
    • Collection 활용 로직 처리 성능은 자바 api가 좋다. 이런게 없나? 싶으면 찾아보는게 좋다.
    • 어느 부분을 테스트할 것인가? 마음이 편해질때까지, 경곗값을 기준으로 테스트한다.
    • 테스트 픽스처(test fixture) 생성 테스트를 반복적으로 수행할 수 있게 도와주고 매번 동일한 결과를 얻을 수 있게 도와주는 ‘기반이 되는 상태나 환경’을 조성하도록 한다. 테스트의 인스턴스 변수 또는 클래스에 대역들을 생성해서 조성한다.
      @BeforeEach는 각 테스트에서 중복으로 사용하는 테스트 픽스처만 적용한다.
    • 테스트에서 특정 상태를 만들기 위한 반복 코드 지양 하나의 관심사만 테스트하도록.. 그에 맞게 메서드를 추가할 수도 있다.
      테스트는 문서처럼 읽기 편하고 명확하게 작성해야한다.
    • Getter 메서드 핵심 비지니스 로직을 구현하는 도메인 객체에서 데이터 전달을 사용하는 경우인 dto의 경우에는 허용할 수 있지만 최대한 사용하지 않도록..
    • 테스트를 위한 코드는 구현 코드에서 분리되어야 한다 생성자와 메서드는 구분해서 보지만, 편의를 위한 메서드가 구현 코드에 있어서는 안된다.
    • Private 메서드를 테스트하지 못하는데 하고 싶다면? public 메서드를 통해서 검증할 수 있다! 정 필요한데 그 메서드가 왜 private인지 확인하자.
  2. 제이슨의 라이브코딩 (내 코드에 적용해보기)
    • 확실한 통과하는 테스트를 짜면서 테스트 가능한 클래스를 늘려간다.
      move(인자전달)로 0123은 정지, 4~9는 이동
    • 주 생성자 내에서 this(name, 0)을 이용해 부 생성자의 호출
      메서드가 많아지는 것은 단일 책임 원칙을 위반할 수 있지만, 생성자의 추가는 사용성이 커진다고 볼 수있다. 생성자는 최소한의 유효성 검증과 값 검증만 하도록 해야한다. 그보다 일이 많아지면 factory 생성이 나을 것이다.
      주 생성자는 모든 변수를 초기화한다.
    • 원시값을 포장하라
      테스트하기 쉬워진다. 책임을 분리할 수 있다. 포장한 클래스의 사용이 보장된다.
    • equals(), hashCode()의 오버라이딩을 이용해 서로 다른 클래스가 사실은 가진게 일치한다면 일치함을 뱉어내 테스트할 수 있다. equals()와 hashCode()는 불변 객체에서 필수가 된다.
    • move할 때 position이 move하면 value를 +1한 position을 새롭게 만들어서 대체하도록 한다. 그럼 final inte value로 불변 객체가 되고, 불변 객체의 이점이 메모리에 대한 걱정보다 훨씬 클 것이다.
    • 매번 호출할 것 같은 new Position(0)을 상수화하여 같은 인스턴스가 되도록 캐싱한다. 이것은 final을 이용해 불변이 보장되기 때문에 할 수 있는 것이다.
    • 일급컬렉션을 만들자
      내가 만든 List<>에 대해서 할 수 있는 거를 제한하고, 보장되므로 외부에서 함부로 사용할 수없도록 한다. 이때 toList(), toSet()을 이용해 cars를 뱉어낼 수 있다.
      만약에 add, remove 이런걸 하고 싶으면 불변을 하지 않아도 된다.
    • 방어적 복사
      생성자 내에서 this.cars = new ArrayList<>(car); 로 하는것.
      주소를 공유하기 때문에 Final List cars = new ArrayList<>(); final List actual = new ArrayList<>(cars); Cars.add(new Car(“Jason”)); assertThat(cars).isEmpty(); 이 통과하지 못한다. 따라서 연결을 끊어버리는 방어적 복사를 하는 것이다. unmodifiableList()는(add, remove 이런거를 제한할 뿐) 이를 할 수 없다. 받을 때와 내보낼 때 모두 방어적 복사를 할 수 있다. 멀티쓰레딩을 하는 환경에서 중요할 수밖에 없다.
    • getter를 사용해야한다면 객체에 메시지를 보내는 것을 고민하자
      .getCar().getPosition()일 바에 car에게 메시지, position에게 메시지를 보내는 메서드를 만들어주자. 타고타고 가는..
    • 오직 테스트 코드만을 위한 생성자를 만드는 것에 대해서 생성자는 사용자에게 클래스에 대한 보장을 해주기 위함임을 기억하자. 그런데 클라이언트가 악용하는 경우가 우려된다면 dto를 생성하자
    • Integer.max(a, b)로 큰 값을 돌려주는 것처럼 api를 적극 활용하자
  3. 리뷰어의 피드백의 피드백
    • .getCar().getNames()와 같이 구현하는 것 보다 Cars 안에 아래와 같이 구현할 수 있다.
        public List<String> getCarNames() {
        List<String> names = new ArrayList();
        for (Car car : this.cars) {
            names.add(car.getName());
        }
        return names;
       }
      
    • view와 domain은 분리되어 있는 layer인데 view에서 변화가 필요하다고 (-를 +로 바꾸는 것과 같은) domain에 변화를 주어야하는 경우를 잘 생각하자(domain의 toString()같은 것의 위험성)
    • 중복되는 출력문의 경우 상수로 관리하고, 에러메시지의 경우 무조건 상수화하고, 자주 사용될 경우 클래스까지 만드는 것을 고려하자
    • 테스트는 문서처럼 봐야하니 메서드명을 영어로 잘 짓고 displayName을 활용하자
    • 객체끼리 서로서로 소통하도록 하자 “Cars야 너가 가진 Car 중에 Winner를 줘”
  4. 내가 찾은 것
    • trim: 문자열의 시작과 끝에 있는 공백을 제거해준다.
       String foo = " hi ";
       foo = foo.trim(); //"hi"
      
    • 인스턴스 변수의 접근 제한자가 private으로 하는게 왜 좋은가?
      1. 프로그램의 어느 부분이 변수를 변경할 수 있는지 제어할 수 있다.
      2. 언제든지 내부 표현을 변경할 수 있다.
    • 인스턴스 변수의 수를 최소화해야하는 이유?
      1. 객체의 복잡도를 높아지는 것이다.
      2. 버그의 발생 가능성이 높아진다.
      3. (내 생각) 불변의 인스턴스 변수가 아니라면, 조작이 쉬워진다. 단일 책임이 위반될 가능성이 크다.
    • 클래스 변수의 단점?
      1. static을 사용한다는 것은 객체 지향적이지 않은 요소가 있다는 것이다. 공유하는 변수가 존재한다는 것부터 책임이 애매해지기 때문이다.
      2. gc애 의해 회수되지 않는 static 변수는 메모리 소모이고, 너무 많은 static 변수는 메모리 부족이 생길 것이다.
      3. 함수의 재사용성이 떨어진다. 인터페이스에도 사용될 수 없기 때문이다.