Hi I’d like to share an experiment I’ve been working on recently:
This is the example that comes with cloning the Github repo:
I love using Chrome DevTools, so I decided to have the debugger fit its visual look/feel .
My goal was initially to improve debugging in Elm for myself. Based on my own experiences, I wanted a couple of things:
- reliable hot-reloading, for the debugger and the app it wraps.
- a slider to scroll back and forth between app-states (time-travel)
- an infinite list of updates performed, synchronized with the slider
- a simple way to import/export the full app-state from/to files. (bug-reports)
- an option to overlay an app with it’s model at any given time (model overlay)
- a button to unsubscribe/resubscribe the app with a click
- have the debugger collapse/expand, drag/drop, or dismiss easily.
I’m requesting feedback because I’ve managed to implement these features
I hope some of you will try out the example and give me some feedback on what you think about its current state and the direction you’d like it to go, should you want to use it.
I plan to do my own review of other solutions to similar problems. If you know of any really nice tools in other languages/ecosystems that haven’t already been mentioned, let me know!
Suggestions on a suitable data-structure for the absurdly long sequence of
Msgwould be much appreciated. I’m don’t have a deep theoretical background that allows me to make good decisions in this problem-space. The current approach relies on a naive
ZipList (Msg, Model)backed by
List. I have a lot o ideas, but could use some insights or inspiration
There’s a couple of problems that I haven’t gotten around to solving (or can’t solve at all):
This is my initial implementation which is backed by a naive
ZipListfor navigating states. It doesn’t perform very impressively and starts to feel sluggish on my machine at ~1000 or more updates. There’s a lot to do in this area, but I want to make sure that the design is good before optimizing.
“Breaking changes” to the
Msg-type in your program should be the only way to force your app back to the initial state.
“Breaking changes” in this context means changes to
Msgthat doesn’t make the new
Msg-type a superset of the old one. What you generally want to do is to make append-only changes to your
Msg-type if you want to rely on hot-reloading and time-travel. Beyond
Msg, you can make modifications across your app and shouldn’t experience any issues.
An improvement in this area would be to decode stored
Msgup until the point of the first breaking change, and only return
Msgperformed before then - I haven’t gotten around to do this yet, but it should be trivial at this point.
As you can see in the example above, you can achieve some very dynamic behaviour from making changes to your
update-function after running through a lot of states. I’m uncertain if this is only an upside or could cause real problems in practice.
If you scroll back to the initial state and toggle subscriptions on, the program will bypass the commands from your init-function. This can be mitigated by reloading the browser from the initial state, but I haven’t found a way to solve this properly yet. I’m sure it’s possible though.
Msg -> Json.Encode.Valuehas to exist for my pure Elm solution. There is a possibility that this won’t be necessary in the future, but who knows what might happen. One might argue that it is unacceptable to have to write two such functions, but in my experience, this isn’t a big problem in practice. Sure, retrofitting the debugger onto your app require you to write up both functions from scratch, but it’s fairly easy to incrementally do this while developing your app. I think it’s pretty good practice to keep such functions near your
Msgtype, which is where the changes will cascade from in the first place.
I hope to see this kind of solution prove efficient enough for almost any Elm app. I’m not sure if this will exist as an Elm module with it’s current constraints, or if there will be APIs to get around some of the current caveats before then.
I hope some of these ideas and experiments can help drive the debugging/development experience in Elm forward. From the initial debugger presented by Evan a couple years ago, to the release of the Elm 0.18 debugger, I hope to drive this vision forward and maybe help you be more productive in your work
Let me know what you think!