Templates, state trees, a school of ‘whatever’ and a state definition language
At first look, mobx seems easy, sounds like easy, quacks like easy.
(x-posted from onurgunduz.com)
Its design, however, requires some reconsideration of how the state should be organized in an application.
I love the fact that it is the recommended pattern for beginners these days, but most people use it because it’s magic. I’m here to convince you that there is much more to mobx than that.
First of all, it’s not magic, there is nothing paranormal with it, and I will come to that in a moment. But, first…
Rotterdam is a wonderful city, you should really visit here.
Back to mobx.
I admit, when I first heard of it, in late 2015, I wasn’t really quite impressed with the operational details of it. To my knowledge, there were already many observable implementations around and most of them were not even going this deep; they were just light-weight implementations, and mobx was not.
I thought it was just a sweet syntactic sugar with a sweet real-world application called mobx-react where it proved to be really useful. But even so, it stayed on my mind as something over-simplified or over-complicated.
Now you could say I was not the brightest kid in the class when it comes to functional programming :) I also didn’t join the workshops at Mendix organized by Hans L’hoëst which was aiming to introduce new-comers to FP using Scala.
Of course, that was not my exact thoughts when I was on a plane to AMSTERDAM!
I was like… OMGGG !! OMMMGG! I’m moving to the NL, are we there yet? Are we there yet? Are we? ARE we there? But that’s another story.
Then, after a week or so, mobx kicked in.
Now, besides the theory, to this day, I still don’t think it is a very practical tool to use as any other light-weight component you put in an average nodejs application. That’s my experience.
However, when it comes to UIs, it excels.
And we didn’t know that. It’s funny how everything is unfolding now! When I landed in Amsterdam, mobx (then mobservable) had around 120 stars, today I checked it once again and it was almost 10,000. Massive kudos to Michel and everybody who has contributed! A great achievement!
Not so obvious things
Like I said, some things are not really obvious at first sight, like everything should be in state.
Don’t let those smart kids make you think it is magic, it’s not. It’s an illusion.
Some people freak out when they hear the term mutable, or see something that even remotely resembles a mutable is being used for state management. It’s like how Dutch people love Hagelslag, and how the rest of the world thinks: “Why not Nutella?”
Well, they are not the same things. Indeed, they are not the same things, a Hagelslag is never a Nutella. It can taste like a Nutella, quack like a Nutella, but it won’t be a Nutella. For me, if it works, it works, whatever. It really depends on the current context that I am working in. “Is there butter around?” “How big is the bread?” “What should be the ratio of cacao sprinkles to the rest of the other stuff?” But, regardless of that, it’s not Nutella.
I was coming to that. The coolest thing about mobx is… Are you ready? It’s native types. It’s just mimicking… native types. The ones that the mustache spec is mentioning or the lodash API is being used for. The good old native types! Your high school bros!
Yes, of course, in mobx, it looks and quacks like you are dealing with them, but actually, you’re not. But, whatever…
The familiarity creates this illusion that you’re working with native types. But behind that green curtain, there is a wizard of Oz, putting a great deal of effort for creating this illusion. I mean, seriously, I’ve seen Michel bisecting the
Arrays, trisecting the
Maps into the tiniest bits and putting so much effort into making mobx support all the native types. So, it’s not magic, it’s mostly hard work.
With observable natives, also comes great power w.r.t. interoperability and of course composability. Don’t ignore that.
So, it’s not only the ease of use of data types or how fancy their names are, it’s also their familiarity.
Listen up, yo!
So, you did actually. Thanks!
You put your observables inside a class or whatever, and commented it nicely, then sealed off carefully and saved it to a file called
That’s why the state container concept should not be a new thing to you. In fact, your
state.js file was actually a state container from the beginning, albeit not a very popular one.
Perhaps, so far this can only be considered a convenient namespace for tucking new observables in. You efficiently emit tiny
change events without even noticing, and with a little help from mobx-react, voila! Everything is in motion!
Nevertheless, that’s all. When people say that “mobx is un-opinionated”, what they really mean is, there is no opinionated way to simply interact with your observables directly.
You can do anything to start a chain reaction, and you know, people do all the peculiar things in life. Early this year, I wrote these two modules: kek and kek. kek is a state container that proxies a mobx observable to lodash and kek is a state container and a duplex stream which emits & applies JSON-patches (rfc6902). (mobx-state-tree has built-in JSON-patch support so that kek is kapot I guess.) What I mean is: I don’t think people do that, I don’t think people use mobx like this, I don’t even think people use the same names for two different modules.
You see, everybody has their own opinions of leveraging what mobx does well. This causes a lot of confusions and bugs when the project you’re working on is growing.
Scalability knocks the door telling you that you need a way more opinionated approach, maybe even a limited one.
mobx-state-tree does that, it provides a generally accepted approach for defining how a state should look like. And it’s a very cool project, you should check it out.
Ok, there’s one last thing that I want to put emphasize on before closing up the mobx section.
Your state is not only a dataset, it’s a state; and by the same token, it is not only a phase of existence, it’s alive.
This is important. When working with mobx, you don’t have data or store, or whatever. You have an initial state. So, the object/the store you created is gone, mobx has changed it into something else and tries to convince you that it is still the same object, but it’s long gone. Think of it as a piece of paper that you had shown to someone, then thrown into thrash. What is left is a memory of what’s written on it.
Let’s talk about templates before talking about something even better.
As previously mentioned, in mobx realm React is just a tree-renderer, nothing else. You should really not put that much thought on it. The special thing about React is, those things take time to write, experiment and understand. There are billions of virtual DOM implementations on the internet now, if not trillions. React is just a very simple, very light-weight implementation, battle-tested on one of the most advanced UIs in the history of Internet, TheFacebook.
But seriously, you don’t really have to think about it. Ideally, you only want to test the state; the rest should be solid.
Eventually, this brought me to the idea of a templating language on top of mobx/mobx-state-tree. I think my ideal application has only a state definition of some sorts, an
index.js to glue things up, and a bunch of layout templates.
There weren’t many haikus about xūs yet, so I wrote one:
React.Component is a tree
mobx-state-tree is a tree
“A state definition language”
I was sitting there and thinking why simple things should be limited and how I can finish this write-up, I realized that data-types are also limited. There is only so much you can do with them.
Can we go further from there and create a minimalistic functional programming language for defining the state?
Let’s start with the simplest. The simplest is, of course, a
boolean type. So how would you describe a
boolean’s relationship to another
boolean in a single sentence? You could say they are symmetric, or you could say,
A is inverse of B
And, here you go! You defined a reaction! Or I think so, I am not really sure.
How would that work indeed? And what about other types?
A filters B
C sorts A by B.x
In the coming weeks, I will experiment with this idea and let you know the results :) I think, we can form such a familiar and expressive-enough language for defining a state which could replace a runtime in this context.
What do you think?
Final words & shout-outs
So, this post pretty much sums up my experience in the Netherlands since the day I stepped foot in the low lands (except the day I came to work after taking Ayahuasca) (ok, just kidding 😅 this is not serious!)
These days, I think I may have taken a great risk, and I only have 10-weeks left to find that out *sigh*
Regardless of that, I had great time at Mendix. A world-class team of developers, I must say. Besides, they gave me shelter and soup and put me on a desk where I sat next to the creator of mobx, Michel Weststrate, and opposite to one of the co-authors of the UML standard, Jos Warmer.
And the final shout-out goes to Meinte Boersma, (ex) Team Lead of Mendix Web Modeler. Meinte is an exceptional software engineer and lead. And he also gave me the Dragon Book as a present. ️Do I need to tell more? :)
Meinte and his wife recently welcomed their second son, Jamie! So, I want to congratulate them also from here! 🎉 👶 ✨
So, that’s it. Hope you enjoyed!