A RealWorld example app version to demonstrate how to structure an Elm application using the Effect pattern.
The application is initially based on the great rtfeldman/elm-spa-example.
Most of complex Elm application architecture examples out there use some variant of the pattern used in rtfeldman/elm-spa-example or the OutMsg pattern to have a updatable global state available in each subpage (a
Session for example). The former passes the data from subpage to subpage during their initialization, so each subpage can modify it locally, the later returns an additional message from their
update function handled in the top level one.
My favorite pattern to do this (and more), the Effect pattern, is most often described only in the context of tests and
Cmd, for example by avh4/elm-program-test, but it can be extended to state changes and offers a clean and versatile way to handle different use cases of complex applications.
The extended Effect pattern used in this application consists in definining an
Effect custom type that can represent all the effects that
update functions want to produce.
These effects can represent:
- a request to change the state at an upper level (for example an URL change from a subpage without an anchor)
Having a way to request an upper level state change, with or without an associated actual
Cmd msg, is what lets this extended effect pattern combine the benefits of the
OutMsg one with the ones from the usual effect pattern used for tests.
There are several benefits to this approach that makes it a valuable pattern for complex applications, including:
All the effects are defined in a single
Effectmodule, which acts as an internal API for the whole application that is guaranteed to list every possible effect.
Effects can be inspected and tested, not like
Cmdvalues. This allows to test all the application effects, including simulated HTTP requests.
updatefunctions keep a clean and concise
Msg -> Model -> ( Model, Effect Msg )signature.
Effectvalues carry the minimum information required, some parameters like the
Browser.Navigation.keyare needed only in the effects
performfunction, which frees the developer from passing them to functions all over the application.
Ignored Stringcan be used for the whole application.
Differences with elm-spa-example
To focus on the architecture changes and to offer a different perspective, the elm-spa-example has been quite heavily reworked with the following changes:
- Refactored to use an Effect type and application
- Upgraded dependencies, including
- Removed client-side fields validation to focus subpage code on effects
- Put all specific styled view code into a single
Viewmodule to declutter subpages code
- Replaced slow loading detection by a simple CSS transition
- Refactored according to personal preferences
- Removed custom assets
Testing programs with Cmds with
- A service pattern: @mzero explored a variant of this pattern to implement application wide services.
- The Effect pattern: Transparent updates in Elm.
elm-spa-example from Richard Feldman made me realize how much work went into it.
I would most likely never had released this version without such a solid base, so thank you very much @rtfeldman.