DEV Community

loading...

Discussion on: Mere Functional Programming in F#

Collapse
macfarmw profile image
Matthew MacFarland

Great article! This paragraph stood out to me.

This idea sounds easy enough, but life is rarely straight-forward. And I often find that I need to interleave side effects with decision-making. For example, make an initial decision, then load some data (a side effect), then use that data to make further decisions. It has been a fun journey to figure out ways to accomplish the goal of deterministic decision-making. I have a strategy for that I'll cover in a future post.

I'm eager to see your strategy that helps with this.

Collapse
kspeakman profile image
Kasey Speakman Author
Collapse
kspeakman profile image
Kasey Speakman Author

Thanks!

Sorry for the delay in writing that article. There are two main reasons. We've been heads down working on a new product. Also, I am using the product as an opportunity to refine my approach before publishing. I like to have the code in production and face some of those edge cases before I write about it.

If you are not familiar with the Model-View-Update pattern, then the rest of this comment probably won't make sense to you. And I would encourage you to check it out instead of reading further.

I can sum up the essence of the approach. It is an adaption of the MVU pattern (aka The Elm Architecture). The main modification to the MVU approach is that I create another type Effect (a DU) to represent side effects, and a function perform to execute the effects. The Effect type should be immutable with value equality for testability. Then the update statement will return a Model * Effect list instead of whatever it normally returns. This is easily adaptable to work with the Elmish library on front-end projects. On the back-end, there is no need for me to run the Elmish library or bother with a view function. Instead, I essentially plug the same MVU (sans V) types and functions into a small recursive function that runs update and perform until there are no more messages or effects to process.

There is a trade-off obviously. The main downside is that I have to always define types and functions associated with MVU. (But on the plus side, I always have a place to start.) The other downside is mentally transitioning from interspersing side effects into the update/perform structure. In the article, I plan to cover some guidelines/lessons-learned.

The benefits are pretty strong. Using the Effect variation, the update statement can be completely deterministic. Not just for the Model, but also for the Effects. Put another way: not only can you test that the logic produces the correct answer, but also that the correct side-effects are invoked! Without any sort of mocking framework... only using an equality comparison. This isn't even available in Elm since its effects (Cmd) are not equatable. And of course, having a deterministic update statement makes it much easier to refactor safely.

That is the basic run-down. Hopefully if you are familiar with MVU, it made some sense.