객체지향

객체지향적으로 리팩토링하며 이해해보자

리팩토링 전 코드

사용자가 상점에서 상품을 구매하는 코드이다.

사용자와 상점은 돈을 가지고 있고, 거래가 일어나면 돈을 주고 받는다.

상점 코드

import Foundation

class SoiStore {
    var money: Int = 0
    var name: String = "쏘이네 가게"
    var products: [Int: [String: Any]]
    
    init() {
        self.money = 0
        self.products = {
            [
            1: ["name": "키보드", "price": 30000],
            2: ["name": "모니터", "price": 50000]
            ]
        }()
    }
    
    func setMoney(_ money: Int) {
        self.money = money
    }
    
    func setProducts(_ products: [Int: [String: Any]]) {
        self.products = products
    }
    
    func getMoney() -> Int {
        return self.money
    }
    
    func getProducts() -> [Int: [String: Any]] {
        return self.products
    }
}

손님 코드

실행 코드

리팩토링 1 - 추상화

추상화

상점 코드

변경사항 없으며, JiwonStore가 새로 생겼다. (형채는 SoiStore와 동일)

사용자 코드

실행코드

리팩토링 2 - 캡슐화

Store의 책임 재정의

  1. Store는 사용자가 요구한 제품을 보여줄 수 있어야한다.

  2. Store는 사용자에게 물건을 줘야한다.

  3. Store는 사용자에게 돈을 받아야한다.

상점 프로토콜

상점 코드

사용자 코드

실행코드

헷갈렸던 부분

  • 프로토콜 : 객체의 기본 규약

    • setMoney라는 함수가 있다고 가정한다면 이것은 프로토콜에 추가해서는 안 된다.

    • 객체의 기본 규약을 정의하는 것이기 때문에 당연히 적용되어야된다고 생각했었다. 하지만 프로토콜로 선언하면 private을 쓸 수 없다. 또한 외부 객체가 알 필요 없는 내부 로직이나 구현 방식에 대한 정보는 포함시키지 않는 것이 맞다. (캡슐화와 정보 은닉)

리팩토링 3 - 단일 책임

상점 프로토콜

상점

손님

리팩토링 4 - Product의 객체화

Product가 Dictionary로 선언되어있어서 복잡해보일 뿐만 아니라 추후 Product 역시 특정 책임을 갖게 될 수 있으므로 구조체 또는 클래스를 이용해야한다.

또한 함수명으로 코드를 이해할 수 있도록 money>=price 등을 함수로 만드는 것이 좋다.

프로토콜

Product 구조체

Store

User

main

Last updated