이번주 주요 지적사항

코틀린 컨벤션 지키기의 습관화 및 자동정렬

->안드로이드 스튜디오 기준 ctrl+Alt+L키
->object는 맨 아래에 위치

가독성과 통일성

->함수의 이름 지을 때에는 목적과 통일성 모두 고려
  단순 작동 결과에 대한 이름❌
✔실질적 목적에 따른 함수 이름을 지어야
❌자료형 등을 변수 명에 사용하는 것은 최대한 자제

enum과 object(예시: 메뉴처리)

enum의 용도

정의적인 특징

자바와 마찬가지로 enum은 단순히 값만 열거하는 존재가 아니다.
✔enum의 클래스 안에도 프로퍼티나 메서드를 정의할 수 있다.
Kotlin In Action 78p

연관성 있는 집합

연관성이 있는 각각의 상수 집합 정의 시 사용
각각의 열거 상수는 객체,열거형 클래스도 하나의 인스턴스

enum의 특징에 따른 장점 및 단점

장점

가독성

⚪논리적인 정의를 통한 구분으로 가독성 향상이 가능하다.

타입안정성과 코드 안정성

⚪각 상수가 해당 열거형의 인스턴스로 존재.
->컴파일러가 타입을 검사할 수 있어서 잘못된 키나 값이 들어갈 가능성 줄어듦
⚪IDE자동완성 기능 사용 가능
->코드 작성시 발생 가능한 오타나 실수 방지 가능

유지보수의 간편함

메뉴 항목의 추가 및 삭제가 object에 비해 편리
코드를 간단하게 변경이 가능하므로 리팩토링 시 변경범위가 줄어든다.

확장성

항목의 추가 뿐 아니라 동작의 추가에 대해서도 쉽게 확장이 가능하다.

단점(object와 비교한 상대성)

메모리의 사용

enum class사용시 모든 열거 상수가 해당 클래스의 인스턴스로 생성된다.
따라서 상수의 집합이 큰 경우 인스턴스의 증가로 메모리 사용 역시 증가한다.

enum class ErrorMessage(val message: String) {
   INVALID_DATE("[ERROR] 유효하지 않은 날짜입니다. 다시 입력해 주세요."),
   DUPLICATE_MENU("[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요."),
   INVALID_MENU_FORM("[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요."),
   OVER_MENU("[ERROR]메뉴는 한번에 20개까지만 주문 가능합니다.")
}

위 코드는 컴파일러에 의해 다음과 같이 변환된다.

public final class ErrorMessage private constructor(val message: String) {
    public companion object {
        public val INVALID_DATE: ErrorMessage = ErrorMessage("[ERROR] 유효하지 않은 날짜입니다. 다시 입력해 주세요.")
        public val DUPLICATE_MENU: ErrorMessage = ErrorMessage("[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요.")
        public val INVALID_MENU_FORM: ErrorMessage = ErrorMessage("[ERROR] 유효하지 않은 주문입니다. 다시 입력해 주세요.")
        public val OVER_MENU: ErrorMessage = ErrorMessage("[ERROR]메뉴는 한번에 20개까지만 주문 가능합니다.")
        
        public val values: Array<ErrorMessage> = arrayOf(INVALID_DATE, DUPLICATE_MENU, INVALID_MENU_FORM, OVER_MENU)
    }
}

지금과 같이 작은 단위라면 enum의 장점을 활용가능하나, 열거상수가 늘어난다면 메모리가 상당히 증가할 것이다.

가독성

논리적인 정의가 지나치게 많은 독특한 상황이라면 오히려 가독성이 떨어질 수도 있다.

단일상속만 지원

코틀린은 단일상속만을 지원하기 때문에 enum은 당연 다른 클래스의 상속이 불가하다.
✔인터페이스를 enum에서 사용하는 것 자체가 불가능은 아니다.
그러나 다른 특성을 가지게 만드는 것은 불가능하다.

관련된 자세한 사항을 알고싶다면?

object의 용도

단일 인스턴스 생성

클래스를 정의함과 동시에 그 클래스의 단일 인스턴스 형성
->싱글톤 패턴의 자동 적용이 가능함.

익명 객체의 사용

추상클래스의 상속 또는 인터페이스 구현시 사용
재사용하지 않거나 외부 접근 없는 간단한 기능 수행 시 주로 사용
코드의 간결성 유지 가능

companion object(동반 객체)

내가 기존에 했던 오해들

관계성

관계가 있는 변수들을 모아놓는 것?
그러나, companion object에 어떤 분이 함수를 넣은 것을 보고 오해가 풀렸다.
또한, 이것들을 관계성으로만 이해하게 되면 enum의 집합처럼 표현하는 효과와 뭐가 다르지 싶어진다

공유의 편리함

미리 언급하지만, 아래에 나온 코드는 리팩토링 이전의 코드로 적합하지 않은 부분이 많다

    companion object {
        val menu = mapOf(
            "애피타이저" to listOf(Pair("양송이 수프", 6000), Pair("타파스", 5000), Pair("시저샐러드", 8000)),
            "메인" to listOf(
                Pair("티본스테이크", 55000),
                Pair("바비큐립", 54000),
                Pair("해산물파스타", 35000),
                Pair("크리스마스파스타", 25000)
            ),
            "디저트" to listOf(Pair("초코케이크", 15000), Pair("아이스크림", 5000)),
            "음료" to listOf(Pair("제로콜라", 3000), Pair("레드와인", 60000), Pair("샴페인", 25000))
        )
        val menuMap = mutableMapOf<String, Int>()
        var totalPrice = 0
        var benefitPrice = 0
    }

위에 보여준 내용들은 모두 다른 클래스에서도 사용해야하는 부분이기 때문에 companion object에 집어넣었다
당시 이렇게 짠 이유는 a라는 클래스에서 계산이 완료된 totalPirce를 b에서도 사용해야했기 때문이다

동반 객체의 진짜 장점

모든 인스턴스에서 안전하게 공유

위에서 설명한 오해와 아주 약간 다르지만, 나에겐 가장 크게 다가왔다.
간혹 a라는 클래스에서 연산을 끝낸 뒤에 제대로 출력된 전역변수가 b라는 클래스에서 불러왔더니 초기화 상태로 있는 경우가 있다.
특정 인스턴스에 속한 속성의 경우 해당 인스턴스에서만 상태를 유지하기 때문인데 이럴 때에 동반객체를 사용하면 자신이 원하는 값을 얻을 수 있다.

함수도 공유 가능

해당 클래스의 모든 인스턴스에서 공유되는 함수 역시 구현이 가능하다

private 멤버 접근 가능

클래스 내부에서만 사용되어야하는 private에 접근이 가능하다

모듈화

위에서 말한 장점으로 모듈화가 쉬워진다
클래스의 외부에서는 필요한 인터페이스와 공개된 멤버만 사용할 수 있도록 세팅가능하기 때문

유지보수

클래스 내부의 구현이 변경되었을 때에 보수가 쉬워진다
동반객체를 통한 접근은 유지하면서 외부에 노출된 api는 변경하지 않아도 되기 때문이다

그래서 object와 enum의 차이는?

서로 다른 유형을 하나로 만든다면?

이때에는 enum이 보다 용이하다.
예를 들어 계절이라는 집합 안에 봄 여름 가을 겨울을 넣는 개념이다.

어마어마하게 방대한 양이라면?

내가 바로 menu를 object에 넣은 이유가 이 때문이다.
위 예시에서는 정해진 적은 량이 입력되었으나, enum은 메모리가 더 많이 사용될 수 있기 때문에
방대한 양으로 늘어날 수 있는 menu는 object가 더 적합하다고 판단하였다.

여러 클래스에서 상태를 공유하려면?

이때에는 위에서 언급하였듯 동반 객체가 보다 편리하다.

enum의 확장성

object도 상속이나 인스턴스 사용이 가능하나, 싱글톤 객체로서의 역할이 더 강하다.
따라서 인터페이스 구현이나 확장 시 enum의 사용이 보다 적합할 수 있다.

댓글남기기