Command Query Responsibility Segregation

I mentioned earlier that React had solved an issue I was having for a while. Getter/Setters in Fine-Grained Reactive libraries have always been awkward. They need to handle intercepting access and change. The most classic form is a single function where if called with no arguments was a get, and with one argument was a set. This always was an awkward syntax as it was never clear exactly what you were doing. Were you calling a function? Are you fetching a value? To be fair it doesn’t really matter in these sorts of libraries because everything within the execution context gets tracked, but when it comes to refactoring if you weren’t careful you could create some really bad reactive loops.

Newer libraries used explicit .get and .set methods but it was always so verbose. Then came in proxies which removed all this overhead but that hid the data more. This was a good progression, but with nesting it was harder to follow change. Does it have deep observability or not? In coarser-grained systems like Virtual DOMs employed by Vue or React this is less of a big deal, but it never sat quite right with me for Solid. And then I saw:

const [count, setCount] = useState(0);

This is so simple but it solved so many issues. First of all, these are not ambiguous because they are named specific to function. One grabs the value and the other sets it. It also isn’t verbose to use. You just call it what you want to. There is no .set . Finally, and most importantly the read and write are separated. This was something that no one did before and is really the key to control. You can pass the value to descendant code without the ability to change it, or you can pass the setter without the ability to read it. You can create pipes of changes where only the first setter is exposed and the last getter and maintain the same clean pattern. When I saw this I knew this was what Solid’s API had to be.

Previously we had all these mutable atoms around, now we have methods with purpose. The ability to actually control the data flow is the biggest advancement from React Hooks. It is Command Query Responsibility Segregation(CQRS), also known as Flux, applied at a finer granularity on the local state. In simpler terms, by separating reads/writes we can enforce unidirectional dataflow. People wax poetic about Object-Oriented Programming, but this is a pattern without Classes that can afford an even greater level of control. Yet this point seems utterly lost on most “reactive” libraries, so eager for ease they forget we’ve tried this before in the early 2010s and it was terrible.

Vue comes to mind here especially. They have had the ability to go this Composition API(Hooks) direction for years. At any point they could have exposed their reactive system. They did not need React to discover Hooks to make this move. Vue has had it under the hood this whole time. They didn’t I imagine because of the desire to distance themselves from those early 2010s libraries. I don’t blame them. Now that the atmosphere has changed, I worry the lesson still hasn’t been learned.