DEV Community

Discussion on: Immutability - something worth striving for

Collapse
 
kspeakman profile image
Kasey Speakman • Edited

Thanks for the link to the article. We use some of those same patterns.

Lately, we have started to match both model and msg in our update function. Since messages are top level, you can technically receive a message which is not valid for the current view. This accounts for that case and also nicely unwraps the page-level model and msg all at once.

// F#, using Elmish
match model.Page, msg with
...
| CoursePage pageModel, CourseMsg pageMsg ->
    let nPageModel, effects = Course.update pageMsg pageModel
    { model with Page = CoursePage nPageModel }, effects
| CoursePage pageModel, badMsg ->
    // log?
    model, []

We handle page changes within the same structure.

match model.Page, msg with
| _, OpenCoursePage courseId ->
    let nPageModel, effects = Course.init courseId
    { model with Page = CoursePage nPageModel }, effects
...

This works with navigation. For example, it is pretty easy to parse the URL /course/abc123 into OpenCoursePage "abc123". We ended up with too many OpenXX messages, so they were organized under a wrapper message tag like OpenPage .... Then a central function is responsible for calling the correct page init.

Since these are recurring patterns, I've tried to parameterize it different ways. But that requires some extra abstraction/scaffolding. And then that abstraction must be learned by other devs (including Future Me when I've been away from the code for 6 months). The team ultimately deemed it not worth it compared to an extra line or 2 of very clear (and copy/paste-able) boilerplate.

We will continue to try different things and refine how we organize our MVU code. But this is where we are for now. We have used it for top-level pages and for 2nd level sub-pages.