3 ms·
i’ve been writing FRP code in JS for years now. Ease of refactoring and total clarity of what is happening (assuming you are familiar with the FP methods, etc)
by disantlor 4y ago
i’ve been writing FRP code in JS for years now. Ease of refactoring and total clarity of what is happening (assuming you are familiar with the FP methods, etc) are the biggest advantages.
I agree the code can balloon in size, and gets a bit hard to organize at some point, but the self-documenting aspect of it is amazing.
I combine an FRP framework (bacon.js) with Ramda.
I’ll admit I’ve had trouble working with things like React because I’m so used to wiring everything up explicitly and there being no “magic” behavior.
The explicitness is probably what makes it seem so unwieldy as the code/team scales
- cybrox 4y agoOut of curiosity, a lot of people are praising the "self-documenting aspect of [Reactive Code]", and I definitely see why. A single block of statements that transform and handle data in a specific way is indeed almost self documenting, which is really cool. However, how did this work for you with more complex combinations and transformations? For example, our codebase had one module that took inputs from multiple different sources (low-level network handling based on a library) and generated a consistent state out of them. To keep the code performant, we introduced some intermediary values, so that certain transformations had to be run less frequent. (this was necessary) In the end, we ended up with a ~500LoC module. I wrote the same later with async/await and split everything into ~20 functions, which worked really well. The reactive version however, was just a bunch (~15) blocks of transformations, which were somewhat self explanatory in themselves but it was almost impossible to trace the flow of data through the whole module without drawing it up. Even just naming a block (a function name) helped a lot. Sure, you can document blocks of reactive code, which is what we ended up doing but I felt like the self-document aspect fell apart when I had to write a sentence above every block as to why this intermediary transformation is necessary.
- disantlor 4y agoFor me, I think it comes from the ability to easily split a stream at any point and create intermediate variables. I get pretty obsessive about the variable naming (as I'm sure many do here) but a good variable name is crucial to the self-documenting concept. Also, creating more intermediate values than strictly necessary, creates more opportunity to flesh out the explanatory breadcrumb trail. Because of the enforced formality of how data is flowing around, the ability to split these streams up is trivial in a way that was a revelation to me. In the past, I'd be far less confident that I was going to mess up something unintentionally, to the point where I would maybe not bother. And yeah, I think it's totally valid to take larger blocks of streams/transformations and wrap in a named function that takes a stream and returns a stream. Over the years I've gotten out of the habit of always using FRP for every problem. There are many cases where async/await is totally fine and simple. I still always use Ramda, which gives me the same self-documenting qualities (which is really a function of the strictness of FP, not so much the R in FRP, now that I think about it). But whenever I have to coordinate multiple inputs with different time delays (i.e. multiple AJAX requests or UI input) or process a bunch of data where each item creates its own stream of fetching and processing, the "reactive" bit is extremely handy.