728x90
item19 : knowledge를 반복하여 사용하지 말라
프로젝트에서 이미 있던 코드를 복사해서 붙여넣고 있다면, 무언가가 잘못된 것이다
knowledge가 뭘까
- 넓은 의미로 의도적인 정보
비즈니스 로직
또는공통 알고리즘
- 로직은 시간에 따라 변활 수 있다
왜 반복해서 쓰면 안되는데
- 프로그래밍에서 유일하게 유지되는 것은 "변화한다는 속성"
- knowledge가 반복되면 변화에 취약하다.
- 이는 프로젝트의 scalable을 제한하고, fragile하게 한다.
- 반복되는 부분을 추출하여 재사용성을 높임으로써 해결
이건 반복이 아니에요 추출멈춰
- 반복처럼 보이는데 사실 알고보니 짜잔 다른 knowledge였습니다
- 2개의 안드로이드 프로젝트에서 빌드 설정이 비슷하다고 추출하면 안됨
- 어떻게 판단하지 그럼
- 비즈니스 규칙이 다른 곳(소스)에서 왔는지 확인
- SRP 단일 책임 원칙을 따른다
SRP 단일 책임 원칙
- 두
actor
가 같은 클래스를 변경하는 일은 없어야한다.actor
: 변화를 만들어 내는 존재 (source of change)
- SRP로 부터 알 수 있는 것.
- 서로 다른 곳에서 사용하는 knowledge는 독립적으로 변경할 가능성이 높다
- 다른 knowledge는 분리하는 것이 좋다 (개발자를 유혹함)
item20 : 일반적인 알고리즘을 반복해서 구현하라
이미 구현된 알고리즘을 활용하면
- 코드 작성이 빨라짐
- 함수의 이름만 보고 동작 유추 가능
- 실수를 줄일 수 있다
- 간단 알고리즘은 stdlib 대부분 구현되어 있다
커스텀 유틸 만들기
- 동일한 결과를 얻는 함수를 여러번 만드는건 멋지지 않아
- 따라서 자신이 만들라는게 있는지 찾아보도록 하자
- 유틸을 만들어 추출해내는 방법에는 여러가지(top-level 함수, 프로퍼티 위임, 클래스 등)가 있는데 그 중 여러모로 확장함수가 좋다. 왜?
- 함수는 상태가 없으므로 행위를 나타내기 좋다
- top-level 함수에 비해 타입을 제한할 수 있다.
- arg로 받아 쓰는 것 보다 가독성에 좋다
- 자동완성 기능 활용 가능해서 찾기 쉽다
item21 : 일반적인 프로퍼티 패턴은 프로퍼티 위임으로 만들어라
프로퍼티 위임이란
- 다른 객체의 메서드를 활용해서 프로퍼티의 접근자를 만드는 방식
프로퍼티 위임은
- 프로퍼티의 동작을 추출해서 재사용할 수 있다.
- 프로퍼티 패턴을 활용하면 다양한 패턴을 만들 수 있다.
- EX ) lazy 프로퍼티 / observable
- 코틀린에서 간단하고 type-safe하게 구현할 수 있다.
코틀린으로 구현하기
private class LoggingProperty<T>(
varvalue:T
) {
operator fun getValue(
thisRef: Any?,
prop: KProperty<*>
): T {
print("${prop.name} returned value $value")
return value
}
operator fun setValue(
thisRef: Any?,
prop: KProperty<*>,
newValue: T
) {
val name = prop.name
print("$name changed from $value to $newValue")
value = newValue
}
}
getValue
와setValue
를 정의한다.getValue
와setValue
가 여러개 있어도 context에 따라 다르게 사용 가능
item22 : 일반적인 알고리즘을 구현할 때 제네릭을 사용하라
제네릭 함수는
- type arg를 가지는 함수를 제네릭 함수라고 한다.
- 컴파일러에 타입 관련 정보를 제공해 타입을 더 정확하게 추측할 수 있게 함
- 컴파일 과정에서 타입 정보는 사라지지만 개발중에 특정 타입을 강제할 수 있다.
제네릭 제한하기
- supertype 지정하기
fun <T: Comparable<T>> Iterable<T>.sorted() : List<T>
- Any로 Non-nullable
fun <T, R: Any> Iterable<T>.mapNotNull() : List<R>
item23 : 타입 파라미터의 섀도잉을 피하라
섀도잉 shadowing이란
- 프로퍼티와 파라미터가 같은 이름을 가진다면?
- local 파라미터가 클래스의 프로퍼티를 가림
- 이를 섀도잉이라고 한다.
- 타입 파라미터에서도 일어나는 현상
interface Tree
class Birch: Tree
class Spruce: Tree
class Forest<T: Tree> {
fun <T: Tree> addTree(tree: T) { ... }
}
그러니까 이름 다르게 쓰세요~~ 라고 하심
item24 : 제네릭 타입과 variance 한정자를 활용하라
Invariant 불공변성, Covariant 공변성, Contravariant 반병성
- Invariance 불공변성
A
가B
의 서브타입일 때 ,Box<A>
와Box<B>
는 아무런 관련성이 없음
- Covariant 공변성
A
가B
의 서브타입일 때 ,Box<A>
가Box<B>
의 서브타입이다.
- Contravariant 반변성
A
가B
의 서브타입일 때 ,Box<A>
가Box<B>
의 슈퍼타입이다.
variance 한정자 in
& out
class Cup<T>
class Cup<in T>
class Cup<out T>
- 제네릭 타입에서
- 기본적으로 invariance 불공변성
in
: covariant 공변성을 나타냄out
: contravariant 반변성을 나타냄
- 함수 타입에서
- 코틀린의 모든 함수 파라미터 타입은 contravariant 반변성 (out)
- 코틀린의 모든 함수 리턴 타입은 covariant 공변성 (in)
variance 한정자의 안정성
- 자바의 배열은 covariant -> 명백한 결함이 존재한다.
Interger[] numbers = {1, 2, 3, 4} Object[] objects = numbers objects[2] = "B"
- 따라서 코틀린에서는 invariant한 Array를 사용
IntArray
,CharArray
,BooleanArray
등
- Immutable Collection (List, Set)은 convariant(out)
- 변경 불가능 하기에 convariant해도 문제 없음
- 반대로 mutable Collection은 위 Array 문제와 같이 invariant
variance 한정자의 위치
- 클래스와 인터페이스 선언부
class Box<out T>(val value: T)
- 클래스와 인터페이스를 시용하는 위치
val boxAny: Box<out Any> = Box<String>("Str")
728x90
'Kotlin' 카테고리의 다른 글
[이펙티드 코틀린] 4장 🖼️ 추상화 설계 Abstraction Design (item 26..32) (0) | 2023.06.28 |
---|---|
[이펙티브 코틀린] 2장 👀 가독성 Readability (item 11..18) (0) | 2023.06.18 |
[이펙티트 코틀린] 1장 🏰 안정성 Safety (item 01..10) (0) | 2023.06.18 |