2017-01-24 12:00:00
Don't use ReactiveUI
TL;DR
This blog post says the opposite of its lazy and deliberately provocative title. I have become a huge fan of ReactiveUI. I just want to ramble about the path I took to get here.
Listening to Paul Betts
I first heard about ReactiveUI at a conference presentation by Paul Betts. I think it was at Xamarin Evolve. Mostly I remember feeling dumb. He said a lot of things that I didn't understand.
I went to that session without much real experience in Model-View-ViewModel (MVVM) development. Conceptually, I understood the idea of a ViewModel. But Paul mostly talked about how ReactiveUI avoids certain problems. And since I had not experienced those problems, his words didn't sink in.
Talking to teenagers about risk
Each time one of my kids was approaching adolescence, I sat down and explained the risks associated with certain choices. Laws and moral judgements aside, the simple fact is that many choices involve risks, and I thought it would be helpful to pass along that bit of information.
And in each case, my child said, "Thanks Dad", and proceeded to always make wise and low-risk choices from that point on.
Well, actually, no.
Teenagers simply do not learn that way. They process risk very differently from people who are more mature. Tell a 16-year-old that "if you drive too fast you might get a ticket". The adolescent will immediately begin driving too fast, and, in all likelihood, will not get ticket. This is how teenagers realize they are smarter than their parents.
Tangent #1: It is almost certainly a good thing that young people are more brave. It would be Very Bad if everybody started out with the same level of risk aversion as the average 65-year-old. Go watch the "Tapestry" episode of Star Trek TNG.
Tangent #2: I really should claim no expertise in parenting, but if somebody forced me to write a book on parenting a teenager, I would say this: Let your kid suffer from their own choices. That said, it is worth the effort to try and help them avoid the really bad mistakes, the ones with consequences that last for decades. But they do have to learn to make their own choices. Realize this as early as you can. The path to frustration starts with making everything all about you.
How we learn new technologies
My metaphor has many problems. For starters, Paul Betts is not my Dad.
Also, the element of adolescent rebellion was not present. I didn't hear Paul's wisdom and run in the opposite direction because of my deep need to separate my identity from his. In fact, I started devouring everything I could find on MVVM and IObservable. I really wanted to understand what he was saying.
But the metaphor works in one significant way: Like a teenager, I had to learn by doing. Nobody's words made much of a difference. None of that reading helped me become a a user of ReactiveUI. I went down another path.
Actually, I went down several other paths.
Maybe it's just me
I observe that most developers want content that explains how to get something done. "If your objective is to do X, then do the following steps." The most popular books and articles tend to follow this pattern. Questions of this form are the ones that do well on StackOverflow.
But this is almost never what I want.
I much prefer content that explains how things work. Once I understand that, I can figure out the steps myself.
When I am developing software, I always, ALWAYS do better when I understand what is going on "under hood", when I can see through the leaky abstractions.
And as I mentioned, I am apparently in the very small minority on this. If 90% of the world disagrees with me, does that put me in the top 10% ? Or does it mean my approach is somehow defective? Modesty aside, my history contains enough successes to allow me some confidence in believing that my approach is better.
I also observe that my approach is just a different spelling for the old adage, "Give a man a fish and you feed him for a day. Teach a man to fish and he eats for a lifetime."
If you tell a software developer what to type and where to click, you can help them complete today's task. But if you instead teach them how things work, they will be able to apply that understanding on other days too.
Hmmm. I'm talking myself into this. I don't know why most people prefer shallow recipes, but I really do think deep understanding is better.
Still, I like to stay open-minded about things. I've got a lot of failures too.
The truth is that my approach has tradeoffs. The need to understand everything tends to slow me down during the early stages. I usually gain some of that back in the fourth quarter of the game, where deeper understanding is often helpful in diagnosing tricky problems.
But again, in the decision making around software development, absolutes are rare. I'll admit that sometimes a simple set of steps without depth are exactly what is needed.
Maybe the ReactiveUI docs are just bad?
I don't know. Maybe. I've read the docs plenty. They don't seem bad to me. I also see nothing there that makes me want to defend them as the best docs ever.
Suppose that I regret not choosing ReactiveUI sooner. Further suppose that I wanted to blame somebody else for my choices. I guess I could find something to complain about. But I also don't tend to find that criticizing somebody else's work is helpful.
And remember, I started this journey sitting in front of an audience, listening to Paul Betts, and feeling dumb. To be clear, in that kind of context, I *like* feeling dumb. It's an opporunity to learn.
So why did I not choose ReactiveUI sooner?
I guess I don't really know. But I'm pretty sure that nothing has made me appreciate ReactiveUI more than the suffering that comes from not using it.
And that remark isn't very helpful, is it? I'd like to try and do better. Let's see...
"Son, it's just basic statistics. If you're going to always drive 15 MPH over the speed limit, you will eventually get caught. Suppose you roll the dice 20 times in a row without getting a 12. You still might get a 12 on the next roll, right?"
Oh, wait, wrong topic. Let me try again.
Why is ReactiveUI awesome?
In some software development situations, like mobile apps, if you take a step back and look at the forest instead of the trees, you will see that most of your code is reacting to something that changed.
There are lots of tools you can use to approach this kind of app. You can use C# events and callbacks and switch statements and delegates and lambdas and observables and notifications and bindings and more.
For simple apps, none of these approaches are much better than any other. But as your app gets more complicated, some approaches cope more gracefully than others.
Most cars drive pretty smooth at 30 MPH. But at 75 MPH, some vehicles are still giving a smooth ride, while others are shaking.
Let's try a conceptual example or two. Suppose you have a button, and you want something to happen when the user presses that button. This is pretty simple. All reasonable solutions to this problem are about the same.
On the other hand, let's say you have a list of items. The items in that list come from a SQL query. That query has 4 inputs, each of which comes from a UI control. Every time one of those controls changes its value, the query needs to be re-run and the list needs to be updated. A couple of those controls need to be disabled under certain circumstances.
These UI elements have a complicated relationship. We still have plenty of choices in how to express that relationship in code, but this situation is complicated enough that we start to see differences between those approaches. Some of the ones that worked out really well in the simple case seem kinda tedious for this case.
If my driveway has half an inch of snow, all methods of clearing it are about the same. But if my driveway has 15 inches of snow, a shovel is decidedly inferior to a tractor.
Why do I like ReactiveUI? Because I have found that it copes gracefully as the situation gets more complicated.
Why is this? Much of the credit goes to the "reactive" foundation on which ReactiveUI is built. Reactive Extensions. Rx. IObservable. These building blocks are particularly adept at expressing the relationship between a group of things that are changing. ReactiveUI adds another layer (or two) on top of these things to make that expressiveness more convenient when implementing user interfaces.
To be honest, I fudged a little bit when I said that all solutions are roughly equivalent when the problem is simple. That's not quite true. For simple situations, I'd have to admit that ReactiveUI might be a little worse. There is a learning curve.
If I am writing a grocery list, I could use a word processor, but a pencil and paper is actually simpler. But if I am writing a novel, the word processor is the clear winner.
I'm claiming that the effort to learn Rx and ReactiveUI is worth the trouble. My claim is based on this notion that ReactiveUI shines as complexity increases, but also on my belief that most people underestimate the complexity of their app.
If you disagreed with me above when I said that "most of your code is reacting to something that changed", you might be underestimating the complexity of your app. It is in fact very common to start implementing under the assumption that something will not change and then later realize that you need notifications or events. Or an observable.
Hmmmm.
Would the paragraphs above have changed my course earlier?
I don't know. Probably not.
I didn't start this believing that I could write the best ReactiveUI advocacy ever. Looking at it now, I can't believe I wrote it with no code in it. The canonical ReactiveUI evangelism pamphlet has gotta have WhenAnyValue() in it somewhere.
I just think it's interesting that despite my best efforts, I was unable to really understand the benefits of ReactiveUI until I tried using its alternatives. My current project is late. If I had chosen ReactiveUI earlier, maybe it would be, er, less late? There are questions here worth asking.
But am I 100% certain that it is always better to spare yourself the learning experience of using less effective approaches? No.
Can I credibly claim that everyone should choose ReactiveUI in every situation? Certainly not.
Maybe all I can say is that I am currently having a great experience with ReactiveUI.
Maybe that means the rest of this blog post is useless.
But you should have known that when you saw the cheesy title.