TDD
- TDD 는 개발 방법론이자 철학, Development
TDD 로 구현할 기능 찾기
-=–
시작하기
- 퍼블릭 클래스!
- 요구 사항 분석을 통한 기능 목록 작성
- 객체 설계를 통해 어느 부분부터 구현을 시작할 것인지 결정
기능 목록
- 구매할 Lotto의 매수 구하기
- 1000 -> 1
- 1500 -> 1
- 500 -> error
- 한장의 Lotto 생성
- 당첨 번호 생성
- 정상적인 당첨 번호 입력
- 유효하지 않은 당첨 번호
- 한 장의 Lotto에 대한 당첨 결과 구하기
- n장의 Lotto에 대한 당첨 결과 구하기
- Lotto 결과에 따른 수익률 구하기
- …
TDD로 구현할 기능 찾기
- 구현 중간 부분을 자르는 연습을 해야 한다.
- 로또 구매 금액을 전달하면 구매할 수 있는 로또의 장수를 반환한다.
- 구매한 로또와 당첨 번호를 넣으면 당첨 결과를 반환한다.
- 당첨 결과를 입력하면 당첨금 총액을 반환한다.
- 당첨 금액과 구매 금액을 넣으면 수익률을 반환한다.
- 구현 중간 부분을 자른다는 것은 로또 구현에 필요한 메서드를 찾는 과정이다.
- 메서드를 자르는 과정
=============================
Lotto
번거로움들이 테스트를망설이게 하는 가장 큰 이유 테스트를 위해서 프로덕션코드가 변경되는것은 좋지 않다
- 그렇다고 mock, Reflection API 같은거를 쓰지말자
프라이빗 메서드를 테스트하고싶은 욕망은, 클래스 분리의 신호를 나타내는것이다 요구사항을 보고 기능요구사항을 분리하는게 » 클래스를 찾고 퍼블릭 메서드를 를 찾고,
의존관계
- 자바에서 : import 를 하는것
- 다른 클래스를 알고있는 범위!
- 클래스 간의 의존 관계를 어떻게 연결 할 것인가
- 상속 : is-a 관계 , is a kind of 관계
- 조합 : has-a 관계
상속
- 역사적 배경 : 펌웨어를 만들기 위해서 만들어진게 Java 인데, 그때는 용량이 작아야했다. Ram Disk 모두!
- 그래서 코드 재사용이 미덕임
- 옜날 안드로이드는 전체 메서드 수가 제한이 있었음. 메서드의 수가 65000개 (2^@@ 개) 넘어가면 앱이 빌드가 안되었음
- 코드 재사용을 위한 강력한 수단이 상속임!
- 문제
- 상위 클래스의 잘못된 코드 한줄이, 건드리지도 않은 하위 클래스의 에러를 유발 할 수 있다
리스코프 치환 원칙 위반
- 한방설명 : 이렇게 작동할줄 알았는데, 이렇게 작동하지 않고 다르게 작동하네?
- 객체가 어떤 상황에 협력하냐에 따라 다르다
open class TextFile {
fun length(): Int {
return content().size
}
open fun content(): ByteArray {
// 문서의 내용을// 바이트 배열로 로드한다
}
}
class EncryptedTextFile:TextFile() {
override fun content(): ByteArray {
// 문서를 로드해서,// 즉시 복호화하고,// 복호화한 내용을 반환한다.
}
}
//문제는 : length() >> 평문의 사이즈를 받길 원했는데, 암호문의 사이즈를 받는 LSP 위배가 발생함
LSP 위배 코드
- addAll 이 6이 나오는 이슈 » 3이 나오는 상황
올바른 상속이란
- abstract class 만 있는것
- 정제하는것만이 유일한 상송
자바/코틀린의 생성자
- JVM 생성자의 한계 : 일단 생성자가 호출되면 새로운 힙 영역이 할당되는것을 막을 수 없음 » 동등성은 통과, 동일성은 아님
- kotest : shouldBeSameInstanceAs 키워드로 검증 할 수 있음
- (정적)팩토리메서드 사용시 » 동등성을 챙길수 있고, 새로운 초기화를 하지 않음. 그래서 동일성도 챙김
========
<잘 못들음>
=========
DSL : 도메인 특화 언어
- 범용 프로그래밍 언어(java, python) 와는 다름
- DSL
- 세부 실행은 언어를 해석하는 엔진에 맡긴다.
- 코틀린DSL
- DSL 단점을 보완하기 위한 DSL
DSL 학습 테스트코드
@Test
fun lastChar() {
val actual = lastChar("Kotlin")
}
// 일반 함수
fun lastChar(s:String) : Char = s.get(s.length-1)
// 확장 함수
fun String.lastChar() : Char = this.get(this.length -1 )
- 확장함수개념!