일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 2022 플러터 설치
- 서비스 쓰레드 차이
- android retrofit login
- ANR이란
- 안드로이드 유닛 테스트 예시
- rxjava disposable
- 객체
- rxjava hot observable
- 안드로이드 레트로핏 사용법
- 안드로이드 라이선스
- ar vr 차이
- 멤버변수
- 안드로이드 레트로핏 crud
- 큐 자바 코드
- 2022 플러터 안드로이드 스튜디오
- 클래스
- Rxjava Observable
- android ar 개발
- 서비스 vs 쓰레드
- 자바 다형성
- jvm이란
- rxjava cold observable
- 안드로이드 라이선스 종류
- jvm 작동 원리
- 플러터 설치 2022
- 안드로이드 os 구조
- 스택 자바 코드
- 안드로이드 유닛 테스트
- 안드로이드 유닛테스트란
- 스택 큐 차이
- Today
- Total
목록책/Effective Kotlin (53)
나만을 위한 블로그
클라이언트가 클래스의 인스턴스를 만들게 하는 가장 일반적인 방법은 기본 생성자(primary constructor)를 쓰는 것이다. fun main() { val list = MyLinkedList(1, MyLinkedList(2, null)) } class MyLinkedList( val head: T, val tail: MyLinkedList? ) 하지만 생성자가 객체를 만들 수 있는 유일한 방법은 아니다. 디자인 패턴으로 다양한 생성 패턴들이 만들어져 있다. 일반적으로 이런 생성 패턴은 생성자를 객체로 직접 생성하지 않고 별도의 함수를 통해 생성한다. 예를 들어 아래 코드의 톱레벨 함수는 MyLinkedList 클래스의 인스턴스를 만들어서 제공한다. fun main() { val list = myL..
규약은 개발자들의 단순한 합의다. 따라서 한쪽에서 규약을 위반할 수도 있다. 기술적으로 모든 부분에서 이런 규약 위반이 발생할 수 있다. 예를 들어 아래처럼 리플렉션을 활용하면 원하는 걸 열고 사용할 수 있다. import kotlin.reflect.full.declaredMemberFunctions import kotlin.reflect.jvm.isAccessible class Employee { private val id: Int = 2 override fun toString(): String = "User(id = $id)" private fun privateFunction() = println("Private function called") } fun callPrivateFunction(emplo..
아이템 27에서 확인했던 메시지 출력 함수를 다시 확인한다. fun Context.showMessage( message: String, duration: MessageLength = MessageLength.LONG ) { val toastDuration = when (duration) { MessageLength.SHORT -> Toast.LENGTH_SHORT MessageLength.LONG -> Toast.LENGTH_LONG } Toast.makeText(this, message, toastDuration).show() } enum class MessageLength { SHORT, LONG } 메시지 출력 방법을 자유롭게 바꿀 수 있게 함수로 추출했다. 하지만 문서화가 잘 돼 있지 않다. 다른..
작은 인터페이스는 배우기 쉽고 유지하기 쉽다. 기능이 많은 클래스보단 적은 클래스를 이해하는 게 쉽고 유지보수하기도 쉽다. 일반적으로 어떤 수정을 가하기 위해선 클래스 전체를 이해하고 있어야 한다. 보이는 요소 자체가 적다면 유지보수하고 테스트할 게 적다. 변경을 가할 때는 기존의 것을 숨기는 것보다 새로운 것을 노출하는 게 쉽다. 일반적으로 공개적으로 노출된 요소들은 공개 API의 일부고 외부에서 사용할 수 있다. 따라서 이런 요소들은 이미 외부에서 쓰이고 있을 것이다. 그래서 이런 요소들을 변경하면 이 코드를 쓰는 모든 부분이 영향을 받는다. 가시성 관련 제한을 변경하는 건 더 어렵다. 따라서 처음에는 작은 API로서 개발하도록 강제하는 것이 더 좋을 수 있다. 클래스의 상태를 나타내는 프로퍼티를 외..
API 설계자가 안전하지 않다고 하거나 API 설계자가 안전하다고 해도 우리가 그걸 신뢰할 수 없다면 그 API는 불안정한 것이다. 이런 불안정한 API를 과도하게 사용하는 것은 굉장히 위험하다. 어쩔 수 없이 이런 API를 써야 한다면 최대한 로직과 직접 결합시키지 않는 게 좋다. 그래서 많은 프로젝트가 잠재적으로 불안정하다고 판단되는 외부 라이브러리 API를 랩해서 사용한다. 랩해서 사용하면 아래와 같은 자유, 안정성을 얻을 수 있다. 문제가 있다면 wrapper만 바꾸면 되므로 API 변경에 쉽게 대응 가능하다 프로젝트 스타일에 맞춰서 API 형태를 조정할 수 있다 특정 라이브러리에서 문제가 발생하면 wrapper를 수정해서 다른 라이브러리를 쓰도록 코드를 쉽게 바꿀 수 있다 필요한 경우 쉽게 동작..
프로그래밍에서도 안정적이고 최대한 표준적인 API를 선호한다. 주요 이유는 아래와 같다. API가 바뀌고 개발자가 이를 업데이트했다면 여러 코드를 수동으로 업데이트해야 한다. 많은 요소가 이 API에 의존하고 있다면 큰 문제가 된다. 변경에 대응하거나 다른 대안을 찾는 건 어렵다. 특히 다른 개발자가 API를 사용한 경우에는 익숙하지도 않아 더 어려울 것이다. 라이브러리의 작은 변경은 이를 활용하는 다른 코드들의 많은 부분을 변경하게 만들 수 있다. 그래서 라이브러리가 바뀌어도 이전 라이브러리를 유지하는 경우가 많다. 하지만 그럴수록 점점 업데이트가 어려워지고 버그, 취약성 등이 발생할 수 있다. 오래된 라이브러리는 더 이상 지원되지 않을 수도 있다. 따라서 개발자가 안정적인 라이브러리로 업데이트하는 걸..
함수, 클래스 등의 추상화로 실질적인 코드를 숨기면 사용자가 세부사항을 알지 못해도 괜찮다는 장점이 있다. 그리고 이후에 실질적인 코드를 원하는 대로 수정할 수도 있다. 예를 들어 정렬 알고리즘을 함수로 추출하면 이를 쓰는 코드에 어떤 영향도 주지 않고 함수 성능을 최적화할 수 있다. 자동차 제조업체와 엔지니어는 자동차 내부의 원하는 걸 마음대로 바꿀 수 있다. 작동만 제대로 된다면 사용자는 뭐가 바뀐지 전혀 모를 것이다. 여기선 추상화를 통해 변화로부터 코드를 보호하는 행위가 어떤 자유를 가져오는지 확인한다. 가장 간단한 추상화인 상수부터 알아본다. 상수 리터럴은 아무것도 설명하지 않는다. 따라서 코드에서 반복 등장할 때 문제가 된다. 이런 리터럴을 상수 프로퍼티로 변경하면 해당 값에 의미있는 이름을 ..
개발자 관점에서 컴퓨터에서 가장 낮은 추상화 계층은 하드웨어다. 개발자는 일반적으로 프로세서를 위한 코드를 작성하므로, 하드웨어 위의 관심 있는 계층은 프로세서 제어 명령이다. 이런 프로세서 제어 명령은 원래 0, 1로 이뤄지지만 이를 쉽게 읽을 수 있게 일대일로 대응된 어셈블리라는 언어로 표현한다. 하지만 어셈블리어로 프로그래밍하는 건 굉장히 어렵고, 오늘날 우리가 쓰는 것과 같은 앱을 만드는 것은 상상도 할 수 없다. 프로그래밍을 간단하게 할 수 있게 엔지니어는 한 언어를 다른 언어(일반적으로 낮은 레벨 언어)로 변환하는 프로그램인 컴파일러를 만들었다. 최초의 컴파일 언어는 어셈블리어로 작성됐으며 텍스트로 작성된 코드를 어셈블리 명령어로 변환했다. 그리고 최초의 컴파일 언어는 더 나은 프로그래밍 언어..
기업이 한 플랫폼만을 대상으로 앱을 만드는 경우는 없다. 기업은 일반적으로 둘 이상의 플랫폼을 대상으로 하는 제품을 만들기 원하며 요즘 대부분 기업의 제품, 서비스는 여러 플랫폼에서 돌아가고 있다. 네트워크 호출을 통해 통신하는 클라이언트, 서버 앱을 생각해라. 두 앱은 서로 소통하므로 재사용할 수 있는 부분이 많을 것이다. 다른 플랫폼에 동일한 제품을 구현한다면 재사용할 수 있는 부분이 많을 것이다. 특히 비즈니스 로직 부분들은 거의 동일하다. 따라서 소스코드를 공유할 수 있다면 큰 이득이 발생할 것이다. 풀스택 개발 일반적으로 웹 사이트를 제품으로 사용하며 백엔드 애플리케이션(서버 측)이 필요하다. 웹 사이트 개발에선 자바스크립트 이외의 선택지는 없을 정도로 독점적으로 사용되고 있다. 백엔드에서 가장..
아래 제네릭 클래스가 있다고 가정한다. class Cup 위 코드에서 타입 파라미터 T는 variance 한정자(out 또는 in)가 없기 때문에 기본적으로 invariant(불공변성)이다. invariant라는 건 제네릭 타입으로 만들어지는 타입들이 서로 관련성이 없다는 의미다. 예를 들어 Cup, Cup, Cup, Cup은 어떤 관련성도 갖지 않는다. class Cup fun main() { val anys: Cup = Cup // 오류. Type mismatch val nothings: Cup = Cup() // 오류. Type mismatch } 만약 어떤 관련성을 원한다면 out 또는 in이란 variance 한정자를 붙인다. out은 타입 파라미터를 covariant(공변성)로 만든다. 이는 ..