목록Book/Effective Kotlin (8)
시배's Android
아이템49. 하나 이상의 처리 단계를 가진 경우에는 시퀀스를 사용하라 sequence 는 지연(lazy) 처리 된다. 따라서 시퀀스 처리 함수들을 사용하면, 데코레이터 패턴으로 꾸며진 새로운 시퀀스가 리턴된다. 시퀀스 처리 함수는 최정 연산이 이루어지기 전까지는 각 단계에서 연산이 일어나지 않는다. Iterable 은 처리 함수를 사용할 때마다 연산이 이루어져 List 가 만들어진다. 컬렉션 처리 연산은 호출할 때 연산이 이루어진다. 시퀀스의 지연 처리 장점 자연스러운 처리 순서를 유지 최소한만 연산 무한 시퀀스 형태로 사용 각각의 단계에서 컬렉션을 만들어 내지 않는다. 시퀀스가 빠르지 않은 경우 컬렉션 전체를 기반으로 처리해야 하는 연산은 시퀀스를 사용해도 빨라지지 않는다. sorted 는 Sequen..
아이템45. 불필요한 객체 생성을 피하라 Int 와 같은 기본형을 사용하면, 일반적으로 기본 자료형 int 로 컴파일 된다. 하지만 nullable 로 만들거나, 타입 아규먼트로 사용할 경우에는 Integer 로 컴파일 된다. 기본 자료형은 null 일 수 없고, 타입 아규먼트로도 사용할 수 없기 때문이다. 객체 생성 비용은 항상 클까? 현대 64비트 JDK 에서 객체는 8바이트의 배수만큼 공간을 차지한다. 앞부분 12바이트는 헤더로서 반드시 있어야 하므로, 최소 크기는 16바이트이다. 추가로 객체에 대한 레퍼런스도 공간을 차지한다. 일반적으로 레퍼런스는 -Xmx32G 까지는 32/64비트 플랫폼 모두 4바이트다. 64비트 플랫폼에서는 32G(-Xmx32G)부터는 8바이트이다. 캐시를 활용하는 팩토리 함..
36. 상속보다는 컴포지션을 사용하라 상속은 관계가 명확하지 않을 때 사용하면, 여러 가지 문제가 발생할 수 있습니다. (‘is-a’ 관계에서 사용) class ProfilerLoader { fun load() { // 프로그래스 바를 보여 줌 // 프로파일을 읽어 들임 // 프로그레스 바를 숨김 } } class ImageLoader { fun load() { // 프로그래스 바를 보여 줌 // 이미지를 읽어 들임 // 프로그레스 바를 숨김 } } 상속을 이용하면 위의 코드를 아래와 같이 시용할 수 있습니다. abstract class LoaderWithProgress { fun load() { // 프로그래스 바를 보여 줌 innerLoad() // 프로그래스 바를 숨김 } abstract fun i..
아이템 33. 생성자 대신 팩토리 함수를 사용하라 클라이언트가 클래스의 인스턴스를 만들게 하는 가장 일반적인 방법은 기본 생성자(Primary constructor)를 사용하는 방법이다. class MyLinkedList{ val head : T val tail : MyLinkedList? } val list = MyLinkedList(1, MyLinkedList(2, null)) 하지만 생성자가 객체를 만들수 있는 유일한 방법은 아니다. 헬퍼 클래스를 생각해보자. fun myLinkedListOf( ): MyLinkedList? { if(elements.isEmpty()) return null val head = elements.first() val elementsTail = elements. copy..
아이템26. 함수 내부의 추상화 레벨을 통일하라 계층이 잘 분리되면 무엇이 좋을까요? 어떤 계층에서 작업할 때 그 아래의 계층은 이미 완성되어 있으므로, 해당 계층만 생각하면 된다는 것입니다. 즉, 전체를 이해할 필요가 없어지는 것입니다. 추상화 레벨 높은 레벨로 갈수록 물리 장치로부터 점점 멀어집니다. 프로그래밍에서는 일반적으로 높은 레벨일수록 프로세서로부터 멀어진다고 표현합니다. 높은 레벨일수록 걱정해야 하는 세부적인 내용들이 적습니다. 높은 레벨일수록 단순함을 얻지만, 제어력을 잃습니다. 예를 들어 C언어는 메모리 관리를 직접 할 수 있습니다. 반면, 자바는 가비지 컬렉터가 자동으로 메모리를 관리해 줍니다. 추상화 레벨 통일 함수도 높은 레벨과 낮은 레벨을 구분해서 사용해야 한다는 원칙이 있습니다...
아이템19. knowledge를 반복하여 사용하지 말라 knowledge는 넓은 의미로 의도적인 정보를 뜻합니다. 프로젝트를 진행할 때 정의한 모든 것이 knowledge입니다. 알고리즘의 작동 방식, UI의 형태, 우리가 원하는 결과 등이 모두 의도적인 정보이며, knowledge입니다. 로직 : 프로그램이 어떠한 식으로 동작하는지와 프로그램이 어떻게 보이는지 공통 알고리즘 : 원하는 동작을 하기 위한 알고리즘 둘의 가장 큰 차이점은 시간에 따른 변화입니다. 비즈니스 로직은 시간이 지나면서 계속해서 변하지만 콩통 알고리즘은 한 번 정의된 이후에는 크게 변하지 않습니다. knowledge도 계속해서 변한다. 회사가 사용자의 요구 또는 습관을 더 많이 알게 되었다. 디자인 표준이 변화했다. 플랫폼, 라이브..
아이템11. 가독성을 목표로 설계하라 // 구현 A if (person != null && person.isAdult) { view.showPerson(person) } else { view.showError() } // 구현 B person?.takeIf { it.isAdult } ?.let(view::showPerson) ?. view.showError() 가독성이란 코드를 읽고 얼마나 빠르게 이해할 수 있는지를 의미합니다. 구현 A는 수정하기 쉽습니다. 구현 A는 디버깅도 더 간단합니다. 기본적으로 인지부하를 줄이는 방향으로 코드를 작성해야한다. 극단적이지 않기 let으로 인해서 예상하지 못한 결과가 나올 수 있다. (view.showPerson 에서 nullable을 리턴하는 경우) let은 절대..
가변성을 제한하라 상태를 적잘하게 관리해야한다. 프로그램을 이해하고 디버그하기 힘들어집니다. 가변성이 있으면, 코드의 실행을 추론하기 어려워집니다. 멀티스레드 프로그램일 때는 적절한 동기화가 필요합니다. 테스트하기 어렵습니다. 상태변경이 일어날 때, 이러한 변경을 다른 부분에 알려야 하는 경우가 있습니다. val lock = Any() var num = 0 for ( i 1..1000) { thread { Thread.sleep(10) synchronized(lock) { num += 1 } } } Thread.sleep(1000) print(num)가변성은 생각보다 단점이 많아서 이를 완전하게 제한하는 프로그래밍 언어도 있습니다. 바로 순수 함수형 언어입니다. 코틀린에서 가변성 제한하기 읽기 전용 프로..