Hanbit the Developer
Effective Kotlin | 4장. 추상화 설계 본문
아이템 26: 함수 내부의 추상화 레벨을 통일하라
올바른 예시:
fun makeCoffee() {
boilWater()
brewCoffee()
pourCoffee()
}
잘못된 예시:
fun makeCoffee() {
// boil water
val water = findWater()
val kettle = findKettle()
kettle.boil(water)
brewCoffee()
pourCoffee()
}
아이템 27: 변화로부터 코드를 보호하려면 추상화를 사용하라
추상화 할 수 있는 방법은 다음과 같다:
- 상수로 추출한다.
- 동작을 함수로 래핑한다.
- 함수를 클래스로 래핑한다.
- 인터페이스 뒤에 클래스를 숨긴다.
- 보편적인 객체를 특수한 객체로 래핑한다.
다만 추상화가 과도하면 코드가 복잡해지기 때문에 다음과 같은 기준으로 균형을 맞춰야 한다:
- 팀의 크기
- 팀의 경험
- 프로젝트의 크기
- feature set
- 도메인 지식
아이템 28: API 안정성을 확인하라
프로그래밍에서 안정적이고 최대한 표준적인 API를 선호하는 이유:
- unstable하기 때문에 API가 자주 변경된다면 여러 코드를 수동으로 업데이트 해야 한다.
- 사용자가 새로운 API를 배워야 한다.
그럼에도 불구하고 좋은 API를 한번에 설계하기 어렵기 때문에 적절한 변경도 필요하다.
API 또는 API 일부가 불안정하다면 이를 알려야 한다.
시멘틱 버저닝
MAJOR.MINOR.PATCH(ex: 2.44.2)
- MAJOR: 호환되지 않는 수준의 API 변경
- MINOR: 이전 변경과 호환되는 기능을 추가
- PATCH: 간단한 버그 수정
Annotation
- @Experimental: 해당 요소는 안정적이지 않다는 것을 알림
- @Deprecated: 직접적인 대안이 있다면 ReplaceWith를 붙일 수도 있음(IDE가 자동 전환)
아이템 29: 외부 API를 랩(wrap)해서 사용하라
안전하다고 명시되어 있어도 신뢰할 수 없는 경우, 이 불안정한 API를 과도하게 사용해선 안 된다. 따라서 이를 wrap해서 사용한다.
장점은 다음과 같다:
- 문제 발생 시 wrapper만 변경하면 된다.(코드 변경이 쉽다.)
- 프로젝트 스타일에 맞춰 API 형태를 조정할 수 있다.
단점은 다음과 같다:
- wrapper를 따로 정의해야 한다.
- 다른 개발자가 프로젝트를 다룰 때 어떤 wrapper들이 있는지 따로 확인해야 한다.
- wrapper는 내부에서만 유효하므로 문제가 생겨도 stack overflow 등에 질문할 수 없다.
일반적으로 라이브러리 사용자가 많을수록 안정적이다.
아이템 30: 요소의 가시성을 최소화하라
장점:
- 인터페이스가 작을수록 이를 공부하고 유지하는 것이 쉽다.
- 변경하기 쉽다.
- 클래스 상태를 나타내는 프로퍼티가 노출되었다면, 클래스가 자신의 상태를 책임질 수 없다.
- API 변경을 쉽게 추적할 수 있다.
아이템 31: 문서로 규약을 정의하라
KDoc 주석으로 의도를 명시하라.
함수나 클래스 이름만을 예측할 수 없는 사항들에 대해 추가적인 설명이 필요하다.
규약
규약을 정의하여, 클래스의 오사용을 방지하고 사용자는 내부 구현을 알지 않아도 된다.
규약을 정의하는 방법:
- 이름: sum()이라는 이름만으로 문서를 볼 필요도 없게 만든다.
- 주석과 문서
- 타입
주석을 써야 할까?
[클린 코드] 이후 주석을 읽지 않고도 읽을 수 있는 코드가 인기가 많아졌다.
단, 어느쪽이든 극단적인 것은 좋지 않으므로 ‘적절히’ 사용해야 한다.
KDoc 형식
주석으로 함수를 문서화할 때 사용되는 공식적인 형식이며 KDoc 마크다운 형식으로 작성한다.
/**
* Hello world!
*/
주석의 구성 요소는 다음과 같다:
- 요약 설명
- 상세 설명
- 태그
- @param <name>
- @return
- @constructor
- @receiver: 확장 함수의 리시버를 문서화한다.
- @property <name>
- @throws <class>, @exception <class>
- @sample <identifier>
- @see <identifier>
- @author
- @since: 요소에 대한 버전을 지정한다.
- @supress: 지정 시 만들어지는 문서에서 해당 요소가 제외된다. 외부에서 사용되지만 공식 API에 포함할 필요가 없는 요소에 지정한다.
관련된 요소들에 링크를 걸 때는 대괄호를 사용한다.(ex: @see [Fragment])
링크 대상에 대한 추가 설명을 입력하고 싶을 때는 대괄호를 두 번 연속해서 사용한다.(ex: [this element with custom description][Element])
Dokka: 공식적인 코틀린 문서 생성 도구
아이템 32: 추상화 규약을 지켜라
규약은 단순한 합의이기 때문에 위반될 수 있다. 무언가를 할 수 있다고 해도 그것을 해도 괜찮다는 것이 아니므로 규약을 지켜야 한다.
상속된 규약
클래스를 상속하거나 인터페이스를 구현할 때 규약을 반드시 지켜야 한다.
'Kotlin' 카테고리의 다른 글
Effective Kotlin | 6장. 클래스 설계 (0) | 2023.08.12 |
---|---|
Effective Kotlin | 5장. 객체 생성 (0) | 2023.08.08 |
Effective Kotlin | 3장. 재사용성 (0) | 2023.06.13 |
Effective Kotlin | 2장. 가독성 (0) | 2023.06.13 |
Effective Kotlin | 1장. 안정성 (0) | 2023.06.13 |