Fact
- 오늘은 프로그래머스 레밸 2 짜리 3문제를 풀었다. 올바른 괄호, 다음 큰 숫자, 주식가격. javaScript로 올바른 괄호, 다음 큰 숫자를 풀고 나머지는 java로 풀었다. 셋 다 레벨 25 TDD로 자동차 경주게임 구현 동영상을 보면서 TDD를 하는 방법을 봤다.
Feelings
- tdd 고것은 너무나 어려운것
- 동영상 시청 후에 느낀건 내가 완벽한 tdd는 안하고 있었다.
Findings
- tdd 할려고 노력해야함. testcode 보다 production code를 먼저 짜게 될때가 있음. 이것을 방지하기 위해서 페어로 프로그래밍하던가 옆에 인형 놓고 인형이랑 얘기하면서 해야함.
메소드 분리를 해야 하지만 인덴트 1 유지하게 됨.
클래스 분리 연습
- 모든 원시값과 문자열을 포장한다
- 줄여쓰지 않는다(축약 금지)
- 일급 콜렉션을 쓴다.
의미 있는 이름
-
의도를 분명히 밝혀라
- 좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 더 많다.
- 그러므로 이름을 주의 깊게 살펴 더 나은 이름이 떠오르면 개선하기 바란다. 그러면 (자신을 포함해) 코드를 읽는 사람이 좀더 행복해진다.
- 따로 주석이 필요하다면 분명히 드러내지 못했다는 소리다.
-
그릇된 정보를 피하라
- 프로그래머는 코드에 그릇된 단서를 남겨서는 안된다. 그릇된 단서는 코드 의미를 흐린다.
- 서로 흡사한 이름을 사용하지 않도록 주의한다.
- 유사한 개념은 유사한 표기법을 사용한다.
-
의미 있게 구분하라
- 컴파일러나 인터프리터만 통과할려는 생각으로 코드를 구현하는 프로그래머는 스스로 문제를 일으킨다.
- 연속적인 숫자를 덧붙인 이름(a1,a2,…,aN) 덧붙이거나 불용어(Info, Data, a ,an, the)를 추가하는 방식은 적절하지 못하다. 이름이 달라야 한다면 의미도 달라져야 한다.
-
인터페이스 클래스와 구현 클래스
-
인터 패이스 이름은 접두어를 붙이지 않는 편이 낫다고 생각한다.
- IShapeFactory(인터페이스), ShapeFactory(구현 클래스) 구조로 이름을 짓는 것은 좋은 선택은 아니다.
- 오히려 인터페이스를 ShapeFactory로 이름을 짓고 구현 클래스의 의도를 드러낼 수 있는 이름을 짓는 것을 추천한다.
-
-
클래스 이름
- 클래스 이름과 객체 이름은 명사나 명사구가 적합하다.
- Customer, WikiPage, Account, AddressParser 등이 좋은 예다.
- Manager,Processor, Data, Info 등과 같은 단어는 피하고, 동사는 사용하지 않는다.
-
메소드 이름
- 메소드 이름은 동사나 동사구가 적합하다.
- postPayment, deletePage, save 등이 좋은 예따.
- 접근자, 변경자, 조건자는 자바 빈 표준에 따라 값 앞에 get, set, is를 붙인다.
- 생성자를 중복해 정의할 때는 정적 팩토리 메소드를 사용한다. 메소드를 인수를 설명하는 이름을 사용한다.(생성자가 여러 개 일때 가령 변수가 달라서… 그러면 그 생성자의 의도가 잘 들어 나지 않아서 팩토리 메소드를 쓰기도 한다 )(인스턴스를 new 키워드로 생성하는게 아니라 생성자를 private로 만들고 static method 를 제공해서 인스턴스 생성을 강제하는게 정적 팩토리 메소드를 활용해서 인스턴스 메소드를 생성하는거. )
-
개념 하나에 단어 하나를 사용하라
- 추상적인 개념 하나에 단어 하나를 선택해 이를 고수한다.
- 일관성 있는 어휘는 코드를 사용할 프로그래머가 반갑게 여길 선물이다.
production code: 실제 구현해서 사용자에게 가치를 주는 서비스 코드, 프로그램 구현을 담당하는 부분으로 사용자가 실제로 사용하는 소스코드
testcode는 프로덕션 코드가 정상적으로 동작하는지를 확인하는 코드
TDD = TFD(Test First Development) + 리팩토링.
테스트 코드, 프로덕션 코드 추가 할때마다 리팩토링을 실시한다.
리펙토링은 설계이다. 설계를 자주 하겠다는 이야기다. 테스트 케이스 추가할때 마다 리팩토링을 하는게 핵심이다.
TDD란 프로그래밍 의사결정과 피드백 사이의 간극을 의식하고 이를 제어하는 기술이다.
Tdd의 아이러니 중 하나는 테스트 기술이 아니라는 점이다. TDD는 분석 기술이며, 설계 기술이기도 하다.
TDD를 하는 이유
- 디버깅 시간을 줄여준다.
- 동작하는 문서 역할을 한다.
- 변화에 대한 두려움을 줄여준다.
TDD 사이클 Test fail => Test passes => Refactor => Test Fail => …
위의 사이클에 서 production code를 넣는 시점은 Test fail이 일어날 때 production code를 넣는다. 태스트가 실패 하기 때문에 production code에 무엇인가 추가한다. 이 원칙이 중요하다. 필요할거야 해서 미리 구현하는건 TDD원칙을 깬다.
요구사항 분석 및 설계
- 요구사항 분석을 통해 대략적인 설계 - 객체 추출
- UI, DB 등과 의존관계를 가지지 않는 핵심 도메인 영역을 집중 설계
test 연습 할 시에 controller, view 보다는 일단 domain을 집중적으로 tdd로 작성 하면서 연습해야한다.
또한 테스트 하기 힘든것 가령 random 값 생성등을 밖으로 뺀다.
구현할 기능 목록 작성하는것도 중요함. 연습이 많이 필요하다.
구현할 기능 목록 작성하는게 막막하면
- 테스트 없이, 객체 설계도 안하고, 기능 목록을 분리도 안한 채로 일단 구현.
- 구현함으로써 도메인 지식을 쌓는다.
- 구현한 모든 코드를 버린다.
- 구현 목록 다시 작성
- 기능 목록 중 가장 만만한 녀석 부터 TDD로 구현 시작.
- 복잡도가 높아져 리팩토링 하기 힘든 상태가 되면 버린후 재시작.
레거시 코드 리팩토링 하는게 버리고 다시 작성 하는것 보다 배로 걸린다.
DI spring에서 의존성 주입 ????
대표적으로 어려운 테스트 하기 어려운 코드
-
내부 API
- Random, shuffle, 날짜
-
외부 세계
- 외부 REST API
- 데이터베이스 API
얘들을 interface를 통해서 격리를 시킨다. 이 interface를 주입한다. 이게 바로 의존성 주입이다.
equals method???? 넣으면 잘된다? 36 alt + insert 쇼트커트.
//given
코드
//when
코드
//then
코드
으로 나누는것도 리펙토링이다. 주석 다는것도 연습용으로 좋다.
stream으로 indent 줄이지 말것
getter method은 쓰지 말것. 보이면 없애야 한다고 봐야한다. 가져와서 쓰는게 아니라 값을 보내서 메세지를 보내듯이 뭐 해달라고 한 결과값을 받아오는것.
ctrl + alt + m 메서드로 추출.
다른 클래스에서 메서드를 쓰지 않게 하기 위해서 default로 만든다 ( public 를 지운다. 왜 private로 안하지??)
Future Action
- tdd 연습 과제에서 막 빨리하는 게 아니라 이것저것 해보면서 어떤 설계가 좋을지도 느끼고 이런저런 실험해서 공부하는 게 목적이다. 나는 그냥 대충 빨리 끝내기 위해서 했는데 다음에는 천천히 이런저런 장난을 치면서 공부하도록 하자.