Giter Club home page Giter Club logo

ios-juice-maker's Introduction

๐Ÿฅค์ฅฌ์Šค ๋ฉ”์ด์ปค

์ฅฌ์Šค๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ ์žฌ๋ฃŒ๋ฅผ ํ™•์ธํ•˜๊ณ  ์žฌ๋ฃŒ์˜ ์žฌ๊ณ ๊ฐ€ ์žˆ์œผ๋ฉด ๋ ˆ์‹œํ”ผ๋Œ€๋กœ ์ฅฌ์Šค๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ํ”„๋กœ๊ทธ๋žจ

ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ ๊ธฐ๊ฐ„ | 23.05.08.(์›”) ~ 23.05.26.(๊ธˆ)

๐Ÿ“š ๋ชฉ์ฐจ

๐Ÿง‘โ€๐Ÿ’ป ํŒ€์› ์†Œ๊ฐœ

Yetti Mary yy-ss99

โฐ ํƒ€์ž„๋ผ์ธ

๋‚ ์งœ์™€ ์ค‘์š”ํ•œ ์ปค๋ฐ‹ ์œ„์ฃผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • 23/05/09 (ํ™”)
    • ์ „์ฒด ๊ตฌ์กฐ์—์„œ ํ•„์š”ํ•œ ํƒ€์ž…๋“ค ์„ ์–ธ ๋ฐ ํŒŒ์ผ๋ณ„ ์ •๋ฆฌ
    • ์žฌ๊ณ ๋ฅผ ์กฐ์ ˆํ•˜๋Š” ๊ธฐ๋Šฅ ๊ตฌํ˜„
    • ์—๋Ÿฌ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์—๋Ÿฌ ํƒ€์ž… ๊ตฌํ˜„
  • 23/05/11 (๋ชฉ)
    • ์ฅฌ์Šค๋ฅผ ์ฃผ๋ฌธ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ์™€ ๋งŒ๋“œ๋Š” ๊ธฐ๋Šฅ ๋ถ„๋ฆฌ
  • 23/05/12 (๊ธˆ)
    • ๋ ˆ์‹œํ”ผ ๋ฐ˜ํ™˜ ๋ฉ”์„œ๋“œ๋ฅผ ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋กœ ์ˆ˜์ •
  • 23/05/16 (ํ™”)
    • ์ฅฌ์Šค ์ฃผ๋ฌธ ๋ฒ„ํŠผ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„
    • alert ๋ฉ”์„œ๋“œ ๋ฐ ๊ณผ์ผ ์ˆ˜๋Ÿ‰ ๋ ˆ์ด๋ธ” ๋ณ€๊ฒฝ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„
    • ์žฌ๋ฃŒ ๋ถ€์กฑ alert์™€ ์žฌ๊ณ  ์ˆ˜์ • ๋ฒ„ํŠผ์—์„œ ํ™”๋ฉด ์ „ํ™˜ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • 23/05/23 (ํ™”)
    • ์žฌ๊ณ  ์ถ”๊ฐ€ ํ™”๋ฉด ์ง„์ž…์‹œ ๊ณผ์ผ์˜ ํ˜„์žฌ ์žฌ๊ณ  ์ˆ˜๋Ÿ‰ ํ‘œ์‹œ ๊ธฐ๋Šฅ ๊ตฌํ˜„
    • Stepper๋ฅผ ์ด์šฉํ•œ ์žฌ๊ณ  ์ˆ˜์ • ๊ธฐ๋Šฅ ๊ตฌํ˜„

๐Ÿ” ์‹œ๊ฐํ™” ๊ตฌ์กฐ

UML ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

๐Ÿ“ฑ ์‹คํ–‰ ํ™”๋ฉด

iPhone 14 Pro

ezgif com-video-to-gif-min

iPhone SE(3generation)

ezgif com-video-to-gif (1)-min

๐Ÿ”จ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

๐Ÿ“ฃ์ฝ”๋“œ๋Š” ํ† ๊ธ€ ์ฒ˜๋ฆฌ ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค.

1๏ธโƒฃ ๊ฐ’ ์ „๋‹ฌ ๋ฐฉ๋ฒ• ๊ฒฐ์ •ํ•˜๊ธฐ

๐Ÿ”‘ ์ฒซ๋ฒˆ์งธ ๋ฐฉ์•ˆ - delegate pattern

  • ์žฅ์ 

    • ๊ฐ์ฒด ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๋Š”๋ฐ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค. ๊ฐ์ฒด๋“ค์€ ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐœ๋ฐœ๋˜๊ณ  ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋‹ค๋ฅธ ๊ฐ์ฒด์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์ด ์ตœ์†Œํ™”๋ฉ๋‹ˆ๋‹ค.
    • ์ฝ”๋“œ์˜ ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. delegate pattern์‚ฌ์šฉ ์‹œ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝ์‹œ์— protocol์™€ extension์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ํ•ด๋‹น ๊ฐ์ฒด์— ์ ์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์‰ฝ๊ฒŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • protocol๊ณผ extension์œผ๋กœ ๊ตฌํ˜„๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ช…ํ™•ํ•˜๊ฒŒ ์ •์˜ํ•˜๊ณ  ๋ฌธ์„œํ™” ํ•  ์ˆ˜ ์žˆ์–ด ๊ฐœ๋ฐœ์ž๋“ค์ด ์ƒํ˜ธ์ž‘์šฉ์„ ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋‹จ์ 

    • ์ƒํ™ฉ์— ๋”ฐ๋ผ ๊ฐ์ฒด ๊ฐ„์˜ ์–‘๋ฐฉํ–ฅ ์˜์กด์„ฑ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ๊ณ  ๊ธฐ๋Šฅ์ด ๋ถ„์‚ฐ ๋จ์œผ๋กœ ๊ฐ์ฒด ๊ฐ„์˜ ๊ด€๊ณ„ ํŒŒ์•…์ด ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค.
์ฝ”๋“œ
final class JuiceOrderViewController: UIViewController {
    ...
    private func presentChangeStockViewController() {
        guard let viewController = storyboard?
            .instantiateViewController(identifier: "ChangeStockViewController") as? ChangeStockViewController else { return }
        viewController.delegate = self
        viewController.modalPresentationStyle = .fullScreen
        present(viewController, animated: true)
    }
     ...
}

extension JuiceOrderViewController: StockDelegate {
    func getCurrentStock() -> [Int] {
        return Fruits.allCases.map { fruits in
            juiceMaker.fruitStore.bringQuantity(of: fruits) }
    }
    
    func addStock(quantities: [Int]) {
        for (index, fruit) in Fruits.allCases.enumerated() {
            juiceMaker.fruitStore.addStock(fruit: fruit, quantity: quantities[index])
        }
    }
}
protocol StockDelegate: AnyObject {
    func getCurrentStock() -> [Int]
    func addStock(quantities: [Int])
}

final class ChangeStockViewController: UIViewController {
    ...
    weak var delegate: StockDelegate?
    ... 
    private func initializeStockLabels() {
        guard let currentStock = delegate?.getCurrentStock() else { return }
        initialStock = currentStock
        for (index, label) in stockChangeLabels.enumerated() {
            label.text = "\(initialStock[index])"
        }
    }
    
    @IBAction private func hitDismissButton(_ sender: UIBarButtonItem) {
        delegate?.addStock(quantities: additionalStock)
        dismiss(animated: true)
    }
    ...
}

๐Ÿ”‘ ๋‘๋ฒˆ์งธ ๋ฐฉ์•ˆ - closure

  • ์žฅ์ 

    • ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋‹จ์ 

    • ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•  ์ˆ˜๋ก ์ฝ”๋“œ๊ฐ€ ์กฐ๋ฐ€ํ•ด์ ธ์„œ ๊ฐ€๋…์„ฑ์„ ํ•ด์น ๋งŒํ•œ ์šฐ๋ ค๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
์ฝ”๋“œ
final class JuiceOrderViewController: UIViewController {
    ...
    private func presentChangeStockViewController() {
        guard let viewController = storyboard?
            .instantiateViewController(identifier: "ChangeStockViewController") as? ChangeStockViewController else { return }
        viewController.getCurrentHandler = self.getCurrentStock
        viewController.addStockHandler = self.addStock
        viewController.modalPresentationStyle = .fullScreen
        present(viewController, animated: true)
    }
    
    private func getCurrentStock() -> [Int] {
        return Fruits.allCases.map { fruits in
            juiceMaker.fruitStore.bringQuantity(of: fruits) }
    }

    private func addStock(_ quantities: [Int]) {
        for (index, fruit) in Fruits.allCases.enumerated() {
            juiceMaker.fruitStore.addStock(fruit: fruit, quantity: quantities[index])
        }
    }
    ...
}
final class ChangeStockViewController: UIViewController {
    ...
    var getCurrentHandler: (() -> [Int])?
    var addStockHandler: ((_ quantities:[Int]) -> Void)?
    ...    
    private func initializeStockLabels() {
        guard let currentStock = getCurrentHandler?() else { return }
        initialStock = currentStock
        for (index, label) in stockChangeLabels.enumerated() {
            label.text = "\(initialStock[index])"
        }
    }
    
    @IBAction private func hitDismissButton(_ sender: UIBarButtonItem) {
        addStockHandler?(additionalStock)
        dismiss(animated: true)
    }
    ...
}

๐Ÿ”‘ ์„ธ๋ฒˆ์งธ ๋ฐฉ์•ˆ - notification

  • ์žฅ์ 

    • ๋‹ค์ˆ˜์˜ ๊ฐ์ฒด์— ๋™์‹œ์— ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์„ค์ •ํ•ด์ค„ ํ•„์š”์—†์ด ์งง์€ ์ฝ”๋“œ๋กœ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋‹จ์ 

    • ์˜ค๋ฅ˜์˜ ์ถ”์ ์ด ์‰ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด notificationName ๋˜๋Š” userInfo์˜ key๊ฐ’์ด String๊ฐ’์œผ๋กœ ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜๋Š”๋ฐ ์ด ๋ถ€๋ถ„์— ์˜คํƒ€๊ฐ€ ๋‚˜์„œ postํ•˜๋Š” ๋ถ€๋ถ„๊ณผ addObserver๋ถ€๋ถ„์ด ๋‹ฌ๋ผ์ง€๊ฒŒ ๋˜๋”๋ผ๋„ ์ปดํŒŒ์ผ์ด๋‚˜ ๋Ÿฐํƒ€์ž„์—์„œ ์—๋Ÿฌ๋ฅผ ๋ฑ‰์–ด์ฃผ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ง์ ‘ ๋ˆˆ์œผ๋กœ ๋ฐœ๊ฒฌํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ๋…ธํ‹ฐํ”ผ์ผ€์ด์…˜์—์„œ ๋‚˜๋Š” ์—๋Ÿฌ์ธ์ง€ ์ธ์ง€ํ•˜๊ธฐ ์‰ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    • post๊ฐ€ ๋œ ํ›„์— ๋‹ค์‹œ postํ•œ ๋ถ€๋ถ„์œผ๋กœ ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
์ฝ”๋“œ
final class JuiceOrderViewController: UIViewController {
    ...
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(addStock(_:)),
                                               name: Notification.Name("changeStock"),
                                               object: nil)
    }
        ...    
    @objc func addStock(_ notification: NSNotification) {
        guard let notifi = notification.userInfo?["additionalStock"] as? [Int] else { return }
        for (index, fruit) in Fruits.allCases.enumerated() {
        juiceMaker.fruitStore.addStock(fruit: fruit, quantity: notifi[index])
        }
    }
}
final class ChangeStockViewController: UIViewController {
		...    
    @IBAction private func hitDismissButton(_ sender: UIBarButtonItem) {
        NotificationCenter.default.post(name: Notification.Name("changeStock"),
                                        object: nil,
                                        userInfo: ["additionalStock": additionalStock])
        dismiss(animated: true)
    }
    ...
}

โ†’ ์ฝ”๋“œ๋กœ ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๊ณ  ์žฅ๋‹จ์ ์„ ๊ณ ๋ คํ•œ ๊ฒฐ๊ณผ delegate pattern์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ ํ™”๋ฉด ์ „ํ™˜ ๋ฐฉ๋ฒ• ์„ ํƒํ•˜๊ธฐ

๐Ÿ”’ ๊ณ ๋ฏผํ–ˆ๋˜ ์  :๋„ค๋น„๊ฒŒ์ด์…˜ vs ๋ชจ๋‹ฌ

๊ณผ์ผ์˜ ์žฌ๊ณ ๊ฐ€ ๋ถ€์กฑํ•  ๊ฒฝ์šฐ๋‚˜ JuiceOrderViewController์—์„œ ์žฌ๊ณ  ์ˆ˜์ • ๋ฒ„ํŠผ์„ ํ„ฐ์น˜ํ•  ๊ฒฝ์šฐ์— ChangeStockViewController์—์„œ ๊ณผ์ผ์˜ ์žฌ๊ณ ๋ฅผ ์ถ”๊ฐ€ํ•œ ๋’ค JuiceOrderViewController๋กœ ๋Œ์•„๊ฐ€๋Š” ํ™”๋ฉด ์ „ํ™˜์€ ์–ด๋–ค ๋ฐฉ์‹์ด ์ข‹์„์ง€ ๊ณ ๋ฏผํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ๋„ค๋น„๊ฒŒ์ด์…˜ ์ธํ„ฐํŽ˜์ด์Šค ํŠน์ง•
    • Navigation Controller๋Š” ์ฃผ๋กœ ๊ณ„์ธต์  ๊ตฌ์กฐ์˜ ํ™”๋ฉด์ „ํ™˜์„ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๋“œ๋ฆด ๋‹ค์šด ์ธํ„ฐํŽ˜์ด์Šค(๊ฐ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ํ•ญ๋ชฉ์— ๋Œ€ํ•œ ์„ธ๋ถ€ํ•ญ๋ชฉ์ด ์กด์žฌํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค)์ž…๋‹ˆ๋‹ค.
    • ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ ์Šคํƒ์— ๋”ฐ๋ผ ํ™”๋ฉด์„ ์Šคํƒ์— ํ‘ธ์‹œ(push)ํ•˜๊ฑฐ๋‚˜ ํŒ(pop)ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํ™”๋ฉด ์ „ํ™˜์„ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ชจ๋‹ฌ ํŠน์ง•
    • ํ™”๋ฉด์„ ๋‹ค๋ฅธ ํ™”๋ฉด์œ„์— ๋„์›Œ์„œ ์‚ฌ์šฉ์ž์˜ ์ด๋ชฉ์„ ๋Œ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • ํ˜„์žฌ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ ์œ„์— ๊ฒน์ณ์ ธ์„œ ํ‘œ์‹œ๋˜๋ฉฐ ๋‹ค๋ฅธ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์ด๋™ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ซ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ๋ชจ๋‹ฌ์€ ์–ผ๋Ÿฟ์„ ํ†ตํ•ด ํ™•์ธ/์ทจ์†Œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜๊ฑฐ๋‚˜ ์•ก์…˜์‹œํŠธ์—์„œ ์„ ํƒ์„ ํ•˜๋Š” ๋“ฑ์˜ ํŠน์ • ์„ ํƒ์„ ์™„๋ฃŒ ํ•ด์•ผํ•œ๋‹ค๋Š” ํŠน์ง•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

โ†’ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ฃผ๋กœ ์•ฑ์˜ ๋ฉ”์ธ ํƒ์ƒ‰ ํ๋ฆ„๊ณผ ํ™”๋ฉด ์ „ํ™˜์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๊ณ , ๋ชจ๋‹ฌ์€ ์ถ”๊ฐ€ ์ •๋ณด๋‚˜ ์ž„์‹œ ์ž‘์—…์— ํ•„์š”ํ•œ ํ™”๋ฉด ์ „ํ™˜์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

ChangeStockViewController๋Š” ์ฅฌ์Šค ์ฃผ๋ฌธ ๊ณผ๋Š” ๊ด€๊ณ„์—†์ด ์žฌ๊ณ ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ํ™”๋ฉด์„ ๋„์šฐ๋Š” ์—ญํ• ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ํ๋ฆ„์ƒ ์—ฐ๊ฒฐ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋‹ฌ๋กœ ํ™”๋ฉด์ „ํ™˜์„ ํ•˜๋Š” ๊ฒƒ์ด ๋” ์ ์ ˆํ•˜๋‹ค๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์žฌ๊ณ  ์ถ”๊ฐ€ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์•„๋‹Œ โ€œ์ฃผ๋ฌธ์„ ํ™•์ธ์ค‘์ž…๋‹ˆ๋‹คโ€ฆโ€ ๋ฉ”์‹œ์ง€๋ฅผ ๋„์›Œ์ฃผ๋Š” ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋กœ ํ™”๋ฉด์ „ํ™˜์„ ํ•œ๋‹ค๋ฉด ์ฅฌ์Šค ์ฃผ๋ฌธ๊ณผ ๊ฐ™์€ ํ๋ฆ„์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿด ๋•Œ์—๋Š” ๋„ค๋น„๊ฒŒ์ด์…˜ ์ธํ„ฐํŽ˜์ด์Šค ๋ฐฉ์‹์ด ๋” ์ ์ ˆํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.


3๏ธโƒฃ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฒ„ํŠผ์„ ํ•œ ๊ฐœ์˜ IBAction์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ

๐Ÿ”’ ๋ฌธ์ œ์ 

JuiceOrderViewController์—๋Š” ์ฅฌ์Šค๋ฅผ ์ฃผ๋ฌธํ•˜๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฒ„ํŠผ์ด ์žˆ๊ณ , ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด placeAnOrder(for:)๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ๊ฐ์˜ IBAction์„ ๋งŒ๋“ค์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋‹ˆ ์ฝ”๋“œ๊ฐ€ ์ค‘๋ณต๋˜๋Š” ๋ฌธ์ œ์ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
@IBAction private func hitStrawberryJuiceOrderButton(_ sender: UIButton) {
		placeAnOrder(for: .strawberryJuice)
}

@IBAction private func hitBananaJuiceOrderButton(_ sender: UIButton) {
		placeAnOrder(for: .bananaJuice)
}

...

๐Ÿ”‘ ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ์ฒซ๋ฒˆ์งธ

์ฒซ๋ฒˆ์งธ๋กœ ์ฐพ์•˜๋˜ ํ•ด๊ฒฐ์ฑ…์€ tag๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ์‹์ด์—ˆ๊ณ  ์ด๋ฅผ ์ด์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฒ„ํŠผ์„ ํ•˜๋‚˜์˜ IBAction์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ์ค‘๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์–ด๋–ค ๋ฒ„ํŠผ์ด tag๊ฐ€ ๋ช‡์ธ์ง€ ํ•œ ๋ˆˆ์— ์•Œ๊ธฐ ์–ด๋ ค์› ๊ณ , ๊ฐ ๋ฒ„ํŠผ์˜ ํƒœ๊ทธ๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ์ง€์ •ํ•ด์ฃผ์–ด์•ผํ•ด์„œ ํ™•์žฅ์„ฑ์ด ์ข‹์ง€ ์•Š๋‹ค๊ณ  ํŒ๋‹จํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
private func searchJuice(by tag: Int) -> Juice? {
    switch tag {
    case 1:
        return .strawberryJuice
    case 2:
        return .bananaJuice
		...
    default:
        return nil
    }
}

@IBAction private func hitJuiceOrderButton(_ sender: UIButton) {
    guard let choosedJuice = searchJuice(by: sender.tag) else { return }
		placeAnOrder(for: choosedJuice)
}

๐Ÿ”‘ ์ตœ์ข… ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

์ตœ์ข…์ ์œผ๋กœ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ฒ„ํŠผ์„ ํ•˜๋‚˜์˜ IBAction์œผ๋กœ ๋ฌถ์–ด์ฃผ๊ณ , ๋ฒ„ํŠผ์˜ title์„ ๊ธฐ์ค€์œผ๋กœ ์ฅฌ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋„๋ก ์ˆ˜์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค. tag ๋ฐฉ๋ฒ•๊ณผ๋Š” ๋‹ฌ๋ฆฌ title์ด ๋ฌธ์ž์—ด์ด๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ๋ฒ„ํŠผ์ธ์ง€ ํ•œ ๋ˆˆ์— ์•Œ๊ธฐ ์‰ฌ์›Œ ํ•ด๋‹น ๋ฐฉ๋ฒ•์œผ๋กœ ์ฑ„ํƒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
private func searchJuice(by tag: Int) -> Juice? {
    switch tag {
    case 1:
        return .strawberryJuice
    case 2:
        return .bananaJuice
		...
    default:
        return nil
    }
}

@IBAction private func hitJuiceOrderButton(_ sender: UIButton) {
    guard let choosedJuice = searchJuice(by: sender.tag) else { return }
		placeAnOrder(for: choosedJuice)
}

4๏ธโƒฃ ๋งค์ง๋ฆฌํ„ฐ๋Ÿด ์ œ๊ฑฐํ•˜๊ธฐ

๐Ÿ”’ ๋ฌธ์ œ์ 
์ฅฌ์Šค๋ฅผ ์ฃผ๋ฌธํ•˜๋Š” ๋ฒ„ํŠผ์˜ title์— ๋”ฐ๋ผ ์ฅฌ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” searchJuice๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ switch๋ฌธ ์•ˆ์— ๋ฒ„ํŠผ์˜ ํƒ€์ดํ‹€์„ ๋ฌธ์ž์—ด๋กœ ์ง์ ‘ ์ž‘์„ฑํ•ด์ฃผ๋‹ˆ ๋งค์ง๋ฆฌํ„ฐ๋Ÿด์ด ๋˜์–ด ๋ฌธ์ž์—ด์˜ ์˜๋ฏธ๋ฅผ ํ•œ ๋ˆˆ์— ์•Œ๊ธฐ ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
private func searchJuice(by buttonTitle: String) -> Juice? {
    switch buttonTitle {
    case "๋”ธ๊ธฐ์ฅฌ์Šค ์ฃผ๋ฌธ":
        return .strawberryJuice
    case "๋ฐ”๋‚˜๋‚˜์ฅฌ์Šค ์ฃผ๋ฌธ":
        return .bananaJuice
    ...
    default:
        return nil
    }
}

๐Ÿ”‘ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

๋งค์ง๋ฆฌํ„ฐ๋Ÿด์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Juiceํƒ€์ž…์˜ ์—ฐ๊ด€๊ฐ’ ํ™œ์šฉ, ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ ํ™œ์šฉ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด๋ดค์ง€๋งŒ ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ ธ ์˜คํžˆ๋ ค ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์งˆ ๊ฒƒ ๊ฐ™์•˜์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์ฐพ๋‹ค๊ฐ€ case๊ฐ€ ์—†๋Š” enum์„ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ฐฉ๋ฒ•์€ ์—ด๊ฑฐํ˜•์ด์ง€๋งŒ case๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ดˆ๊ธฐํ™”๋Š” ์•ˆ๋˜๊ณ , ์ˆœ์ˆ˜ํžˆ namespace๋กœ์„œ๋งŒ ์ž‘๋™ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฅฌ์Šค๋ฉ”์ด์ปค์— ์ ์šฉ์€ ButtonTitle ์—ด๊ฑฐํ˜•์— ํƒ€์ž…ํ”„๋กœํผํ‹ฐ๋กœ ๊ฐ ๋ฒ„ํŠผ์˜ ํƒ€์ดํ‹€์ธ String๊ฐ’์„ ํ• ๋‹นํ•ด์ฃผ์—ˆ๊ณ  ๊ทธ ๊ฐ’์„ ๊ฐ€์ ธ์™€ switch๋ฌธ์—์„œ ํ˜ธ์ถœํ•ด์ค„ ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
private enum ButtonTitle {
    static let strawberryJuiceOrder = "๋”ธ๊ธฐ์ฅฌ์Šค ์ฃผ๋ฌธ"
    static let bananaJuiceOrder = "๋ฐ”๋‚˜๋‚˜์ฅฌ์Šค ์ฃผ๋ฌธ"
    ...
}
    
private func searchJuice(by buttonTitle: String) -> Juice? {
    switch buttonTitle {
    case ButtonTitle.strawberryJuiceOrder:
        return .strawberryJuice
    case ButtonTitle.bananaJuiceOrder:
        return .bananaJuice
		...
    default:
        return nil
    }
}

5๏ธโƒฃ ์ด๋‹ˆ์…œ๋ผ์ด์ €๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ๋‹ค๋ฅธ ํ”„๋กœํผํ‹ฐ์—์„œ ์ดˆ๊ธฐ๊ฐ’ ๋ฐ›๊ธฐ

๐Ÿ”’ ๋ฌธ์ œ์ 
Cannot use instance member 'initialStock' within property initializer; property initializers run before 'self' is available ์ดˆ๊ธฐ๊ฐ’์„ ์ฃผ๋ ค๋Š” ์ƒํ™ฉ์—์„œ ์ด๋‹ˆ์…œ๋ผ์ด์ €๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— .self์— ์ ‘๊ทผํ•ด์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋ ค๊ณ  ํ•ด์„œ ์ด๋Ÿฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
let initialStock = 10
var fruitStock: [Fruits: Int] = [
    .strawberry: initialStock, 
    .banana: initialStock,
    .pineapple: initialStock, 
    .mango: initialStock,
    .kiwi: initialStock
]	

๐Ÿ”‘ ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ์ฒซ๋ฒˆ์งธ

  • ์ฒซ๋ฒˆ์งธ ๋ฐฉ์•ˆ : static ์‚ฌ์šฉ

    staticย ํ‚ค์›Œ๋“œ ์žฅ์ 

    • static์€ ํ•ด๋‹น ๊ตฌ์กฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค๋‚˜ ํด๋ž˜์Šค๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š์•„๋„ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์žฅ์  ๋•Œ๋ฌธ์— ์ „์—ญ์ ์ธ ๊ธฐ๋Šฅ์„ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ํด๋ž˜์Šค๋‚˜ ๊ตฌ์กฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค์™€๋Š” ๋…๋ฆฝ์ ์ธ ๊ฐ’์„ ์ €์žฅํ•  ํ•„์š”๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐย staticย ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ „์—ญ์œผ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์„ค์ •๊ฐ’์ด๋‚˜ ์ƒ์ˆ˜ ๊ฐ’์„ ์ •์˜ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

    staticย ํ‚ค์›Œ๋“œ ๋‹จ์ 

    • static์œผ๋กœ ์„ ์–ธ๋˜๋ฉด ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ฉ”์„œ๋“œ๋Š” ์˜ค๋ฒ„๋ผ์ด๋”ฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
    • staticย ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ ์–ธ๋œ ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ฉ”์„œ๋“œ๋Š” ํด๋ž˜์Šค๋‚˜ ๊ตฌ์กฐ์ฒด ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋‹ค๋ฅธ ๋ชจ๋“ˆ์—์„œ ์ ‘๊ทผํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”ย public static๊ณผ ๊ฐ™์ด ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • staticย ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ ์–ธ๋œ ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ฉ”์„œ๋“œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋‚ด์— ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ํ• ๋‹น๋˜๋ฏ€๋กœ, ๋Ÿฐํƒ€์ž„ ๋™์•ˆ ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๊ฒฝ์šฐ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๋‚˜ ์Šค๋ ˆ๋“œ์—์„œ๋„ ๋ณ€๊ฒฝ๋œ ๊ฐ’์ด ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.
    • ์ข…๋ฃŒ์‹œ๊นŒ์ง€ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ• ๋‹น๋œ ์ฑ„๋กœ ์กด์žฌํ•˜๋ฏ€๋กœ ๋งŽ์€ย staticย ์ƒ์„ฑ์‹œ ํ”„๋กœ๊ทธ๋žจ ํผํฌ๋จผ์Šค์— ์•…์˜ํ–ฅ์„ ์ค„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

    โ†’stactic ์žฅ๋‹จ์ ์„ ๊ณ ๋ คํ–ˆ์„ ๋•Œ ์ง€๊ธˆ ํ˜„์žฌ์— ์ฝ”๋“œ์— ์ ์ ˆํ•œ ๋” ์ข‹์€ ๋ฐฉ์•ˆ์ด ์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
static let initialStock = 10
var fruitStock: [Fruits: Int] = [
    .strawberry: initialStock, 
    .banana: initialStock,
    .pineapple: initialStock, 
    .mango: initialStock,
    .kiwi: initialStock
]	

๐Ÿ”‘ ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ๋‘๋ฒˆ์งธ

  • ๋‘ ๋ฒˆ์งธ ๋ฐฉ์•ˆlazyย ํ‚ค์›Œ๋“œ ์‚ฌ์šฉ

    lazy ํ‚ค์›Œ๋“œ ํŠน์ง•

    • ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ฒ˜์Œ ์‚ฌ์šฉ๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ผ๊ฐ€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ์†Œ์š”๋˜๋Š” ์ž‘์—…์—ย lazyย ๋ฅผ ๋ถ™์ด๋ฉด ์‹ค์ œ ์ž‘์—…์ด ์ง„ํ–‰๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์•„ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค. ์ž‘์—…์ด ๋‹ค๋ฅธ ์ž‘์—…์— ์˜์กด์ ์ธ ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    โ†’ initialStock์€ ์ „์—ญ์ ์œผ๋กœ ์ ‘๊ทผํ•  ํ•„์š”์—†๊ณ ,ย fruitStock๋ฅผ ์ดˆ๊ธฐํ™” ํ•  ๋•Œ๋งŒ ํ•„์š”ํ•˜๋‹ค๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œย static let initialStock์„ ํ™œ์šฉํ•˜๋Š” ๋Œ€์‹ ์—ย fruitStock๋ฅผย lazy var๋กœ ๋งŒ๋“ค์–ด ์ ‘๊ทผ ์‹œ์— ๊ฐ’์„ ํ• ๋‹นํ•˜๋„๋ก ์ˆ˜์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
private let initialStock = 10
private(set) lazy var fruitStock: [Fruits: Int] = [
    .strawberry: initialStock, 
    .banana: initialStock,
    .pineapple: initialStock, 
    .mango: initialStock,
    .kiwi: initialStock
]	

๐Ÿ”‘ ์ตœ์ข… ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

  • init ๋ฉ”์„œ๋“œ ํ™œ์šฉ

    • lazy๋Š” ํ”„๋กœํผํ‹ฐ์˜ ์ดˆ๊ธฐํ™” ๊ณผ์ •์ด ๋ณต์žกํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๊ฐ’์— ์˜์กด์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ ์ดˆ๊ธฐํ™” ๋  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์–ด์„œ ์ฝ”๋“œ์˜ ๋ณต์žก์„ฑ์„ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐฉ์•ˆ์ด ์žˆ์ง€ ์•Š์„๊นŒ ๊ณ ๋ฏผํ•˜๋˜ ์ค‘์— init๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
    • initialStock์˜ ์ดˆ๊ธฐ๊ฐ’์€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„ init๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„์ฃผ์—ˆ๊ณ , fruitStock์€ initialStockํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ์ดˆ๊ธฐ ์žฌ๊ณ ๋ฅผ ์„ค์ •ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

    โ†’ lazyํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด fruitStock์ด ์ฒ˜์Œ ์‚ฌ์šฉ๋  ๋•Œ ์ดˆ๊ธฐํ™”๋˜์—ˆ์ง€๋งŒ ๋ณ€๊ฒฝ๋œ ์ฝ”๋“œ์—์„œ๋Š” FruitStore ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ๋งŒ๋“ค์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ๋” ์ผ์ฐ ์ดˆ๊ธฐํ™”ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ
init(initialStock: Int = 10) {
    self.fruitStock = [.strawberry: initialStock,
                        .banana: initialStock,
                        .pineapple: initialStock,
                        .kiwi: initialStock,
                        .mango: initialStock]
    }

6๏ธโƒฃ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ (Result type)

๐Ÿ”’ ๋ฌธ์ œ์ 
Result Type์˜ success๋ถ€๋ถ„์— Bool๊ฐ’์„ ๋„ฃ์–ด์ฃผ์—ˆ์ง€๋งŒ ์‹ค์งˆ์ ์œผ๋กœ ๋ฐ˜ํ™˜๋˜๋Š” true๊ฐ’์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋“ค์–ด๊ฐ€๋Š” ๊ฐ’์ด true์ด๋“  false์ด๋“  ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰์—๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ๊ณ  ๊ฒฐ๊ณผ์ ์œผ๋กœ success์˜ true๊ฐ’์€ ์“ธ๋ชจ์—†๋Š” ๊ฐ’์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
private func checkFruitStock(_ recipe: [Recipe]) -> Result<Bool, JuiceMakerError> {
    for fruit in recipe {
        guard let stock = fruitStore.fruitStock[fruit.name] else { return .failure(JuiceMakerError.notExistFruit) }
        guard stock >= fruit.quantity else { return .failure(JuiceMakerError.ingredientShortage) }
    }
    return .success(true)
}

๐Ÿ”‘ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•
ํŠน์ •ํ•œ ๊ฐ’์ด ๋ฐ˜ํ™˜๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ณ ์ •๊ด€๋… ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ๊ฐ’์„ ๋„ฃ์–ด ์‹œ๋„ํ•ด๋ณด์•˜์ง€๋งŒ ๊ฒฐ๊ตญ ๋ชจ๋‘ ๋ถˆํ•„์š”ํ•œ ๊ฐ’์ด ๋˜์–ด๋ฒ„๋ ธ๊ณ  ๊ฒฐ๊ณผ์ ์œผ๋กœ๋Š” Void ๋ฐ˜ํ™˜ ๊ฐ’์„ ์ด์šฉํ•ด success๋˜์—ˆ๋‹ค๋Š” ์˜๋ฏธ๋งŒ ๋ฐ˜ํ™˜๋  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
private func checkFruitStock(_ recipe: [Recipe]) -> Result<Void, JuiceMakerError> {
    for fruit in recipe {
        guard let stock = fruitStore.fruitStock[fruit.name] else { return .failure(JuiceMakerError.notExistFruit) }
        guard stock >= fruit.quantity else { return .failure(JuiceMakerError.ingredientShortage) }
    }
    return .success(())
}

7๏ธโƒฃ ๋ณต์žกํ•œ ํƒ€์ž…

๐Ÿ”’ ๋ฌธ์ œ์ 
Juice ํƒ€์ž…์˜ recipe ํ”„๋กœํผํ‹ฐ๋Š” ์ฅฌ์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ ํ•„์š”ํ•œ ๊ณผ์ผ์˜ ์ข…๋ฅ˜์™€ ์ˆ˜๋Ÿ‰์„ ๊ฐ™์ด ๋ฐ˜ํ™˜ํ•ด์ฃผ์–ด์•ผํ•˜๊ณ , ํ•„์š”ํ•œ ๊ณผ์ผ์˜ ์ข…๋ฅ˜๊ฐ€ 2๊ฐœ ์ด์ƒ์ผ ์ˆ˜ ์žˆ์œผ๋‹ˆ ํŠœํ”Œ์˜ ๋ฐฐ์—ด ํƒ€์ž…์œผ๋กœ ์„ค์ •ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด recipe ํ”„๋กœํผํ‹ฐ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ์˜ ์ •์˜ ๋ถ€๋ถ„์ด ๊ธธ์–ด์ ธ ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์กŒ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
private func checkFruitStock(_ recipe: [(name: Fruits, quantity: Int)]) -> Result<Void, StockError> {}

๐Ÿ”‘ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•
typealias ๋ฅผ ์ด์šฉํ•˜์—ฌ ํŠœํ”Œ ๋ฐฐ์—ด ํƒ€์ž…์„ ์ •์˜ํ•˜์˜€๋”๋‹ˆ ์ฝ”๋“œ๊ฐ€ ํ›จ์”ฌ ๊น”๋”ํ•ด์กŒ๊ณ , naming์„ ํ†ตํ•ด ํŠœํ”Œ ๋ฐฐ์—ด ํƒ€์ž…์ด recipe์˜ ํƒ€์ž…์ด๋ผ๋Š” ๊ฒƒ์ด ์กฐ๊ธˆ ๋” ๋ช…ํ™•ํ•ด์ง€๋Š” ํšจ๊ณผ๋ฅผ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
typealias Recipe = (name: Fruits, quantity: Int)

private func checkFruitStock(_ recipe: [Recipe]) -> Result<Void, StockError> {}

8๏ธโƒฃ ๋งค๊ฐœ๋ณ€์ˆ˜ ์—†์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ

๐Ÿ”’ ๋ฌธ์ œ์ 
receiveRecipe๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์ง€ ์•Š๊ณ  ์ •ํ•ด์ง„ ์ฅฌ์Šค๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ทธ ๋’ค์— ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜์–ด ํ•ด๋‹น ์ผ€์ด์Šค์˜ ๊ฐ’๋งŒ ๊ฐ€์ ธ์˜ค๋Š” ์—ญํ• ์„ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋กœ์ง ์ƒ์— ํฐ ๋ฌธ์ œ๋Š” ์—†์—ˆ์ง€๋งŒ ๊ตณ์ด ๋ฉ”์„œ๋“œ๊นŒ์ง€ ์‚ฌ์šฉํ•˜์—ฌ ๋ ˆ์‹œํ”ผ์˜ ๋ฐ˜ํ™˜๊ฐ’๋งŒ์„ ๊ฐ€์ ธ์˜ฌ ํ•„์š”๋Š” ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
func receiveRecipe() -> [Recipe] {
    switch self {
    case .strawberryJuice:
        return [(.strawberry, 16)]
    case .bananaJuice:
        return [(.banana, 2)]
    case .kiwiJuice:
        return [(.kiwi, 3)]
    case .pineappleJuice:
        return [(.pineapple, 2)]
    case .strawberryBananaJuice:
        return [(.strawberry, 10), (.banana, 1)]
    case .mangoJuice:
        return [(.mango, 3)]
    case .mangoKiwiJuice:
        return [(.mango, 2), (.kiwi, 1)]
    }
}

๐Ÿ”‘ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•
๊ฒฐ๊ณผ์ ์œผ๋กœ receiveRecipe ๋ฉ”์„œ๋“œ๋ฅผ recipe ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋กœ ๋ณ€๊ฒฝ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ
var recipe: [Recipe] {
    switch self {
    case .strawberryJuice:
        return [(.strawberry, 16)]
    case .bananaJuice:
        return [(.banana, 2)]
    case .kiwiJuice:
        return [(.kiwi, 3)]
    case .pineappleJuice:
        return [(.pineapple, 2)]
    case .strawberryBananaJuice:
        return [(.strawberry, 10), (.banana, 1)]
    case .mangoJuice:
        return [(.mango, 3)]
    case .mangoKiwiJuice:
        return [(.mango, 2), (.kiwi, 1)]
    }
}

๐Ÿ‘ฅ ํŒ€ ํšŒ๊ณ 

์šฐ๋ฆฌ ํŒ€์ด ์ž˜ํ•œ ์ 

  • ๊ทธ๋ผ์šด๋“œ ๋ฃฐ๋กœ ์ •ํ•œ ์‹œ๊ฐ„์— ์ž˜ ๋ชจ์ด๋ ค ๋…ธ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์„œ๋กœ ๋ชจ๋ฅด๋Š” ๋ถ€๋ถ„์— ๋Œ€ํ•ด ์ž์œ ๋กญ๊ฒŒ ์งˆ๋ฌธ ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํŒ€์›์—๊ฒŒ ์•„๋Š” ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ์ž์„ธํ•˜๊ฒŒ ์„ค๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํŒ€ ํ”„๋กœ์ ํŠธ์˜ ์˜์˜์— ๋งž๊ฒŒ ํ•จ๊ป˜ ๊ณ ๋ฏผํ•˜๋Š” ๊ณผ์ •์—์„œ ์–ป๋Š” ๊ฒŒ ๋งŽ์•˜์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ ํŒ€์ด ๊ณ ์ณ์•ผ ํ•  ๋ถ€๋ถ„

  • ํ”„๋กœ์ ํŠธ์— ์น˜์ค‘๋˜์–ด ๊ฐœ์ธ๊ณต๋ถ€์— ๋ถ€์กฑํ•จ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

To. yyss99(์™€์ด)

  • Yetti: ๋ชจ๋ฅด๋Š” ๋ถ€๋ถ„์€ ํ™•์‹คํ•˜๊ฒŒ ์ดํ•ดํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๋Š” ๋ชจ์Šต์ด ์ข‹์•˜์Šต๋‹ˆ๋‹ค! ๐Ÿ‘
  • Mary: ์ •ํ™•ํ•˜๊ฒŒ ์ดํ•ดํ•˜์‹œ๋ ค๋Š” ์—ด์ • ๋•๋ถ„์— ์ €๋„ ๋ถ€์กฑํ•œ ๋ถ€๋ถ„์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๊ฒŒ ๋˜์–ด ๊ณต๋ถ€์— ๋งŽ์€ ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค ๐Ÿ‘

To. Mary(๋ฉ”๋ฆฌ)

  • yyss99(์™€์ด): ๋”ฐ๋กœ ๊ณต๋ถ€ํ•œ ๊ฒƒ๋“ค์„ ์ž˜ ๊ณต์œ ํ•ด์ฃผ์‹œ๊ณ  ์•Œ๊ธฐ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•ด์ฃผ์…”์„œ ์ข‹์•˜์Šต๋‹ˆ๋‹ค. ๐Ÿ˜†
  • Yetti: ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ๋” ๋‚˜์€ ์ฝ”๋“œ๊ฐ€ ๋ ์ง€๋ฅผ ์ง€์†์ ์œผ๋กœ ๊ณ ๋ฏผํ•˜๋Š” ๋ชจ์Šต์ด ์ข‹์•˜์Šต๋‹ˆ๋‹ค!๐Ÿ‘

To. Yetti(์˜ˆํ‹ฐ)

  • yyss99(์™€์ด): ์ž์œ ๋กญ๊ฒŒ ์งˆ๋ฌธํ•˜๊ณ  ๋ชจ๋ฅด๋Š” ๋ถ€๋ถ„์— ๋Œ€ํ•ด ๊ณต์œ ํ•ด์ฃผ์…”์„œ ๊ฐ™์ด ๋ฐฐ์šธ ์ˆ˜ ์žˆ๋Š” ๋ถ„์œ„๊ธฐ๋ฅผ ํ˜•์„ฑํ•ด ์ฃผ์…”์„œ ์ •๋ง ์ข‹์•˜์Šต๋‹ˆ๋‹ค.๐Ÿ˜†
  • Mary: ํ”„๋กœ์ ํŠธ ์ „๋ฐ˜์ ์ธ ๋ถ„์œ„๊ธฐ๋ฅผ ์ž˜ ์ด๋Œ์–ด์ฃผ์…จ๋˜ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์—ด์ •์ ์œผ๋กœ ๊ณต๋ถ€ํ•˜์‹œ๋Š” ๋ชจ์Šต์ด ์ข‹์•˜์Šต๋‹ˆ๋‹ค. ๐Ÿ‘

๐Ÿ“‘ ์ฐธ๊ณ ์ž๋ฃŒ

ios-juice-maker's People

Contributors

ios-yetti avatar maryjo-github avatar yagom avatar yy-ss99 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.