(Every architecture I've tried sucks, but I think this one sucks the least.)
The UI now has one type alias Model per page, instead of trying to have "components" each with their own Model/Msg types.
Pros of this approach:
Simpler: easier to look at each page and see what it can do, since all of the Msgs are in one place instead of encapsulated in subcomponents.
Less magic: previously, I'd written a shim (called Page) interposed between the Elm runtime and most of the UI code, which maintained some Globals object and passed it into everything's view function. I was always kinda of intimidated by this. The flattened approach eliminates the need for this shim.
Cons of this approach:
Lots of copy-paste: e.g., literally every single page has ~identical update code that defines how to handle auth events.
Hard to nest: it's kinda awkward to have more than two conceptual levels. (E.g., if ViewUserPage wants to contain a PredictionListWidget which contains several PredictionWidgets, then PredictionListWidget.Config needs to... needs to, like, contain a factory function for PredictionWidget.Configs... or something. Never figured this out.)
(Every architecture I've tried sucks, but I think this one sucks the least.)
The UI now has one
type alias Model
per page, instead of trying to have "components" each with their own Model/Msg types.Pros of this approach:
Page
) interposed between the Elm runtime and most of the UI code, which maintained someGlobals
object and passed it into everything'sview
function. I was always kinda of intimidated by this. The flattened approach eliminates the need for this shim.Cons of this approach:
update
code that defines how to handle auth events.ViewUserPage
wants to contain aPredictionListWidget
which contains severalPredictionWidget
s, thenPredictionListWidget.Config
needs to... needs to, like, contain a factory function forPredictionWidget.Config
s... or something. Never figured this out.)