본문 바로가기
728x90

공부158

아이템 17 - 이름 있는 아규먼트를 사용하라 코드에서 아규먼트의 의미가 명확하지 않는 경우가 있다. 예를들어 다음과 같은 코드이다. val text = (1..10).joinToString { "|" } "|" 가 무엇을 의미하는지는 joinToString 대해서 이미 알고 있다면 이것이 구분자(separator) 를 의미한다는 것을 알 것이다. 하지만 모른다면 접두사로 생각할 수도있을것이다. 명확하지 않는 경우 이를 직접 지정해서 명확하게 만들어 줄 수 있다 val text2 = (1..10).joinToString(separator = "|") 또는 val seperator = "|" val text3 = (1..10).joinToString(seperator) 또는 val test4 = (1..10).joinToString(separator .. 2024. 4. 10.
아이템 16 - 프로퍼티는 동작이 아니라 상태를 나타내야 한다 코틀린의 프로퍼티는 자바의 필드와 비슷해 보이지만, 사실 서로 완전히 다른 개념입니다. 둘 다 데이터를 저장한다는 점은 같습니다. 하지만 프로퍼티에는 더 많은 기능이 있습니다. 일단 기본적으로 프로퍼티는 사용자 정의 세터와 게터를 가질 수 있습니다. class User { var name: String = "initial name" get() = field // getter에서 백킹 필드에 접근 set(value) { field = value // setter에서 백킹 필드에 값을 할당 } } 위 코드에서 setter 에 name = value 를 하지않지 않고 field를 사용한 이유와 백킹필드란? 백킹필드 프로퍼티의 값을 저장하는 데 사용되는 내부적인 필드 코틀린에서는 프로퍼티의 값을 저장하고 검색할.. 2024. 4. 8.
아이템 15 - 리시버를 명시적으로 참조하라 리시버? 확장 함수나 확장 속성, 또는 수신 객체 람다에서 대상이 되는 객체를 의미한다 확장 함수나 속성을 호출할 때, 그 앞에 오는 객체가 바로 리시버 객체이다. 수신 객체 지정 람다에서는 람다 내부에서 사용 가능한 컨텍스트 객체를 가리킨다. 확장 함수: 특정 타입의 객체에 대해 호출되며, 그 타입의 객체가 리시버 수신 객체 지정 람다: applu, run, with, also, let 같은 함수는 모두 리시버 객체를 가지며, 람다 내부에서 직접 호출할 수 있다. fun User.printInfo() { println("Name: $name, Age: $age") // 확장 함수 내에서 'this' 생략 가능 } val user = User("injin Jeong", 10).apply { name = .. 2024. 4. 7.
아이템 14 - 변수 타입이 명확하지 않는 경우 확실하게 지정하라 코틀린은 개발자가 타입을 지정하지 않아도, 타입을 지정해서 넣어 주는 굉장히 높은 수준의 타입 추론 시스템을 갖추고 있다. 이는 개발 시간을 줄여 줄 뿐만 아니라, 유형이 명확할 때 코드가 짧아지고 가독성이 크게 향상된다 하지만 유형이 명확하지 않을 때는 남용하면 좋지 않다. val data = getSomeDate() 위의 코드는 타입을 숨기고 있으며 코드를 설계할 때 읽는 사람에게 중요한 정보를 숨겨서는 안된다. 코드를 읽으면서 함수 정의를 보며 타입을 확인하면 되지 않나? 라고 생각할 수 있지만, 이는 곧 가독성이 떨어진다를 의미한다 타입을 지정해 주면, 코드를 훨씬 쉽게 읽을 수 있다 아이템3, 아이템4 를 참고해보자 생각: 요즘 ide 가 훌륭해서 크게 생각은 안해봤지만 요즘에는 함수를 들어가서.. 2024. 4. 7.
아이템 13 - Unit? 을 리턴하지 말라 Boolean 의 true, false 를 갖는 것처럼 Unit? 은 Unit 또는 null 이라는 값을 가질 수 있다. 따라서 Boolean 과 Unit? 타입은 서로 바꿔서 사용할 수 있다. 위 방법대로 Unit? 을 Boolean 을 표현하는 것은 예측하기 어려운 코드를 만들 수 있다. 따라서 Boolean 을 사용하는 형태로 변경하는 것이 좋다. 기본적으로 Unit? 을 리턴하거나, 이를 기반으로 연산하지 않는 것이 좋다. 언제 Unit? 을 사용할까? Unit? 을 사용하는 경우는 매우 드물다. Unit 은 자바의 void 와 유사한 개념이며, 묵시적으로 모든 함수에서 반환된다 Unit? 을 사용하는 것이 권장되지 않는 이유는 해당 타입이 함수가 때때로 아무것도 하지 않는 상태를 null 로 표.. 2024. 4. 7.
아이템 12 - 연산자 오버로드를 할 때는 의미에 맞게 사용하라 연산자 오버로딩은 굉장히 강력한 기능이지만, 위험할 수 있다 의미가 명확하지 않다면, infix 를 활용한 확장 함수를 사용하는 것이 좋다. 일반적인 이항 연산자 형태처럼 사용할 수 있다 infix 함수 규칙 매개변수가 반드시 필요하고, 하나의 매개변수만 가져야 합니다. infix 함수는 멤버 함수 또는 확장 함수여야 합니다. infix 함수는 suspend 될 수 없습니다(코루틴과 관련 있는 경우). // infix 함수 예시 - 1 @Test fun `p80_1`() { println("Hello".appendExclamation()) // "Hello!" println("Hello" add "World") // "Hello World" } fun String.appendExclamation(): S.. 2024. 4. 7.
아이템 11 - 가독성을 목표로 설계하라 프로그래밍은 쓰기보다 읽기가 중요하다는 의미 항상 가독성을 생각하면서 코드를 작성하자 가독성 이란 코드를 읽고 얼마나 빠르게 이해할 숙 있는지를 의미 인식 부하 감소 가독성은 사람에 따라 다르게 느낄 수 있지만, 일반적으로 많은 사람의 경험화 인식에 대한 과학으로 만들어진 어느정도의 규칙이 있다 우리의 뇌가 얼마나 많은 관용구(구조, 함수, 패턴)에 익숙해져 있는지에 따라 다르다. 익숙하지 않은 구조를 사용하면, 잘못된 동작을 코드를 보면서 확인하기 어렵다 기본적으로 '인지 부하'를 줄이는 방향으로 코드를 작성하자. class Item11Class( var name: String? = null, ) { var innerClass: Item11Class? = null fun printName() { if .. 2024. 4. 7.
아이템 10 - 단위 테스트를 만들어라 단위 테스트의 중요성은 널리 알고 있고, 이미 다들 하고 있는거라 읽고 넘어 감. 코드를 안전하게 만드는 가장 궁극적인 방법은 다양한 종류의 테스트를 하는 것 단위 테스트는 일반적으로 다음과 같은 내용을 확인한다 일반적인 use case 요소가 사용될 거라고 예상되는 일반적인 방법을 테스트 일반적인 오류 케이스와 잠재적인 문제 제대로 동작하지 않을 거라고 예상되는 일반적인 부분, 과거에 문제가 발생했던 부분 등을 테스트 엣지 케이스와 잘못된 아규먼트 Int 의 경우 Int.MAX_VALUE 를 사용하는 경우, nullable 의 같은경우 null 값으로 채워진 객체 등 피보나치 수는 양의정수로만 구할 수 있지만 음의 정수 등을 넣으면 아규먼트 자체가 잘못된 것 등을 테스트 회귀 테스트? 이미 검증된 코드.. 2024. 4. 7.
아이템 9 - use 를 사용하여 리소스를 닫아라 더 이상 필요하지 않을때, close 메서드를 사용해서 명시적으로 닫아야 하는 리소스가 있다 InputStream / OutputStream java.sql.Connection java.io.Reader java.new.Socket / java.uti.Scanner 등등 이러한 리소스들은 AutoCloseable 을 상속받은 Closeable 인터페이스를 구현하고 있다.이러한 모든 리소스는 최종적으로 리소스에 대한 레퍼런스가 없어질 때, 가바지 컬렉터가 처리한다. 하지만, 굉장히 느리며 그동안 리소스를 유지하는 비용이 많이 들어간다. public abstract class InputStream implements Closeable {...} public interface Closeable extends .. 2024. 4. 7.
728x90