I have been working on my off time for some time now to bring reactive programming to the fore-front of web development, as I think it best captures the essence of the logic in those domains, which is basically an event/data flow graph. Current languages and tools are built around the traditional sequential flow of a program, and this mismatch makes it pretty hard to properly adopt the paradigm without proper libraries/tooling.
RxJS is one of the best such libraries, though it lacks some essential features for being properly used at scale:
- It models the flows with inverse event/data flow trees, which though an improvement over the sequential flow still limits how larger flows are described,
- It does not provide any abstraction for re-use of reactive flows, which is essential to large-scale codes based on the paradigm (imagine coding without functions).
CONNECTIVE is a thin library on top of RxJS that addresses those issues. It is designed to be complementary to RxJS, boosting its flexibility and scalability without limiting its potential. You can read the following entry on the docs section for more info about these issues and how CONNECTIVE addresses them:
I've been using RxJS for a while, but I'm confused about this. I don't doubt you are correct; I'm just having trouble understanding.
> It models the flows with inverse event/data flow trees, which though an improvement over the sequential flow still limits how larger flows are described,
What does this mean?
> It does not provide any abstraction for re-use of reactive flows, which is essential to large-scale codes based on the paradigm (imagine coding without functions).
Isn't this just functions? I pass my Observables as arguments and variables, and use pipe() to create transforms.
---
Do you have Connective vs vanilla RxJS example to demonstrate?
It means you (typically) have a few observables being transformed into one (the inverse-tree structure). Reactive flows are in their general-form a directed graph, which can be described as a composition of multiple trees, however that description distances the actual logical model and the description, leading to harder-to-read code.
Additionally, the inverse-tree model of RxJS (mostly) enforces order of fully defining the flow as well, which limits your ability of organization of larger reactive flows, specifically across multiple modules (imagine a case where you need to define the beginning and the end of the flow in one module and the middle in some other modules, like a typical http server).
> Isn't this just functions? I pass my Observables as arguments and variables, and use pipe() to create transforms.
This goes hand-in-hand with the previous question: if all you need to do is to transform some properly defined observables into one transformation observable, then yes they are sufficient. On a more general form though, a re-usable part of a reactive flow would be a sub-graph of a directed graph, which can have multiple inputs and outputs. You can see examples of this across the docs, specifically in the link I mentioned above, or these places:
yes naturally in simpler cases where none of the aforementioned apply, there is no difference in using CONNECTIVE over RxJS. this is why CONNECTIVE does NOT mask the full API of RxJS.
> I don't doubt you are correct; I'm just having trouble understanding.
Well I might as well be wrong actually, thats the main point of these discussions and contemplations, so thanks for asking :)
> It does not provide any abstraction for re-use of reactive flows, which is essential to large-scale codes based on the paradigm (imagine coding without functions).
This is wrong. The "pipe()" operator allows you to reuse parts of an Observable flow in RxJS. For example the following function can be used in many different Observable flows:
import { pipe } from 'rxjs/operators';
function checkAuthPipe() {
return pipe(
doSomething(),
runAnotherPipe(),
map(out => out.isAuth)
)
}
This works great at scale too, as pipes can be composed from other pipes...
Good work with the library though, like the documentation and the concept behind the framework, we won't know if something's better until we try it.
Well pipe(), despite being a great extensibility tool, is not a "flow-reuse" abstraction, as it (mostly) just works as a transformer of (mostly) one observable into another. a reactive flow is a directed graph in general and an inverse-tree in RxJS.
of course you can simply re-use parts of the inverse tree using functions from multiple observables to one, and the main issue for this is basically the inverse-tree model limitation, as can be observed in appearance of convention-breaking and uncomfortable pipes such as partition.
To me, the glaring deficit in RxJS is that it doesn't have an observable collection. The convention to approximate it is `Observable<Foo[]>` which just pushes a whole array change.
.NET's ObservableCollection<T> is an example of doing this well.
The problem with these libraries are significant ramp up time. Unlike what the authors are claiming it’s not because it’s a difficult or greatly different mental model to grasp, it’s because the API is clunky and poorly designed. You’ll notice most of the popular and highly successful abstractions all share the common trait of being easy and quick to pick up.
It should be a red herring to anyone these days when they see demo code that looks completely unintuitive which purports to make something easier. If the author’s haven’t factored in ease of use and uptake it’s already failed at its first principles.
> The problem with these libraries are significant ramp up time. Unlike what the authors are claiming it’s not because it’s a difficult or greatly different mental model to grasp, it’s because the API is clunky and poorly designed.
Regardless of the quality of API design, reactive programming (and by extension RxJS) does indeed require a different mental model, as it is a different model for the flow of a program.
> You’ll notice most of the popular and highly successful abstractions all share the common trait of being easy and quick to pick up.
That is subjective. I remember how many people found node's async callback style unintuitive and confusing on first sight, and I personally find (at least the core abstractions of) RxJS pretty intuitive.
> If the author’s haven’t factored in ease of use and uptake it’s already failed at its first principles.
Yes this is part of the goal with CONNECTIVE, to bridge the gap between the description of a reactive flow (the code) and the most intuitive way to think about it (a directed graph), so that the end-result would be much more easily readable and intuitive code. I would love to hear if you have any more specific feedback on this front.
I don't believe this is the 'most' intuitive. A spreadsheet is a directed graph but that's not how people think when they use it--they just write function expressions.
Svelte 3 does a better job of making it intuitive.
> Svelte 3 does a better job of making it intuitive.
It might just as well be the case. Svelte is going is towards traditional reactive programming languages, which for example because of the implicit change propagation, typically bare the possibility of glitches, which translates into unreliability on the most basic level of the program. I do not know how Svelte 3 handles glitches (or change propagation for that matter), but am just mentioning this as a one of the hurdles of that approach that actually makes it less intuitive (though definitely it looks more magical).
> A spreadsheet is a directed graph but that's not how people think when they use it--they just write function expressions.
That is true, though people also do not utilize spreadsheets to even one percent of what is possible to do with them, mostly due to the fact that the representation masks the directed graph and makes it harder for people to think of a little bit more complex things they can achieve with it. Saying this as a person who (with a friend) has created a full-blown CRM using google sheets.
> I don't believe this is the 'most' intuitive.
I can't (and didn't) claim it is either. I just suspect it is a really intuitive model since it reflects the actuality of what is being programmed.
EDIT: on closer inspection of Svelte 3's implementation of reactivity, it seems that they are not actually implementing support for reactive programming, just keeping the DOM reactive to variable changes in a transient way. This of course means that it will (most probably) not result in glitches, since its not true reactive programming.
On this front it is notable that:
1) CONNECTIVE (and RxJS) are general-purpose libraries, not just for front-end,
2) I suspect that mere DOM reactivity of Svelte will also not hold up in more complex front-end settings, where you would need (and benefit from) proper reactive logic.
I would beg to differ. The FRP aspect of a spreadsheet is not the aspect that is widely used. It is actually a pretty uncomfortable one for even many programmers, though for really simple cases it is possible to get used to it. Actually, for example imagine how powerful the extent of the FRP in something like Google sheets is, IF it was such a shining beacon of easy learning curve I would bet that it would be a really popular programming tool for at least organizational automation software, which it is not.
is this a good thing or a bad thing? like is it "The API looked pretty normal and understandable to me..." or is it like "The API does not seem to have anything special at all, why does this exist"?
This reminds me Cycle.js. I would definitely think stream paradigm is very useful to front-end.
The essential difference in front-end, is the programmer is dealing with continous, realtime signals, and transform it into the graphical interface. This is very different from most request/response style back-end. And the stream is obviously a proper abstraction for modeling this.
However, I found it's tedious to work with RxJS or other stream libraries, not because the design itself, it's just JavaScript lack of flexible DSL machanism like macro. If you invent a DSL for a stream flow diagram, you can get a lot of very neat equations between source and sink, but for JavaScript it's very hard to abstract away the stream context syntactically.
> I would definitely think stream paradigm is very useful to front-end.
I think it is theoretically possible to mostly deprecate VDOM with this paradigm, leading to better overall performance and control.
> The essential difference in front-end, is the programmer is dealing with continous, realtime signals, and transform it into the graphical interface. This is very different from most request/response style back-end. And the stream is obviously a proper abstraction for modeling this.
Even for the backend though, specifically for concepts like message brokers (or any similar construct based on application) I would think the paradigm is quite useful.
> If you invent a DSL for a stream flow diagram, you can get a lot of very neat equations between source and sink, but for JavaScript it's very hard to abstract away the stream context syntactically.
I personally tend to believe that the ideal DSL (representation) for flow diagrams is a graph (as it encapsulates both the logical and the execution flow), which means in the end of the day any textual representation would be sub-optimal (as any textual representation of any directed graph is sub-optimal and less intuitive compared to drawing the graph itself).
this is typically untrue. the genesis of libraries like RxJS is encapsulating repeated code responsible for properly handling async resources/transformations. without them, you would either repeat similar code everywhere, or end-up writing your own version for the organization. you don't need to take my word for it though, try replicating some of the examples on the website (or on learnrxjs.io) to see this for yourself.
> Locked into a libraries way of doing logic chains
this is a valid concern, though the other side of this coin is not using anything like express, angular, react, etc as they all have the same effect. the design of such libraries should typically be pretty flexible to be more facilitating than restricting, and its always a bonus if they are smartly restricting (discouraging programmers from making mistakes and taking away cognitive load of making choices that can be mostly decided beforehand, etc). core concepts of RxJS for example are so basic that there are serious ECMA proposals to adopt them into the language itself (Observables), much like Promises before them (which were initially promoted by libraries that are still around).
> Steep learning curve for new team members
this is specifically true about libraries targeting reactive programming. the issue is not actually with the libraries but with the paradigm itself, as it requires a different mental model of the flow of the code. this is part of the reason CONNECTIVE exists to begin with, to offer an interface reflecting a more intuitive mental model of reactive flows compared to RxJS, though still it would be a different mental model compared to traditional synchronous programming.
this learning curve however is something that I personally believe is unavoidable in the long run. you already need to adopt it if you want to be competent at prominent frontend frameworks like React or Angular, the latter of which incorporates and utilizes RxJS extensively and the former borrows a lot of the concepts. we already had to go through such a curve with transition to NodeJS for backend, where before you would mostly write fully sync one-request at a time instance codes and compensate by paying extra for the hardware, but now-a-days that extra learning-curve is no longer considered a deterrent.
I just went away, learned all about RxJS, and then about Connective, and I think I'm in love.
This is a simple, pure, and elegant way of expressing complex systems. The site makes a whole lot more sense when you catch up with the reactive paradigm and see what RxJS does and what Connective provides that it doesn't.
thanks a lot. if you found any issues and/or had any questions while using this, there is a gitter chat room where you can ask them: https://gitter.im/connectv/community
I don't think it is possible. And it's someone's right (freeze peach) to make a mark on this.
I've love some of the texts books that has small hints of the authors political attitudes hidden in the examples. It gives character to the work.
Especially in open source I believe this is important to have this freedom. Companies usually do not openly express political prefs (unless it's widely accepted, as in gay-pride rainbows when the fight for equality is largely won). Many opensource projects are not run by corps, but by individuals: and that individual decide to tag a message to the product he/she delivers.
This has always been done, it's form of activism, and I believe it is a good thing. Otherwise we would only encounter political statements in the places we expect it (media, which is largely paid for) and much of us have already chosen to ignore.
My main point: please do not be dismissive of politics as that only helps the lobbyists (and the corps/ultra-rich they represent), and at this point we need to free "our" democracies (means: people rule) from them. Shutting people up by telling them not to discuss politics is not going to help.
well it used to be, but that battle seems to have been largely won on some level too, at least all involved parties now realize the value of open-source (though some may just treat it as a PR asset rather than a platform for inclusive innovation and progress).
I mean subtilities like going with a GPLv2 (+ commercial license), LGPLv2/3, GPLv3, BSD-like, CC0 or WTFPL... Or a combination! There you are already cross into politics IMHO. You made a statement, to a greater of lesser degree by choosing one (or more) of the mentioned licenses.
Going to assume you're in English-speaking North America, as I am:
Politics can no longer be kept out of any field whatsoever, because this is "a politically-charged era," in the argot of the day, but it might be more accurate to describe it as business-as-usual for a large Europe-derived civilization. Remember the Hundred Years War?
The post-war period of stability and consensus is an anomaly and has ended. Buckle up.
I also wish we kept politics out of common first names. The Donald referenced here is a mischievous and temperamental white fella (with orange bits here and there) with semi-intelligible speech who most of the time ends up messing what he gets into and thats why we need to keep him out:
I fully agree, the (meta) point here being a reflection on the environment where quoting wikipedia's description of a disney character can legitimately feel politically charged and facetious.
Connective allows users to create graphs between sources and sinks flexibly (i.e., not only source to sink ala typical RxJS), without needing to worry about multicasting.
Is this a fair way to describe this library's benefit?
the first benefit, yes (although I would say it is already two, the "graph" and the "flexible connection").
the second one being offering abstractions for re-use of partial graphs.
and it is notable that though CONNECTIVE takes away the worry of multi-casting in (hopefully) a lot of the cases, it is actually pretty conservative on that front and will in a number of cases default to not-multicasting, which might mean that you can get some unexpected behaviors if you are completely unaware of the concept. the plan is to expand the situations that it will make a good default decision for you on that front overtime based on how it is actually used.
EDIT: also thanks, yes as I mentioned somewhere else I actually started doing this for a super-efficient frontend framework (that effort epically failed), so I ended up being extra careful about a lot design choices (and to be fair, carefully delegating a lot of such choices to RxJS as it is a really brilliantly designed library itself).
it is not featured on the main page since the atomic process is not essentially different (neither from RxJS nor from any other library you might want to use to do that, though the ease of just plugging in any other library for that perhaps is different from RxJS).
yes it really is an interesting project in this area as well, though it seems to be mostly focusing on state-management and binding reactive flows to React components and leaving the flow programming mostly to RxJS (though I have only looked at the docs a bit and not used the library so I might be mistaken). however I feel maybe with recent release of React Hooks popularity of this library might fall, which is a shame (I definitely like the concepts much more).
if you mean "how I got to doing this?" well I was thinking of writing a piece on it, but short story is that I was trying to extend what I was working on before (connect-platform.com) to front-end in a really efficient manner (as I realized the paradigm shift on front-end means much less need for constant performance overhead of mechanisms like VDOM) and hence ended up here.
and about the docs, thanks, I am perhaps going to also independently publish the code responsible for generating it on github pages as an NPM package alongside my next project.
No need to get grumpy. The wording I've used is just a bit more polite than pointing my finger on the one and only maintainer, you, telling his tonality is totally off and might scare people away.
All good and sorry, maybe my initial comment was still offending.
However and what I meant is that your writing style, also looking in the comments here, is for my taste a bit too fluffy, elaborative, zealous and making it hard for the reader to grasp the essence of your statements quickly. If you can’t win people with words your lib won’t have the chance get tried.
While I like new takes in frontend, the overall wording was the reason not to read more about Connective but rather leave a snarky comment.
> All good and sorry, maybe my initial comment was still offending.
No seriously I did not find it offensive even one bit.
> While I like new takes in frontend, the overall wording was the reason not to read more about Connective but rather leave a snarky comment.
And I'm sorry to hear that. I am aware of this and do consciously try to keep it as simple and straight-forward as possible, though there is always room for improvement. It would be really helpful if you could perhaps elaborate a bit more on this, so I would know better on how and what to fix.
I have been working on my off time for some time now to bring reactive programming to the fore-front of web development, as I think it best captures the essence of the logic in those domains, which is basically an event/data flow graph. Current languages and tools are built around the traditional sequential flow of a program, and this mismatch makes it pretty hard to properly adopt the paradigm without proper libraries/tooling.
RxJS is one of the best such libraries, though it lacks some essential features for being properly used at scale:
- It models the flows with inverse event/data flow trees, which though an improvement over the sequential flow still limits how larger flows are described,
- It does not provide any abstraction for re-use of reactive flows, which is essential to large-scale codes based on the paradigm (imagine coding without functions).
CONNECTIVE is a thin library on top of RxJS that addresses those issues. It is designed to be complementary to RxJS, boosting its flexibility and scalability without limiting its potential. You can read the following entry on the docs section for more info about these issues and how CONNECTIVE addresses them:
https://connective.dev/docs/connective-v-rxjs