일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 큐 자바 코드
- 서비스 vs 쓰레드
- 안드로이드 라이선스
- rxjava hot observable
- 안드로이드 레트로핏 crud
- 안드로이드 라이선스 종류
- 안드로이드 유닛 테스트
- 안드로이드 os 구조
- 클래스
- 서비스 쓰레드 차이
- 스택 큐 차이
- Rxjava Observable
- android ar 개발
- 자바 다형성
- 멤버변수
- jvm 작동 원리
- ANR이란
- 안드로이드 레트로핏 사용법
- 객체
- 안드로이드 유닛테스트란
- rxjava disposable
- jvm이란
- android retrofit login
- 플러터 설치 2022
- 2022 플러터 설치
- ar vr 차이
- 2022 플러터 안드로이드 스튜디오
- 안드로이드 유닛 테스트 예시
- rxjava cold observable
- 스택 자바 코드
- Today
- Total
목록책/Effective Kotlin (53)
나만을 위한 블로그
아래 코드처럼 프로퍼티, 파라미터가 같은 이름을 가질 수 있다. 이렇게 되면 지역 파라미터가 외부 스코프에 있는 프로퍼티를 가린다. 이를 섀도잉(shadowing)이라고 부른다. 이런 코드는 많이 사용된다. 개발자들도 문제가 있으면 쉽게 찾을 수 있는 부분이라 어떤 경고도 발생시키지 않는다. class Forest(val name: String) { fun addTree(name: String) { // ... } } 이런 섀도잉 현상은 클래스 타입 파라미터와 함수 타입 파라미터 사이에서도 발생한다. 개발자가 제네릭을 제대로 이해하지 못할 때 이와 관련된 다양한 문제들이 발생한다. 이건 심각한 문제가 될 수 있고 개발자가 스스로 문제를 찾기도 힘들다. interface Tree class Birth: T..

아규먼트로 함수에 값을 전달할 수 있는 것처럼 타입 아규먼트를 사용하면 함수에 타입을 전달할 수 있다. 타입 아규먼트를 사용하는 함수(즉 타입 파라미터를 갖는 함수)를 제네릭 함수라고 부른다. 대표적인 예로는 stdlib의 filter()가 있다. filter()는 타입 파라미터 T를 갖는다. inline fun Iterable.filter( predicate: (T) -> Boolean ): List { val destination = ArrayList() for (element in this) { if (predicate(element)) { destination.add(element) } } return destination } filter()의 람다 표현식 내부에서 컴파일러가 아규먼트가 컬렉션의 ..
코틀린은 코드 재사용과 관련해서 프로퍼티 위임이라는 기능을 제공한다. 프로퍼티 위임을 쓰면 일반적인 프로퍼티의 행위를 추출해 재사용할 수 있다. 대표적인 예로 지연 프로퍼티가 있다. lazy 프로퍼티는 이후에 처음 사용하는 요청이 들어올 때 초기화되는 프로퍼티를 의미한다. 일반적으로 대부분의 언어(자바스크립트 등)에서는 필요할 때마다 복잡하게 구현해야 하지만 코틀린에선 프로퍼티 위임을 활용해 간단하게 구현할 수 있다. 코틀린의 stdlib는 lazy 프로퍼티 패턴을 쉽게 구현할 수 있게 lazy 함수를 제공한다. val value by lazy { createValue() } 프로퍼티 위임을 쓰면 이외에도 변화가 있을 때 이를 감지하는 observable 패턴을 쉽게 만들 수 있다. 목록을 출력하는 리스..
많은 개발자는 같은 알고리즘을 여러 번 반복해서 구현한다. 여기서 말하는 알고리즘은 수학적 연산, 수집 처리처럼 별도의 모듈 또는 라이브러리로 분리할 수 있는 부분을 말한다. 복잡한 알고리즘도 있겠지만 아래처럼 숫자를 특정 범위에 맞추는 간단한 알고리즘도 있을 수 있다. val percent = when { numberFromUser > 100 -> 200 numberFromUser 0 else -> numberFromUser } 이 알고리즘은 stdlib의 coerceIn 확장 함수로 이미 존재한다. 그래서 따로 구현하지 않아도 된다. val percent = numberFromUser.coerceIn(0, 100) 이렇게 의미 있는 것을 활용하면 단순하게 코드가 짧아진다는 것 이외에도 다..
프로젝트에서 이미 있던 코드를 복사해서 붙여넣고 있다면 뭔가가 잘못된 것이다 '실용주의 프로그래머' 책에선 'Don't Repeat Yourself'라는 규칙을 'DRY 규칙'으로 표현한다. WET 안티패턴이란 이름으로 아는 사람도 있을 것이다. DRY는 또한 SSOT(Single Source of Truth)란 이름으로도 알려져 있다. 많은 개발자가 결국 같은 얘기를 하고 있는 것이다. 그런데 너무 자주 하는 이야기라 오용 또는 남용되고 있다. 이 규칙을 확실하게 적용하려면 이 이야기가 언제 왜 나오는지 이해해야 한다. 그리고 이걸 이해하려면 간단한 이론을 알아야 한다. knowledge 프로그래밍에서 knowledge는 넓은 의미로 '의도적인 정보'를 뜻한다. 프로젝트를 진행할 때 정의한 모든 게 k..
코틀린 문서의 Coding Convensions을 보면 코틀린은 잘 정리된 코딩 컨벤션을 갖고 있다. 이런 컨벤션이 모든 프로젝트에 최적인 것은 아니지만 코틀린 커뮤니티에 속한 사람이라면 이런 컨벤션을 최대한 지키는 게 좋다. 이걸 지켜야 어떤 프로젝트를 접해도 쉽게 이해할 수 있다 다른 외부 개발자도 프로젝트의 코드를 쉽게 이해할 수 있다 다른 개발자도 코드 작동 방식을 쉽게 추측할 수 있다 코드를 병합하고 한 프로젝트의 코드 일부를 다른 코드로 이동하는 게 쉽다 코틀린 개발자라면 문서에 설명된 컨벤션에 익숙해져야 한다. 컨벤션은 시간이 지나면서 조금씩 변화할 수 있다. 컨벤션을 지킬 때 도움이 되는 2가지 도구가 있다. 인텔리제이 포매터 : 공식 코딩 컨벤션 스타일에 맞춰 코드를 바꿔 준다 ktlin..
코드에서 아규먼트의 의미가 명확하지 않은 경우가 있다. val text = (1..10).joinToString("I") joinToString()에 대해 알고 있다면 "|"이 구분자라는 걸 알 것이다. 하지만 모른다면 접두사로 생각할 수도 있다. 파라미터가 불명확한 경우에는 이를 직접 지정해서 명확하게 만들 수 있다. 아래 코드처럼 이름 있는 아규먼트를 사용하면 된다. val text = (1..10).joinToString(separator = "I") 또는 아래처럼 변수를 써서도 의미를 명확하게 할 수 있다. val separator = "|" val text = (1..10).joinToString(separator) 이름 있는 파라미터를 쓰면 더 신뢰할 수 있다. 변수명을 쓰는 방법도 개발자 의..
코틀린의 프로퍼티는 자바의 필드와 비슷해 보이지만 서로 완전히 다른 개념이다. var name: String? = null String name = null 데이터를 저장한다는 건 같다. 하지만 프로퍼티엔 더 많은 기능이 있다. 기본적으로 프로퍼티는 사용자 정의 게터, 세터를 가질 수 있다. var name: String? = null get() = field?.toUpperCase() set(value) { if (!value.isNullOrBlack()) { field = value } } field는 프로퍼티의 데이터를 저장해 두는 backing field에 대한 레퍼런스다. 이런 backing field는 게터, 세터의 디폴트 구현에 쓰이므로 따로 만들지 않아도 디폴트로 생성된다. val을 써서 ..
뭔가를 더 자세하게 설명하기 위해 명시적으로 긴 코드를 쓸 때가 있다. 대표적으로 함수, 프로퍼티를 지역 또는 톱레벨 변수가 아닌 다른 리시버로부터 가져온다는 걸 나타낼 때가 있다. 클래스의 메서드라는 걸 나타내기 위한 this가 그 예시다. class User: Person() { private var beersDrunk: Int = 0 fun drinkBeers(num: Int) { // ... this.beersDrunk += num // ... } } 비슷하게 확장 리시버(확장 메서드에서의 this)를 명시적으로 참조하게 할 수도 있다. 비교를 위해 일단 리시버를 명시적으로 표시하지 않은 퀵소트 구현을 확인한다. fun List.quickSort(): List { if (size < 2) retu..
코틀린은 개발자가 타입을 지정하지 않아도 타입을 지정해서 넣어주는 수준 높은 타입 추론 시스템을 갖고 있다. val num = 10 val name = "Marcin" val ids = listOf(12, 111, 554, 2982) 이는 개발 시간을 줄여줄 뿐 아니라 유형이 명확할 때 코드가 짧아지므로 코드 가독성이 크게 향상된다. 하지만 유형이 명확하지 않을 때는 남용하면 좋지 않다. val data = getSomeData() 위 코드는 타입을 숨기고 있다. 가독성을 위해 코드를 설계할 때 읽는 사람에게 중요한 정보를 숨겨선 안 된다. '코드를 읽으면서 함수 정의를 보며 타입을 확인하면 되지 않나?' 라고 생각할 수 있지만 이는 곧 가독성이 떨어진다는 의미다. 또한 코드 정의로 쉽게 이동할 수 없는..