The author does a lovely job of covering a number of the interesting ideas in this space. But reactive programming is such a tough sell. I know from experience.
I maintain a reactive, state management library that overlaps many of the same ideas discussed in this blog post. https://github.com/yahoo/bgjs
There are two things I know to be true:
1. Our library does an amazing job of addressing the difficulties that come with complex, interdependent state in interactive software. We use it extensively and daily. I'm absolutely convinced it would be useful for many people.
2. We have completely failed to convince others to even try it, despite a decent amount of effort.
Giving someone a quick "here's your problem and this is how it solves it" for reactive programming still eludes me. The challenge in selling this style of programming is that it addresses complexity. How do you quickly show someone that? Give them a simple example and they will reasonably wonder why not just do it the easy way they already understand. Give them a complex example and you've lost them.
I've read plenty of reactive blog posts and reactive library documentation sets and they all struggle with communicating the benefits.
That sounds very familiar to me. I'm now retired but in my last job I put together a simple C++ framework to do something similar. I used this in a small part of a financial trading application. Like you, I was convinced it would pay off to apply much more widely, but I found it difficult to "sell" the idea. As you say, the real payoff comes in complex situations, which simple examples don't really convey.
However lots of people seem to be playing around with reactive programming now, so perhaps it's an idea whose time is coming.
Curious as to choice of 'demands' vs 'dependency' and 'supplies' vs 'provider'. The latter of these are fairly commonly understood and used.
As an aside, "complex, interdependent state" is possibly one of the few areas that lend themselves naturally to visual programming (which is a fail in the general programming case). Why not just draw graphs?
> I've read plenty of reactive blog posts and reactive library documentation sets and they all struggle with communicating the benefits.
I just googled 'visual programming for reactive systems' and this (interesting project) turned up:
So the approach is specifically addressing complex interaction patterns between components. To highlight the solution, just do what these guys did: here you can see the benefit of 'reactive components' just by looking.
It's a reasonable suggestion about the naming of demands and supplies. We landed on those names because they had some of the correct connotations, and it was easy to be clear with each other what we were talking about. A "Demand" is a very specific thing when using Behavior Graph. "Dependency" is a common term that means half a dozen things in a program at any given time. "Supplies" is just a reasonable opposite to "Demands".
That being said, we do often consider renaming them and other parts to feel more mainstream reactive. But honestly, I secretly suspect that fiddling with names won't make a difference to anyone.
I do also agree that there is some appeal to visual programming paradigms. It's pretty easy to look at the examples you linked to and get some quick sense of understanding. But those typically work well when there are a handful of nodes and edges. The software we maintain at work can have 1000's of nodes at runtime with more than 10000 edges. There's no visual representation that won't look like a total mess. Whatever their faults, text based programming languages are the only approach that have stood up at scale so far.
So our library is just a normal programming library. You can use standard javascript/swift/kotlin to write it.
I think you are absolutely correct. In this simple example, it's not easier to comprehend. Especially for someone who already understands how composing software out of function calls works.
My goal with that example was to point out how there are implicit dependencies between validateFields() and networkLogin() and updateUI(). They need to be called in the correct order to make the program work. Our library makes those dependencies explicit and calls things for you. It's not a big deal when we have a 3 function program. But when we have dozens or hundreds of interdependent instances of state, those implicit dependencies become a real struggle to navigate.
Now we're convinced our library works well. We use it every day. But it's also very reasonable for you to be skeptical. As you say, there's cognitive load. As a potential user, you would need to spend your time to read the docs, try a few out ideas, and understand the tradeoffs. That's a lot of work.
I'm glad you took a look at the project, though. The fact that we've failed to make a case for it is certainly on us. Which gets back to my original point. I don't know how to sell a solution to complexity.
I regret taking antibiotics for years in high school as a treatment for acne. We just did what the doctor recommended without giving it much thought. My gut has been a mess ever since and it really impacted my quality of life during the “healthiest” years of my life.
State machines are cool but they don't compose well out of the box. Behavior Graph let's you build a composable network of them so they become a practical software architecture. (Disclaimer, I am a coauthor) https://github.com/yahoo/bgjs
Hi. Thanks for the reply. (Pardon my drawn out response. I can nerd out on this all day.)
I'm not aware of sub-state-machines as a standard concept. There are State Charts which are a superset of state machines and have their own notions of composition (XState is an implementation).
A sub-state-machine may feel like an intuitive concept but it does lead to a number of design decisions and related tradeoffs.
For example:
- We can have "State Machine A" influences "State Machine B". In order to make that happen there needs to be code in A that notifies B. Perhaps we do this with an explicit function call B. That's not too bad, but we are introducing a tight coupling between them.
- We can also have "State Machine A" influences a number of downstream state machines. Now we need many function calls or instead implement some observable or event protocol. That's also not too bad but its certainly not out of the box.
- Or we can have "State Machine A" and "State Machine B" both influence "State Machine C". In order to avoid updating C twice (glitches) we need some coordinating code that understand the dependency graph. I know from experience that is definitely not easy or obvious.
- And additionally we can address what it means for state machines to come and go over time which changes the dependency graph.
Behavior Graph is our implementation of those ideas in a slightly more general sense (we aren't restricted to _finite_ state machines and we have a generalized notion of events and observers).
I know talking about things this abstractly can make people's eye's glaze over so I won't belabor it too much, but that's what I mean by "don't compose easily out of the box".
That’s interesting conceptually. Coming from a games background we don’t tend to think about the state machine as the primary element but wrap them inside other concepts. So an Entity might contain multiple state machines but communication and update is mediated by entities rather than between the state machines themselves. So I’m nodding along to the issues you raise but also feel like they get solved quite neatly with the game approach.
Sub-state machines or hierarchical state machines have been a thing in games for quite a long time. It’s a natural extension particularly for AI although IMO it’s mostly reducing a cognitive burden.
The folks behind the SCXML spec were trying to address some of those concerns, albeit in the abstract manner required of platform-independent spec authors:
Work on that goes back to the early 2000s, when XML was on the rise. One of the more important and lasting contributions of that work is likely Appendix D, "Algorithm for SCXML Interpretation":
I suggest ignoring the XML-specific aspects of it; consider that such tree-shaped data structures can as readily be encoded in JS objects (including stringified JSON). Also consider the larger spec's notions of `send` and `invoke` for "External communications":
Sub-state machines have been around since at least 1970. They were used in NLP, where they were coined Augmented Transition Networks. Those were FSA with a stack (and variables), but when you don't do recursion, it's substituting an edge with another FSA.
I always suspect that many people who have a hard time relating to TDD already have experience writing these class & method oriented tests. So they understandably struggle with trying to figure out how to write them before writing the code.
Thinking about tests in terms of product features is how it clicked for me.
That being said, as another poster above mentioned, using TDD for unstable or exploratory features is often unproductive. But that’s because tests for uncertain features are often unproductive, regardless if you wrote them before or after.
I once spent months trying to invent a new product using TDD. I was constantly deleting tests because I was constantly changing features. Even worse, I found myself resisting changing features that needed changing because I was attached to the work I had done to test them. I eventually gave up.
I still use TDD all the time, but not when I’m exploring new ideas.
I do the same. But almost always wish I had done TDD. The times I can bring myself to git reset —-hard after I have finished exploring and then TDD it in, the code benefits. Often though I can’t bring myself to do it and I retro fit in a few tests and reorder the commit history :)
Number of times I've regretted quitting a job: 0
Number of times I've heard of anyone regretting quitting a job: 0
ie its never a bad time
That being said, I interview engineers at a larger tech company. I view it as a negative for a candidate to have multiple short term stints (less than a year).
I regretted quitting my job in 2017. I left for 9 months and came back, but for less equity than I originally had. (The equity I walked away from in the first stint would have made me a few million dollars richer than I currently am.)
> I view it as a negative for a candidate to have multiple short term stints (less than a year).
Do you mind explaining why? I would personally be seen like that by you, but I personally consider it a good thing that I was able to "rise" so quickly in my career. I'd like to hear your take on this if possible.
If I hire you, I want you to be able to stick around long enough to get something done. Typically that's at least 2 years. Staying for less typically makes the hiring process not worth it. Plus now I immediately have to go hire another person again.
There was a discussion on tenure length in another topic a month or two ago.
I'm curious what you would think about someone who's stayed at one company (same role, same team, maybe some minor increase in responsibility and rank) for 5 years? 10 years?
Would you view someone like that better or worse than someone who has multiple n <= 2 year stints during that time?
My observation recently, having been through interview loops and having stayed at my previous company for 7 years, is that longer tenures seem to be perceived as bad these days at tech companies...possibly worse than multiple short stints. Perceptions of expert beginner syndrome, 1 year of experience * n years instead of n years of experience, laziness, lack of motivation, etc. being typical reasons given.
> I'm curious what you would think about someone who's stayed at one company (same role, same team, maybe some minor increase in responsibility and rank) for 5 years? 10 years?
It depends. A long tenure means I will check in the interviews whether you were stagnating and just killing time, or growing and delivering on major improvements.
One of the best people I worked with spent 10 years at a very minor company, but the work they spoke about in the interview was extensive, and they took on a huge amount of development work across our entire company once they joined.
Total man crush on Elon here. He's like a science fiction author except he makes the spaceships for reals instead of writing about them. Meanwhile a large chunk of the entrepreneurs continue to optimize ad delivery and photo sharing (myself included), just sayin.