(Refactoring) 기본형을 객체로 바꾸기

SteadySlower·2023년 5월 12일
0

본 포스팅은 리팩터링 2판을 읽고 작성했습니다.

개발 초기에는 하나의 구조체에 여러가지 기본 자료형 (Int, String)등을 통해서 데이터를 표현할 때가 많습니다. 하지만 앱이 복잡해짐에 따라 구조체도 복잡해지고 때로는 기본자료형들을 묶어서 하나의 구조로 처리하는 것이 효과적인 경우가 있습니다. 아래 코드를 봐주세요.

before

아래 코드를 보면 Student라는 정보에는 학교, 학년, 반이라는 3개의 정보가 각각 String과 Int로 이루어져 있습니다. computed property 중에서도 classRoom과 studentCode의 경우 해당 3개의 속성으로 정의되어 있습니다.

학교, 학년, 반은 의미적으로도 그리고 코드의 효율성 측면에서 보아도 하나의 전용 클래스로 묶어주는 것이 효율적입니다. 리팩터링 해보겠습니다.

struct Student {
    let name: String
    let school: String
    let grade: Int
    let `class`: Int
    let hobby: String
    let friends: [Student]
    
    var desctiption: String {
        "\(school) \(grade)학년 \(`class`)\(name)"
    }
    
    var classRoom: String {
        "\(grade)-\(`class`) 교실"
    }
    
    var studentCode: String {
        "\(school)\(grade)\(`class`)"
    }
    
    var friendsInSameClass: [Student] {
        friends.filter { $0.school == self.school && $0.grade == self.grade && $0.class == self.class }
    }
}

after

학교, 학년, 반을 따로 AcademicInfo(학적정보)라는 객체로 분리하였습니다. 그리고 관련된 computed property 또한 해당 객체 안으로 분리했습니다.

Student라는 객체의 복잡성이 줄어들었습니다. AcademicInfo가 자체적으로 처리할 수 있는 로직은 해당 객체로 이동했기 때문입니다.

더불어 friendsInSameClass를 구할 때도 AcademicInfo에 Equatable을 채택하면 각각 학교, 학년, 반을 비교하지 않고 전체 객체를 사용해서 비교할 수 있습니다.

struct AcademicInfo: Equatable {
    let school: String
    let grade: Int
    let `class`: Int
    
    var description: String {
        "\(school.rawValue) \(grade)학년 \(`class`)반"
    }
    
    var classRoom: String {
        "\(grade)-\(`class`) 교실"
    }
    
    var studentCode: String {
        "\(school)\(grade)\(`class`)"
    }
}

struct Student {
    let name: String
    let academicInfo: AcademicInfo
    let friends: [Student]
    
    var desctiption: String {
        "\(academicInfo.description) \(name)"
    }
    
    var friendsInSameClass: [Student] {
        friends.filter { $0.academicInfo == self.academicInfo }
    }
}
profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.

0개의 댓글