Working in multiple versions of Elm

At Gizra, we’re in the unusual position of working in multiple versions of Elm at once. Most of our apps are targeting Elm 0.18 at the moment. We’ll move some of them to Elm 0.19 eventually, but there will be a substantial transition period for us. In fact, you might be surprised to know that our largest and most complex app is still targeting Elm 0.17!

Why does it work out that way for us? While there are admirable tools for upgrading an app from one version of Elm to the next, it is still a noticeable chunk of work when you’re billing clients for upgrading large and complex apps. (One also has to consider the effort required to do QA on apps already in production). So, it gets prioritized in the usual way against other things clients could be spending their money on. And, continuing to work in Elm 0.17 for our largest app has been surprisingly pain-free. (This is, I think, a tribute to the quality of Elm 0.17 – despite the very real improvements in Elm since then, we’ve been able to do what we need so far without upgrading). This won’t last forever, of course, but we do have a longer period of working in multiple versions of Elm than most developers would, I expect.

Now, working in multiple versions of Elm has its own complexities, and is probably not advisable for 98% of you. However, for the remaining 2%, I thought I would “show and tell” some packages we’ve published to smooth out some of those wrinkles.

When you’re working in multiple version of Elm, you occasionally want to reach out into Elm’s past or Elm’s future. Perhaps you’re still in Elm 0.17 or 0.18, but you’d really like to take advantage of one specific API from a newer version of Elm. Or, perhaps you’re writing an Elm 0.19 app, but you’ve got some complex code written against Elm 0.17 or 0.18 APIs that you’d like to copy over.

Well, it turns out that in many cases it is possible to implement the older or newer APIs. So, we’ve published some packages that collect these kinds of implementations together. Which package you’d want would depend on which version of Elm you’re using:

What will you find in those packages?

Consider the Time module, which had very substantial changes in Elm 0.19.

  • If you install elm-compat-017 or elm-compat-018, you’ll find a Time019 module that implements the new API.

  • If you install elm-compat-019 you’ll find a Time018 module that implements the old API.

Or, consider the Http module. It had very substantial changes in API between Elm 0.17 and 0.18.

  • If you install elm-compat-017, you’ll find a mostly complete implementation of the new API in Http018.

  • If you install elm-compat-018 or elm-compat-019, you’ll find a mostly complete implementation of the old API in Http017.

And, there’s more! So far, we’ve covered everything that has ever been in core, plus the Http module. We’ll probably add a few more commonly-used modules over time.

Now, 98% of you should have stopped reading several paragraphs ago. But the remaining 2% may find something useful in these packages.

18 Likes

Nice experience. So you are back-porting new features to old versions which is understandable. But why would you need to implement old features in newer versions (when you said:

)?

This is one question, the other one is; from business point of view, don’t you think that migrating existing projects is cheaper than back-porting?

Implementing old APIs in newer versions of Elm has been helpful to us in two unusual situations.

One situation is where we are migrating an app to a new version of Elm, but there is complex code in production that is written against the old API. Sometimes switching to the new API is pretty trivial – for instance, it’s just flipped parameters to a function. In those cases, something like elm-upgrade makes migration pretty easy. In other cases, there is a more substantial reworking of the Elm API that may require a more substantial set of changes to our code. It can (in limited circumstances) be quicker to re-implement the old API than to restructure working code to fit the new API. This also lets us do the migration in stages, gradually transitioning to the new APIs, in the few cases where that strategy makes sense.

The other situation is where we have a module we want to share between apps using older and newer versions of Elm. By both back-porting and foward-porting APis, we can choose whether to write this cross-Elm-version module against the old APIs or new APIs, depending on which app the code originally emerged from etc. Either way, we can manipulate the imports to keep the body of the module very similar (sometimes identical) as between older and newer versions of Elm. Again, this is not the typical case – just something we’ve found useful in limited circumstances.

As for whether migrating or back-and-forward-porting APIs costs less, that’s always a judgment call – it isn’t efficient to try both and see which takes less time. :slight_smile: For our most complex app, we have a migration in progress which gave us a rough idea of how long it would take to complete satisfactorily – which started us down the other road. But it’s certainly possible to make mistakes about these things, and I don’t want to give the impression that working in multiple versions of Elm is a good idea in general.

2 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.