Wiki Home

1주차

교육생에게 심리적 안정감을 줄 수 있어야 한다. 비난받거나 벌받지 않음을 보장.

학습 테스트. 단위 테스트를 기반으로 기술을 학습할 수 있다.

각 테스트는 독립적이어야 한다. 테스트의 결과가 다른 테스트의 결과에 영향을 줘선 안 된다.

테스트 데이터들을 Test Fixture라고 한다.

일급 컬렉션 을 사용하라.

G25: 매직 넘버는 명명된 상수로 교체하라.

아이템34 int 상수 대신 열거 타입을 사용하라.

아이템50 적시에 방어적 복사본을 만들라.

아이템46 스트림에서는 부작용 없는 함수를 사용하라.

2주차

컨벤션, 포맷팅 지켜라.

hashCode, equals는 클래스 최하단에 구현하는 게 관례다.

엔터 하나도 의미를 갖고 하라.

엔터는 문맥이 달라지는 구분 단위이기 때문에 추후 메서드 추출의 힌트가 된다.

다른 언어에선 불변 변수를 선언할 수 있지만 Java 11이전엔 불가능하기 때문에 final을 잘 써줘야 한다.

setter는 절대 쓰지말고, getter는 안 쓸 때까지 버티다가 정말 어쩔 수 없으면 쓰자. 생성자 잘 쓰라고.

상태에 대한 변경은 그 상태를 가진 객체가 책임을 지도록 해야한다.

setter, getter를 쓰다보면 절차지향적인 방식 코딩하게 된다.

최소한의 assert문을 통해서 모든 케이스를 커버하는 게 중요하다. 경계값을 기준으로 테스트하면 과도한 assert문을 줄일 수 있다. assert문이 너무 많으면 추후 시그니처 변경이 있을 때 노가다가 불가피해진다.

시그니처가 다양한 생성자를 많이 만들어서 써도 된다. 테스트만을 위한 메서드 추가는 뭔가 설계가 잘못된 것이다.

핵심 비지니스 로직을 가지고 있는 모델, 도메인 객체에선 setter, getter를 쓰면 안 되지만, DTO에선 setter, getter가 허용된다. 만약 DTO를 쓰지 않는다면 마지막 UI에 데이터를 넘겨줄 때 도메인 객체의 getter를 쓸 수 밖에 없다.(최소한으로 쓰란 얘기)

private 메서드를 테스트 해야된다면 뭔가 설계 오류일 확률이 높다. bad smell로 받아들이자.

리팩토링은 설계다. 즉, TDD는 설계를 자주하겠다는 얘기.

반드시 실패하는 테스트가 있을 때만 프로덕션 코드에 추가할 수 있다. 필요할 것이라 예상한 것들을 추가하지말 것.

우선 기능 목록 작성에 집중하자.

TDD를 할 때 메서드의 인풋과 아웃풋을 먼저 정하라.

생성자에서 중복 코드는 인자가 많은 쪽이 주생성자로 인자가 적은 쪽에서 호출하는 형태로 가야한다.

getter를 없애보자. 객체의 데이터를 꺼내지말고 메시지를 보내 일을 시켜라.

ValueObject와 DTO는 엄연히 다르다.

작은 단위의 클래스를 만들다 보면 테스트 하기 쉬운 메서드들이 도출된다. 메서드가 작아짐.

과하다 싶을 정도로 극단적으로 쪼개봐라!

인풋과 아웃풋이 명확하게 만들면서 쪼개다 보면 메서드들의 체이닝으로 구현됨. 함수형 스타일처럼 된다. 메서드의 아웃풋이 다른 메서드의 인풋으로 들어가도록.

유효성 검사를 도메인쪽에서 탄탄하게 해야된다. 사용자 입력쪽에선 null체크 등의 최소한만 하도록. 예를 들어, position을 입력받는다면 Position 객체로 감싸면 Position 객체에서 유효성 검사를 하는 것이다.

Pattern을 매번 Compile 하는 건 비싼 행위다. https://bit.ly/2Ux0ZeB

static 사용을 지양해야 되는 이유

3주차

로또 피드백

  • 핵심이 되는 가장 작은 객체를 빨리 찾아서 TDD를 하면 가장 베스트. 그러나 찾기 어렵기 때문에 우리가 찾을 수 있는 가장 큰 객체라도 할 수 있는 부분만이라도 TDD를 해보자.

메서드 분리

  • 레거시 리팩토링 1단계는 메서드 분리를 먼저 해야하고 좋은 이름을 만드는 것.

클래스 분리

  • 인스턴스 변수를 2개까지만 허용해라.
  • 원시값을 포장한 LottoNumeber는 1~45까지 허용하는 유효성 검사의 책임을 가진다.
  • Lotto는 Lotto가 갖는 규칙 자체에 대한 책임을 갖는다.
  • 서로 관련성이 있는 애들끼리 묶는 게 좋은 설계. Lotto, LottoNumber, WinningLotto.
  • private method를 public으로 바꾸기보단 다른 클래스를 만들고 거기로 메서드를 옮겨서 단위 테스트를 하는 걸 고려.

클래스 간의 의존관계 연결

  • Lottos extends ArrayList는 ArrayList가 가진 메서드를 외부에 모두 노출되는 것이 문제점.
  • 상속보단 조합으로 가자.

추가 리팩토링

  • 생성자 대신 정적 팩토리 메서드를 사용하라.
  • mutable object보단 immutable object.

정적 팩토리 메서드

  • API를 사용하는 사용자 입장에서 매우 다양한 형태로 사용 가능하도록 충분히 제공할 것.

불변 객체

  • 무조건 final 필드라고 해서 불변을 보장하진 않음. 해당 객체 내부에 List Collection이 있다면 보장할 수 없음.

인스턴스가 너무 많이 생기는 거 아닌가?

  • 한 사람이 10장 사면 LottoNumber만 60개 + 7 여기에 1만명이 사용한다면? 67만…
  • 캐싱을 적용해 인스턴스 생성을 최소화 할 수 있는 방법이 있는지 검토한다.

사다리 게임

디미터의 법칙 - 옆집 친구랑만 놀아라.

변경되는 부분과 변경되지 않는 부분을 구분하자.

변경이 발생할 가능성이 높은 정책을 인터페이스로 분리하는 게 중요하다. 람다를 쓰는 게 중요한 게 아님.

Java Optional

Optional을 사용하는 이유

if 문을 통한 null 체크는 순식간에 코드를 더럽히고 가독성을 떨어뜨린다. ?. 나 ?: 연산자가 있는 언어는 null을 비교적 안전하게 처리한다. Haskell의 Maybe, Scala의 Option 타입은 값이 있거나 없거나를 함축하여 나타내고 null이란 개념 자체가 없다. 언어의 타입 시스템 자체가 null checking을 강제하는 것이다.

Java8부터 Haskell, Scala에서 영감을 받아서 Optional<T>를 제공한다. Optional은 하나의 값을 가진 컨테이너다. 물론 empty 일 수도 있다.

Optional은 값이 있거나 없는 경우에 대한 처리를 우아하게 할 수 있는 메서드를 가지고 있다. 그리고 값이 없을 때 처리를 어떻게 할지 강제한다. 그래서 의도치 않은 null pointer exception 발생을 막을 수 있다.

중요한 건 Optional은 모든 단일 null 참조를 대체하기 위한 게 아니다. 대신, 메서드의 시그니처를 읽음으로써 선택적인 값을 기대할 수 있는지 알 수 있어서 보다 이해하기 쉬운 API를 디자인하는 것을 목적으로 한다.

flatMap은 map을 사용했을 때 Optional<Optional<SoundCard>>와 같은 이중 Opetional을 Optional<SoundCard>와 같이 단일 스트림으로 만들어 주는 역할이다.

Optional 사용 방법

4주차

“나중은 결코 오지 않는다.” - 르블랑의 법칙

컴파일 에러가 발생하지 않으면서 리팩토링을 해야한다. 레거시 코드 리팩토링의 핵심은 기존 기능을 깨트리지 않으면서 리팩토링하는 것이다.

테스트 케이스는 불안감을 없애주는 만큼 유지하는 게 좋다. 불안하면 많이 만들어라.

언제나 멈춘 상태로 당장 배포해도 문제없는 방식으로 리팩토링하는 게 좋다.

인스턴스 변수의 타입을 변경해도 외부에 그 여파가 전달되지 않는다면 캡슐화를 굉장히 잘한 것이다. 변경의 영향을 해당 클래스 내부에만 미치도록 만들자.

이런 연습은 데이터베이스 테이블 리팩토링에도 도움이 된다.

리팩토링은 모았다가 한번에 하는 게 아닌 시간이 날 때마다 항시 하는것이다.

책임을 찾으면서 역할에 대해 고민을 하면 인터페이스를 도출할 수 있다.

DIP 같은 건 유연한 코드를 만들기 위한 원칙. 사실 Spring과 무관함.

BeanFactory 서로 다른 객체들을 연결하는 연결자.

서비스 레이어의 비지니스 코드를 도메인 객체쪽으로 옮기는 리팩토링을 해야한다.

Mockito를 사용할 땐 when과 반환값이 없을 때 검증하는 verify 메소드를 알아야 한다.

5주차

stackoverflow 의 공개된 database를 import하고 SQL에 대한 의식적인 연습이 가능하다.

TCP/IP도 미션을 통해 연습이 가능하다.

HTTP도 웹서버 구현을 통해 연습이 가능하다.