kyucumber
전체 글 보기

이펙티브 코틀린 아이템 31. 문서로 규약을 정의하라

fun Context.showMessage( message: String, duration: MessageLength = MessageLength.LONG ) { val toastDuration = when(duration) { SHORT -> Length.LENGTH_SHORT LONG -> Length.LENGTH_LONG } Toast.makeText(this, message, toastDuration).show() } enum class MessageLength { SHORT, LONG }

위 showMessage 함수는 다른 타입으로도 메시지를 출력할 수 있게 하고자 붙인 이름이지만 개발자는 당연히 토스트를 출력할거라고 생각할 수 있다.

따라서 이 함수가 무엇을 하는지 명확하게 설명하고 싶다면 아래처럼 KDoc으로 주석을 붙여 주는 것이 좋다.

/** * Universal way for the project to display a short * message to a user. * @param message 설명 * @param duration 설명 */ fun Context.showMessage( // ... )

규약

규약이 적절하게 정의되어 있다면 클래스를 만든 사람은 클래스가 어떻게 사용될 지 걱정하지 않아도 된다.

서로가 규약을 존중하면 독립적으로 작업해도 모든것이 정상적으로 기능할 것이다.

규악 정의하기

규약 정의를 위한 대표적인 몇가지 방법

  • 이름
  • 주석과 문서
  • 타입

주석을 써야 할까?

대부분의 기능은 이름으로 무엇을 하는지 확실하게 알 수 있으므로 주석을 활용한 추가적인 설명이 필요가 없다.

fun List<Int>.product() = fold(1) { acc, i -> acc * i }

여기에 주석을 다는 것은 코드를 산만하게 만드는 노이즈이다.

KDoc 형식

주석으로 함수를 문서화할 때 사용하는 공식적인 형식을 KDoc이라고 부른다.

KDoc은 /** 로 시작해 */ 로 끝나며 아래와 같은 구조를 가지고 있다.

  • 첫번째 부분은 요소에 대한 요약 설명이다.
  • 두번째 부분은 상세 설명이다.
  • 이어지는 줄은 모두 태그로 시작하며, 이러한 태그는 추가적인 설명을 위해 사용된다.

사용될 수 있는 태그는 아래와 같다.

  • @param 함수 파라미터 또는 클래스, 프로퍼티, 함수 타입 파라미터
  • @return 함수의 리턴 값을 문서화
  • @constructor 클래스의 기본 생성자를 문서화
  • @receiver 확장 함수의 리시버를 문서화
  • @property <name> 명확한 이름을 가진 클래스의 프로퍼티를 문서화, 기본 생성자에 정의된 프로퍼티에 사용한다.
  • @throws <class>, @exception <class> 메소드 내부에서 발생할 수 있는 예외를 문서화
  • @sample <identifier> 정규화된 형식 이름을 사용해 함수의 사용 예를 문서화한다.
  • @see <identifier> 특정한 클래스 또는 메소드에 대한 링크 추가
  • @author 요소의 작성자 지정
  • @since 요소에 대한 버전 지정
  • @supress 이를 지정하면 만들어지는 문서에서 해당 요소가 제외된다. 외부에서는 사용할 수 있지만, 공식 API에 포함할 필요가 없는 요소에 지정

타입 시스템과 예측

클래스가 어떤 동작을 할 것이라 예측되면, 서브클래스도 이를 보장해야 하며 이를 리스코프 치환 원칙(Liskov substitution principle)이라고 부른다.

표준 라이브러리나 인기있는 라이브러리의 대부분 클래스는 서브클래스에 대한 자세한 설명과 규약을 갖고 있다.

interface Car { /** * 자동차의 방향을 변경합니다. * @param angle 바퀴 축의 각도를 지정합니다. * 라디안 단위로 지정하며, 0은 직진을 의미합니다. */ fun setWheelPosition(angle: Float) /** * 자동차의 속도가 0이 될때까지 감속합니다. * @param pressure 브레이크 페달을 사용하는 비율을 지정합니다. * 0 - 1 사이의 숫자를 지정합니다. */ fun setBreakPedal(pressure: Double) }

이러한 설명과 규약은 인터페이스를 유용하게 만든다.

조금씩 달라지는 세부 사항

프로그래밍 언어에서도 구현의 세부 사항은 조금씩 달라질 수 있지만, 최대한 많이 보호하는 것이 좋다.

캡슐화로 최대한 허용되는 범위를 지정해주면 사용자가 구현에 신경을 많이 쓸 필요가 없어지므로 더 많은 자유를 갖게 된다.

정리

특히 외부 API를 구현할 때는 규약을 잘 정의해야 한다.

이러한 규약은 이름, 문서, 주석, 타입을 통해 구현할 수 있다.

Reference

  • 이펙티브 코틀린 - 프로그래밍 인사이트, 마르친 모스칼라 지음, 윤인성 옮김

개인적인 기록을 위해 작성된 글이라 잘못된 내용이 있을 수 있습니다.

오류가 있다면 댓글을 남겨주세요.