(Refactoring) 위임 숨기기

SteadySlower·2023년 5월 14일
0

본 포스팅은 리팩터링 2판을 읽고 작성했습니다.
지난번 포스팅에 기본형을 객체로 변경하는 리팩터링을 했었는데요. 해당 코드에 문제점이 하나 있습니다.

before

아래 코드의 문제점은 학생의 classRoom과 studentCode라는 정보에 접근하기 위해서는 Student라는 객체가 해당 정보들을 AcademicInfo라는 객체에 위임하고 있다는 것을 알아야 한다는 것입니다.

따라서 student.academicInfo.classRoom, student.academicInfo.studentCode 처럼 academicInfo를 하나 거쳐서 해당 정보에 접근할 수 밖에 없습니다.

이 경우 academicInfo의 인터페이스가 수정되는 경우 이렇게 선언된 모든 코드를 수정해야 하는 단점이 있습니다. 따라서 위임객체인 AcademicInfo를 숨기는 방법으로 리팩토링을 해보도록 하겠습니다.

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 }
    }
}

after

아래와 같이 Student 안에 classRoom과 studentCode를 computed property로 선언합니다. 이렇게 하면 Student 객체를 사용하는 사람은 해당 객체가 어떤 객체에 정보를 위임하고 있는지 몰라도 관계없이 student.classRoom, student.studentCode로 바로 필요한 정보에 접근할 수 있습니다.

또한 AcademicInfo의 인터페이스가 변경이 되더라도 Student의 위임객체를 숨기는 부분만 수정하면 다른 코드들은 전혀 수정할 필요가 없게 됩니다.

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

0개의 댓글