SlideShare a Scribd company logo
1 of 46
Download to read offline
SOME STUFF I WAS THINKING ABOUT STATE
MACHINES AND TYPES
FINITE STATE
MACHINES
1. About Finite State Machines
2. Finite State Machines and Types
3. Using State in an View Controller
QUESTION: HAS ANY ONE
USED STATE MACHINES?
FINITE STATE MACHINES ARE
A SERIES OF STATES AND
TRANSITIONS.
THEY CAN BE USEFUL FOR VARIOUS REASONS:
▸ They are simple to draw
▸ They are simple to understand
▸ They make the state of your application explicit
▸ They are easy to program
FOR THIS REASON, THEY CAN
BE A NICE WAY TO MODEL THE
BEHAVIOR OF YOUR
APPLICATION.
AN EXAMPLE API
var machine = StateMachine()
var loadingState = State(name: "Loading")
var emptyState = State(name: "Empty")
var displayState = State(name: "Display")
loadingState.addTransition(with: "loaded", to: emptyState) { state in
guard loadedModel.count > 0 {
machine.transition(with: "firstItemAdded")
return
}
tableView.backgroundView = EmptyMessageView()
}
emptyState.addTransition(with: "firstItemAdded", to: displayState) { state in
tableView.backgroundView = nil
tableView.reloadData()
}
displayState.addTransition(with: "onlyItemRemoved", to: displayState) { state in
tableView.backgroundView = EmptyMessageView()
}
displayState.addTransition(with: "itemAdded", to: displayState) { state in
// animate item addition
}
machine.states = [loadingState, emptyState, displayState]
machine.initialState = loadingState
RUNNING A TRANSITION
// Inside of a network callback
func deleteObject() {
// delete object
if loadedModel.count == 0 {
machine.transition(with: "onlyItemRemoved")
}
}
QUESTION: WHAT SHOULD HAPPEN IN THIS CASE?
// I am in the "loading" state
machine.transition(with: "onlyItemRemoved")
QUESTION: IF STATE
MACHINES ARE EASY TO
MAKE AND EASY TO REASON
ABOUT, WHY DON'T WE USE
THEM MORE?
THE NUMBER OF STATES
OFTEN INCREASES VERY,
VERY QUICKLY.
2 STATES
class ViewController: UIViewController {
let switch1: UISwitch
}
4 STATES
class ViewController: UIViewController {
let switch1: UISwitch
let switch2: UISwitch
}
8 STATES
class ViewController: UIViewController {
let switch1: UISwitch
let switch2: UISwitch
let switch3: UISwitch
}
UI CODE OFTEN HAS A LOT OF
STATES, AS A CONSEQUENCE,
MAKING THOSE STATES
EXPLICIT MEANS YOU HAVE
TO DEAL WITH THEM
SO STATE MACHINES MAY WORK BEST WHEN
THE NUMBER OF STATES IS SMALL.
PART 2: STATE
MACHINES AND
TYPES
YOU MIGHT NOT NOTICE IT BY LOOKING AT A
LOT OF STATE MACHINES LIBRARIES, BUT IT
IS ACTUALLY VERY EASY TO MAKE STATES
INTO INSTANCES AND TRANSITIONS INTO
METHODS.
struct LoadingState {
func loaded() -> EmptyState
}
struct EmptyState {
func oneItemAdded() -> DisplayState
}
struct DisplayState {
func onlyItemDeleted() -> EmptyState
func itemAdded() -> DisplayState
}
THIS WAY YOU CAN USE THE
COMPILER TO PREVENT THE
APPLICATION FROM EVER
ENTERING AN INCONSISTENT
STATE.
E.G. THE PREVIOUSLY DISCUSSED PROBLEM CAN'T HAPPEN
// Might cause an issue at runtime
machine.transition(with: "onlyItemRemoved")
// vs.
// Won't compile
state = loadingState.onlyItemRemoved()
PART 3: USING STATE IN A
VIEW CONTROLLER
class ViewController: UIViewController {
// This item is expensive to load.
// I show the view controller,
// then set the item property once
// it is loaded.
var item: Item?
}
A CONSEQUENCE
func tableView(_ tableView: UITableView, didSelectRow at: IndexPath) {
guard let item = item else {}
// ...
}
func tableView(_ tableView: UITableView, cellForRowAt at: IndexPath) {
guard let item = item else {}
// ...
}
func tableView(_ tableView: UITableView, shouldDoSomethingElse at: IndexPath) {
guard let item = item else {}
// ...
}
// ...
ONCE THE OBJECT IS LOADED, IT NEVER
BECOMES UNLOADED, BUT I STILL HAVE TO
DEAL WITH THE OPTIONAL VALUE FOR THE
LIFECYCLE OF THE VIEW CONTROLLER.
OPTIONALITY DOES NOT HAVE
A WAY OF EXPRESSING THAT
ONCE SOMETHING IS SET,
IT CANNOT BE UNSET.
UNLESS IT CAN?
var data: [Item]!
I DON'T WANT TO USE AN IMPLICITLY-
UNWRAPPED OPTIONAL HERE BECAUSE I AM
INTERACTING WITH APPLE'S FRAMEWORKS.
I AM NOT SURE ABOUT THE TIMING OF THE
CALLS WHEN DEALING WITH A FRAMEWORK I
DON'T CONTROL.
protocol State {}
class LoadingState: State {
func loaded() -> EmptyState
}
class EmptyState: State {
// We know that data is not nil here, so it
// can have a non-optional reference
var item: Item
func oneItemAdded() -> DisplayState
}
// Display State could just be the tableView data source
class DisplayState: State, UITableViewDataSource {
var item: Item // We know that data is not nil here
func onlyItemDeleted() -> EmptyState
func itemAdded() -> DisplayState
}
ASIDE
I MADE THE STATE OBJECTS CLASSES
RATHER THAN STRUCTS SO THAT
DisplayState CAN ACT AS A TABLE
VIEW DATA SOURCE.
QUESTION: DOES ANYONE ELSE USE OBJECTS
RATHER THAN STRUCTS IN CERTAIN CASES
JUST BECAUSE YOU WANT TO INTERACT WITH
APPLE FRAMEWORKS?
END ASIDE
class ViewController: UIViewController {
var state: State
var item: Item?
init() {
state = LoadingState()
}
}
var item: Item? {
didSet {
if let item = item, let loadingState = state as? LoadingState {
let emptyState = loadingState.loaded()
emptyState.item = item
self.state = emptyState
}
}
}
func addObject() {
// add object
if item.listOfSomething.count == 1, let emptyState = state as? EmptyState {
self.state = emptyState.oneItemAdded()
}
}
func deleteObject() {
// delete object
if item.listOfSomething.count < 1, let displayState = state as? DisplayState {
self.state = displayState.onlyItemDeleted()
} else {
// Problem: What if state is not a DisplayState?
}
}
DisplayState IS ACTUALLY THE TABLE VIEW DATA
SOURCE, SO THE ITEM IS NOT NIL OR EMPTY.
func tableView(_ tableView: UITableView, didSelectRow at indexPath: IndexPath) {
let something = item.listOfSomething[indexPath.row]
// ...
}
QUESTION: WAS THIS EXERCISE IN MAKING
EXPLICIT STATE NECESSARY? COULDN'T WE
JUST, FOR EXAMPLE, MAKE CHILD VIEW
CONTROLLERS AND TRANSITION IN BETWEEN
THEM?
CONCLUSION:
▸ In some cases we might be able represent view controller state
explicitly with a state machine.
▸ If the state instances have references to objects which must not be
nil in their scope, we might be able to avoid needing to unwrap a lot
of optionals. (More generally, we might be able to more closely
model the lifecycle of the object.)

More Related Content

Similar to Some Stuff I was thinking about state machines and types

Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahoda
Droidcon Berlin
 

Similar to Some Stuff I was thinking about state machines and types (20)

iOS Talks 6: Unit Testing
iOS Talks 6: Unit TestingiOS Talks 6: Unit Testing
iOS Talks 6: Unit Testing
 
React state managmenet with Redux
React state managmenet with ReduxReact state managmenet with Redux
React state managmenet with Redux
 
Architectures in the compose world
Architectures in the compose worldArchitectures in the compose world
Architectures in the compose world
 
From mvc to redux: 停看聽
From mvc to redux: 停看聽From mvc to redux: 停看聽
From mvc to redux: 停看聽
 
Redux training
Redux trainingRedux training
Redux training
 
Android Application managing activites.pptx
Android Application managing activites.pptxAndroid Application managing activites.pptx
Android Application managing activites.pptx
 
Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React
 
Introducing Vuex in your project
Introducing Vuex in your projectIntroducing Vuex in your project
Introducing Vuex in your project
 
State manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to VuexState manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to Vuex
 
State of the state
State of the stateState of the state
State of the state
 
Do iOS Presentation - Mobile app architectures
Do iOS Presentation - Mobile app architecturesDo iOS Presentation - Mobile app architectures
Do iOS Presentation - Mobile app architectures
 
Unidirectional Data Flow with Reactor
Unidirectional Data Flow with ReactorUnidirectional Data Flow with Reactor
Unidirectional Data Flow with Reactor
 
Ngrx slides
Ngrx slidesNgrx slides
Ngrx slides
 
Force Flutter to Rebuild or Redraw All Widgets.pptx
Force Flutter to Rebuild or Redraw All Widgets.pptxForce Flutter to Rebuild or Redraw All Widgets.pptx
Force Flutter to Rebuild or Redraw All Widgets.pptx
 
MVI - Managing State The Kotlin Way
MVI - Managing State The Kotlin WayMVI - Managing State The Kotlin Way
MVI - Managing State The Kotlin Way
 
Higher-Order Components — Ilya Gelman
Higher-Order Components — Ilya GelmanHigher-Order Components — Ilya Gelman
Higher-Order Components — Ilya Gelman
 
Improving android experience for both users and developers
Improving android experience for both users and developersImproving android experience for both users and developers
Improving android experience for both users and developers
 
Droidcon2013 android experience lahoda
Droidcon2013 android experience lahodaDroidcon2013 android experience lahoda
Droidcon2013 android experience lahoda
 
Don't Make Android Bad... Again
Don't Make Android Bad... AgainDon't Make Android Bad... Again
Don't Make Android Bad... Again
 
React redux
React reduxReact redux
React redux
 

More from gillygize (8)

Manual Layout Revisited
Manual Layout RevisitedManual Layout Revisited
Manual Layout Revisited
 
Reactive cocoa
Reactive cocoaReactive cocoa
Reactive cocoa
 
Optimize llvm
Optimize llvmOptimize llvm
Optimize llvm
 
Connecting to a REST API in iOS
Connecting to a REST API in iOSConnecting to a REST API in iOS
Connecting to a REST API in iOS
 
State ofappdevelopment
State ofappdevelopmentState ofappdevelopment
State ofappdevelopment
 
ViewController/State
ViewController/StateViewController/State
ViewController/State
 
Two-StageCreation
Two-StageCreationTwo-StageCreation
Two-StageCreation
 
Categories
CategoriesCategories
Categories
 

Recently uploaded

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 

Recently uploaded (20)

MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...
 

Some Stuff I was thinking about state machines and types

  • 1. SOME STUFF I WAS THINKING ABOUT STATE MACHINES AND TYPES
  • 2.
  • 4. 1. About Finite State Machines 2. Finite State Machines and Types 3. Using State in an View Controller
  • 5. QUESTION: HAS ANY ONE USED STATE MACHINES?
  • 6. FINITE STATE MACHINES ARE A SERIES OF STATES AND TRANSITIONS.
  • 7.
  • 8. THEY CAN BE USEFUL FOR VARIOUS REASONS: ▸ They are simple to draw ▸ They are simple to understand ▸ They make the state of your application explicit ▸ They are easy to program
  • 9. FOR THIS REASON, THEY CAN BE A NICE WAY TO MODEL THE BEHAVIOR OF YOUR APPLICATION.
  • 10. AN EXAMPLE API var machine = StateMachine() var loadingState = State(name: "Loading") var emptyState = State(name: "Empty") var displayState = State(name: "Display")
  • 11. loadingState.addTransition(with: "loaded", to: emptyState) { state in guard loadedModel.count > 0 { machine.transition(with: "firstItemAdded") return } tableView.backgroundView = EmptyMessageView() } emptyState.addTransition(with: "firstItemAdded", to: displayState) { state in tableView.backgroundView = nil tableView.reloadData() } displayState.addTransition(with: "onlyItemRemoved", to: displayState) { state in tableView.backgroundView = EmptyMessageView() } displayState.addTransition(with: "itemAdded", to: displayState) { state in // animate item addition }
  • 12. machine.states = [loadingState, emptyState, displayState] machine.initialState = loadingState
  • 13. RUNNING A TRANSITION // Inside of a network callback func deleteObject() { // delete object if loadedModel.count == 0 { machine.transition(with: "onlyItemRemoved") } }
  • 14. QUESTION: WHAT SHOULD HAPPEN IN THIS CASE? // I am in the "loading" state machine.transition(with: "onlyItemRemoved")
  • 15. QUESTION: IF STATE MACHINES ARE EASY TO MAKE AND EASY TO REASON ABOUT, WHY DON'T WE USE THEM MORE?
  • 16. THE NUMBER OF STATES OFTEN INCREASES VERY, VERY QUICKLY.
  • 17. 2 STATES class ViewController: UIViewController { let switch1: UISwitch }
  • 18. 4 STATES class ViewController: UIViewController { let switch1: UISwitch let switch2: UISwitch }
  • 19. 8 STATES class ViewController: UIViewController { let switch1: UISwitch let switch2: UISwitch let switch3: UISwitch }
  • 20. UI CODE OFTEN HAS A LOT OF STATES, AS A CONSEQUENCE, MAKING THOSE STATES EXPLICIT MEANS YOU HAVE TO DEAL WITH THEM
  • 21. SO STATE MACHINES MAY WORK BEST WHEN THE NUMBER OF STATES IS SMALL.
  • 23. YOU MIGHT NOT NOTICE IT BY LOOKING AT A LOT OF STATE MACHINES LIBRARIES, BUT IT IS ACTUALLY VERY EASY TO MAKE STATES INTO INSTANCES AND TRANSITIONS INTO METHODS.
  • 24. struct LoadingState { func loaded() -> EmptyState } struct EmptyState { func oneItemAdded() -> DisplayState } struct DisplayState { func onlyItemDeleted() -> EmptyState func itemAdded() -> DisplayState }
  • 25. THIS WAY YOU CAN USE THE COMPILER TO PREVENT THE APPLICATION FROM EVER ENTERING AN INCONSISTENT STATE.
  • 26. E.G. THE PREVIOUSLY DISCUSSED PROBLEM CAN'T HAPPEN // Might cause an issue at runtime machine.transition(with: "onlyItemRemoved") // vs. // Won't compile state = loadingState.onlyItemRemoved()
  • 27. PART 3: USING STATE IN A VIEW CONTROLLER
  • 28. class ViewController: UIViewController { // This item is expensive to load. // I show the view controller, // then set the item property once // it is loaded. var item: Item? }
  • 29. A CONSEQUENCE func tableView(_ tableView: UITableView, didSelectRow at: IndexPath) { guard let item = item else {} // ... } func tableView(_ tableView: UITableView, cellForRowAt at: IndexPath) { guard let item = item else {} // ... } func tableView(_ tableView: UITableView, shouldDoSomethingElse at: IndexPath) { guard let item = item else {} // ... } // ...
  • 30. ONCE THE OBJECT IS LOADED, IT NEVER BECOMES UNLOADED, BUT I STILL HAVE TO DEAL WITH THE OPTIONAL VALUE FOR THE LIFECYCLE OF THE VIEW CONTROLLER.
  • 31. OPTIONALITY DOES NOT HAVE A WAY OF EXPRESSING THAT ONCE SOMETHING IS SET, IT CANNOT BE UNSET.
  • 32. UNLESS IT CAN? var data: [Item]!
  • 33. I DON'T WANT TO USE AN IMPLICITLY- UNWRAPPED OPTIONAL HERE BECAUSE I AM INTERACTING WITH APPLE'S FRAMEWORKS.
  • 34. I AM NOT SURE ABOUT THE TIMING OF THE CALLS WHEN DEALING WITH A FRAMEWORK I DON'T CONTROL.
  • 35. protocol State {} class LoadingState: State { func loaded() -> EmptyState } class EmptyState: State { // We know that data is not nil here, so it // can have a non-optional reference var item: Item func oneItemAdded() -> DisplayState } // Display State could just be the tableView data source class DisplayState: State, UITableViewDataSource { var item: Item // We know that data is not nil here func onlyItemDeleted() -> EmptyState func itemAdded() -> DisplayState }
  • 36. ASIDE
  • 37. I MADE THE STATE OBJECTS CLASSES RATHER THAN STRUCTS SO THAT DisplayState CAN ACT AS A TABLE VIEW DATA SOURCE.
  • 38. QUESTION: DOES ANYONE ELSE USE OBJECTS RATHER THAN STRUCTS IN CERTAIN CASES JUST BECAUSE YOU WANT TO INTERACT WITH APPLE FRAMEWORKS?
  • 40. class ViewController: UIViewController { var state: State var item: Item? init() { state = LoadingState() } }
  • 41. var item: Item? { didSet { if let item = item, let loadingState = state as? LoadingState { let emptyState = loadingState.loaded() emptyState.item = item self.state = emptyState } } }
  • 42. func addObject() { // add object if item.listOfSomething.count == 1, let emptyState = state as? EmptyState { self.state = emptyState.oneItemAdded() } }
  • 43. func deleteObject() { // delete object if item.listOfSomething.count < 1, let displayState = state as? DisplayState { self.state = displayState.onlyItemDeleted() } else { // Problem: What if state is not a DisplayState? } }
  • 44. DisplayState IS ACTUALLY THE TABLE VIEW DATA SOURCE, SO THE ITEM IS NOT NIL OR EMPTY. func tableView(_ tableView: UITableView, didSelectRow at indexPath: IndexPath) { let something = item.listOfSomething[indexPath.row] // ... }
  • 45. QUESTION: WAS THIS EXERCISE IN MAKING EXPLICIT STATE NECESSARY? COULDN'T WE JUST, FOR EXAMPLE, MAKE CHILD VIEW CONTROLLERS AND TRANSITION IN BETWEEN THEM?
  • 46. CONCLUSION: ▸ In some cases we might be able represent view controller state explicitly with a state machine. ▸ If the state instances have references to objects which must not be nil in their scope, we might be able to avoid needing to unwrap a lot of optionals. (More generally, we might be able to more closely model the lifecycle of the object.)