Last active
April 25, 2016 09:11
-
-
Save eofster/4d0386267ad7f6380afd422d4de68bee to your computer and use it in GitHub Desktop.
VendingMachine with extracted Inventory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Item { | |
let price: Int | |
let name: String | |
var count: Int | |
} | |
protocol Inventory { | |
func itemNamed(name: String) throws -> Item | |
func remove(item: Item) throws | |
} | |
class VendingMachine { | |
let inventory: Inventory | |
private(set) var coins: Int = 0 | |
init(inventory: Inventory) { | |
self.inventory = inventory | |
} | |
func deposit(coins: Int) { | |
self.coins += coins | |
} | |
func dispense(item: Item) { | |
print("Dispensing \(item)") | |
} | |
func vend(itemNamed name: String) throws { | |
let item = try inventory.itemNamed(name) | |
try reduceCoinsBy(item.price) | |
try removeFromInventory(item) | |
dispense(item) | |
} | |
private func reduceCoinsBy(price: Int) throws { | |
try validatePrice(price) | |
coins -= price | |
} | |
private func removeFromInventory(item: Item) throws { | |
do { | |
try inventory.remove(item) | |
} catch { | |
deposit(item.price) | |
throw error | |
} | |
} | |
private func validatePrice(price: Int) throws { | |
guard coins >= price else { | |
throw VendingMachineError.InsufficientFunds(coinsNeeded: price - coins) | |
} | |
} | |
} | |
enum VendingMachineError: ErrorType { | |
case InsufficientFunds(coinsNeeded: Int) | |
} | |
class SimpleInventory: Inventory { | |
private var items = [ | |
"Candy Bar": Item(price: 12, name: "Candy Bar", count: 1), | |
"Chips" : Item(price: 10, name: "Chips", count: 4), | |
"Pretzels" : Item(price: 7, name: "Pretzels", count: 11) | |
] | |
func itemNamed(name: String) throws -> Item { | |
if let item = items[name] { | |
return item | |
} else { | |
throw InventoryError.InvalidSelection | |
} | |
} | |
func remove(item: Item) throws { | |
try validateCount(item.count) | |
var item = item | |
item.count -= 1 | |
items[item.name] = item | |
} | |
private func validateCount(count: Int) throws { | |
if count == 0 { | |
throw InventoryError.OutOfStock | |
} | |
} | |
} | |
enum InventoryError: ErrorType { | |
case InvalidSelection | |
case OutOfStock | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment