문서로 규약을 정의하라

  • 함수가 무엇을 하는지 명화갛게 설명하고 싶다면 KDoc 주석을 붙여주는 것이 좋음

/**
* 이 프로젝트에서 짧은 메시지를 사용자에게 출력할 때 사용하는 기본 방식
* @param message 사용자에게 보여 줄 메시지
* @param length 메시지의 길이가 어느정도 되는지 나타내는 enum 값
*/
fun Context.showMessage(
    message: String,
    duration: MessageLength = MessageLength.LONG,
) {
    val toastDuration = when (duration) {
        MessageLength.SHORT -> Length.LENGTH_LONG
        MessageLength.LONG -> Length.LENGTH_LONG
    }
    
    Toast.makeText(this, message, toastDuration).show()
}

행위가 문서화되지 않고 요소의 이름이 명확하지 않다면 이를 사용하는 사용자가 의도했던 추상화 목표가 아닌 현재 구현에 의존할 수 있기 때문에 예상되는 행위를 문서로 설명하면 좋음

규약

어떤 행위를 설명하면 사용자는 이를 일종의 약속으로 취급하며 이를 기반으로 스스로 자유롭게 생각하던 예측을 조정

이처럼 예측되는 행위를 요소의 규약이라고 부름

잘 짜여진 규약은 클래스를 만든 사람은 클래스가 어떻게 사용될지 걱정 안해도 됨

규약 정의하기

이름 : 일반적인 개념과 관련된 메소드는 이름만으로 동작을 예측할 수 있음

주석과 문서 : 필요한 모든 규약을 적을 수 있는 방법

타입 : 자주 사용되는 타입의 경우에는 타입만 보아도 어떻게 사용하는지 알 수 있지만 일부 타입은 문서에 추가로 설명해야할 필요가 있음

주석

로버트 마틴 : 주석없이 읽을 수 없는 코드를 짜야함

하지만 모든 일을 극단적으로 진행하는건 좋지 않고 주석을 적절하게 활용하면 더 많은 내용의 규약을 설명할 수 있음

listOf 와 같이 코틀린 표준 라이브러리에 적힌 주석은 코드를 이해하는데 도움이 됨

KDoc

주석을 사용하여 기능을 문서화 할 때 주석을 표시하는 공식 형식

/** 로 시작해서 */ 로 끝남

주석 구조

첫번째 줄 : 기능 요약 설명

두번째 줄 : 기능 자세한 설명

그 뒤에 모든 줄 : @ tag로 시작, 파라미터를 설명하는데 사용

@param <name> : 함수의  매개변수 또는 클래스를 문서화
@return : 함수의 리턴 
@constructor : 클래스의 기본 생성자
@receiver : 익스텐션 함수의 리시버
@property <name> : 명확한 이름을 갖고 있는 클래스의 프로퍼티를 문서화
@throw <class>, @exception <class> : 메소드 내부에서 발생할  있는 예외 사항
@sample <identifier> : 정규화된 형식 이름을 사용해서 함수의 사용 예를 문서화
@author : 요소의 작성자를 지정
@since : 요소에 대한 버전을 지정
@supress : 이를 지정하면 만들어진 문서에서 해당 요소가 제외

타입 시스템과 예측

클래스와 인터페이스에도 여러 가지 예측이 들어가는데 클래스가 어떤 동작을 할 것이라 예측되면 서브 클래스도 이를 보장해야함

  • 이를 리스코프 치환 원칙이라고 부름

  • 해당 원칙은 객체 지향 프로그램에서 중요한데, S가 T의 서브 타입이라면 별도의 변경 없어도 T 타입 객체를 S 타입 객체로 대체할 수 있어야함

조금씩 달라지는 세부 사항

구현의 세부 사항은 항상 달라질 수 있지만 최대한 많이 보호하는 것이 좋음

즉 캡슐화가 많이 적용될 수록 사용자가 구현에 신경을 많이 쓸 필요없고 자유를 많이 갖게 됨

정리

외부 API를 구현할 때는 규약을 잘 정의해야함

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

Last updated