Skip to content

Instantly share code, notes, and snippets.

@Chadtech
Last active March 4, 2018 19:54
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Chadtech/89d9e085c3c5bf79602cceb53fbd6e31 to your computer and use it in GitHub Desktop.
Save Chadtech/89d9e085c3c5bf79602cceb53fbd6e31 to your computer and use it in GitHub Desktop.

Someone in the Elm slack channel threw out this idea of naming Msg in the past tense, and not imperatively. I thought it was an interesting idea and I adopted the practice, just to try it out. I forgot who it was, I wish I could give them credit.

Anyway, the ramifications were more than I expected, and not simply the same Msg with different names. What I started doing is naming Msg as if they were saying "This happened". So where I would say "HandleUsernameField" I might instead say "UsernameFieldChanged" or instead of "Close" I would do "XClicked". What I didnt account for was that Msg and functionality dont map one to one. So for example, if you have a Msg named Navigate, its going to be the one Msg you use whenever you want to navigate. But if you are naming Msg as paste-tense descriptions, then several different things could happen that could cause a navigation. Since many things should cause a navigation, naming Msg in the past tense leads to lots of Msg which do the same thing.

    -- imperative
    Navigate route ->
         model => navigateTo route
         
    -- descriptive
    
    NavTabClicked route ->
         model => navigateTo route
        
    UrlChanged route ->
         model => navigateTo route
        
    SubmitClicked route ->
         model => navigateTo route

        

This looks really redundant right? Its just the same functionality under three different Msg. But there are some less obvious advantages. In all likelihood, a fully build app will have several pieces of functionality that will be merely similar and not totally identical. Having Msg for every possible occurrence forces you to break down functionality into smaller pieces, and apply those pieces under the Msg where they are necessary. Thats better than making individual Msg that try and be flexible enough to do everything. Msg that try and do everything end up as large blocks of code with lots of conditional logic which are hard to work with and end up super fragile. For example, the code above may very well evolve into..

    NavTabClicked route ->
        let
            cmd =
                [ navigateTo route
                , saveSession model
                ]
                  |> Cmd.batch
        in
        model => cmd

    UrlChanged location ->
        model => navigateTo (Route.fromLocation location)

    SubmitClicked ->
        { model | state = Pending } => navigateTo Home
        

They all use navigateTo, but the functionality is a little different under each Msg. This is a lot better than trying to force an all purpose Navigate Msg to handle all these cases.

Another thing happened, which is that I found myself writing lots of Msg that didnt do anything. Like..

    UserDecoderFailed err ->
        model => Cmd.none
        
    InvalidPortPayload ->
        model => Cmd.none
        
    LogOutSucceeded ->
        model => Cmd.none

Lots of things happen in an app that just dont lead anywhere, and when I got into the mind set of writing Msg per thing-that-can-happen, I found myself writing a lot of do-nothing Msg. Maybe this is clutter, and to that extent I guess its bad, but if you look at these messages coming in (maybe in the debugger for instance) these Msg names create a perfect record of what happened, even if I dont need my program to do anything as a consequence of these do-nothing Msg. That perfect record of what happened could be really useful for debugging and discovering errors. Consider the alternative, where instead I just had a Msg called NoOp that I use everywhere I dont need functionality to occur. The record would show a huge list of NoOp, which isnt informative of whats actually occuring. A list of do-nothing Msg is actually quite descriptive of whats happening.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment