[우아한테크코스] 7일차 TIL
4 minute read
오늘 배운 것
- 자동차 경주 게임 제이슨 피드백
- 제이슨의 라이브코딩
- 자동차 경주 게임 리뷰어 피드백의 피드백
- 내가 피드백을 통해 검색하고 배운 것
내일 할 일
- 2단계 pr 보내기
TIL
- 자동차 경주 게임 제이슨 피드백
- 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인지 확인하자.
- 제이슨의 라이브코딩 (내 코드에 적용해보기)
- 확실한 통과하는 테스트를 짜면서 테스트 가능한 클래스를 늘려간다.
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를 적극 활용하자
- 리뷰어의 피드백의 피드백
- .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를 줘”
- 내가 찾은 것
- trim: 문자열의 시작과 끝에 있는 공백을 제거해준다.
String foo = " hi ";
foo = foo.trim(); //"hi"
- 인스턴스 변수의 접근 제한자가 private으로 하는게 왜 좋은가?
- 프로그램의 어느 부분이 변수를 변경할 수 있는지 제어할 수 있다.
- 언제든지 내부 표현을 변경할 수 있다.
- 인스턴스 변수의 수를 최소화해야하는 이유?
- 객체의 복잡도를 높아지는 것이다.
- 버그의 발생 가능성이 높아진다.
- (내 생각) 불변의 인스턴스 변수가 아니라면, 조작이 쉬워진다. 단일 책임이 위반될 가능성이 크다.
- 클래스 변수의 단점?
- static을 사용한다는 것은 객체 지향적이지 않은 요소가 있다는 것이다. 공유하는 변수가 존재한다는 것부터 책임이 애매해지기 때문이다.
- gc애 의해 회수되지 않는 static 변수는 메모리 소모이고, 너무 많은 static 변수는 메모리 부족이 생길 것이다.
- 함수의 재사용성이 떨어진다. 인터페이스에도 사용될 수 없기 때문이다.