Probably the biggest mistake was in how we designed the Model. We tried to use it as a "database". So for example, when we switched to a page, we would load the data for that page into a property on the model. Then we would reuse the data on another page. However, this led to a lot of code just to check/maintain this shared data. And it was the source of many state-based bugs. (One page left the data in X state, but another page expected it in Y state. Or one page needed field Q but the other page didn't for its view.)
Ultimately, our use cases required the app not be offline-capable and our users really preferred getting the latest data from the API any time they switched pages. So we dropped this shared state model. We went to a strategy where the model represents the state of UI elements. So, pages are part of a DU (aka custom type) because only one can be shown at a time. So when the user switches pages, all the data from the other page is gone. No need to reset it or make sure it is left in a certain state.
So in the end, our model ends up looking more like this. Code is off the top of my head.
typealiasModel={apiToken:String,currentPage:Page}typePage=Home|OrderViewOrderViewState-- others like OrderListtypealiasOrderViewState{orderId:String,orderData:RemoteOrderData}typeRemotea=Loading|LoadFailedHttp.Error|Loadeda
The way we initially did state also led to weird extra routing types. Those became unnecessary once we switched to this model. It maps very cleanly to/from navigation URLs. It is easy to parse the URL /order/{orderId} and convert it into the OrderView page:
Hey. I'm curious to know what were the mistakes.
Probably the biggest mistake was in how we designed the Model. We tried to use it as a "database". So for example, when we switched to a page, we would load the data for that page into a property on the model. Then we would reuse the data on another page. However, this led to a lot of code just to check/maintain this shared data. And it was the source of many state-based bugs. (One page left the data in X state, but another page expected it in Y state. Or one page needed field Q but the other page didn't for its view.)
Ultimately, our use cases required the app not be offline-capable and our users really preferred getting the latest data from the API any time they switched pages. So we dropped this shared state model. We went to a strategy where the model represents the state of UI elements. So, pages are part of a DU (aka custom type) because only one can be shown at a time. So when the user switches pages, all the data from the other page is gone. No need to reset it or make sure it is left in a certain state.
So in the end, our model ends up looking more like this. Code is off the top of my head.
The way we initially did state also led to weird extra routing types. Those became unnecessary once we switched to this model. It maps very cleanly to/from navigation URLs. It is easy to parse the URL
/order/{orderId}
and convert it into theOrderView
page:Going the other way is easy too.
Anyway, I think modeling as a database was the main thing that we did wrong at first.
Got it. Thank you!