Hi There,
Over at the Node v5 beta 6 thread, @Steve-Mcl and I got into a discussion on the linkcall function call. I am opposed because of two main reasons:
a) it breaks the do-one-thing-and-one-thing-only Unix principle (basically the link call node is for doing linkcalls and a function node is used to execute JS code) and
b) the visual contract is broken that data flow is clearly shown in a visual manner (using a hidden calls inside a function node to pass data through a flow breaks that if there isn't a visual que to indicate that a function node is passing data around).
Steve talked about his flow being less brittle by having this added possibility inside the function node. The example he gave was this image:
That made me think: I don't see that as particularly "brittle" or confusing, in fact, it seems to me to be a normal "complex" flow in NR. The core comparison are the two groups on the left side (see below).
As a counter example:
That's a typical flow in my setup. That flow handles content storage (video, audio, image) and delivery for my mind map. Content storage is triggered by dragging and dropping urls into my mind map. The flow also handles interaction for audio transcription (via Whisper) and AI reformatting of texts included in my mind map. The AI and whisper stuff uses two instances of NR and therefore need to handle async messages passing to those instances (via http requests). Not shown are the AI and Whisper flows on those instances.
Premise 1: I believe that there is a certain level of visual complexity is simply inherent to NR and a visual development approach.
For me this complexity is simple part of using NR. I understand wanting to reduce the complexity by having a linkcall inside a function call but that goes against the ideas of having a visual approach in the first place.
For me, this is like saying "well I have too many characters in my C code, I want to use classes and objects to reduce that" - i.e., well then use C++. Secondly, one will use a lot of characters when coding C: it is a given since it's a low-level textual programming language with few high level abstractions. No C program that does anything will have zero characters and with each character complexity raises.
The good thing is, that C programming language is standardised and there is not arguing about what is and what isn't C. Even if its purely arbitrary (what is part of C and what isn't) it defines clear boundaries and folks can move on and build on top of C without worrying about functionality going missing or changing.
NR isn't standardised and the node granularity isn't fixed however I thought that a few guiding principles did exist. Such as NR is visual first and all data flow should be visual and that nodes perform just one task and one task only but that task really well.
Where is the line drawn between an visual approach to solving a problem and a textual solution? C is a standardised programming language, NR isn't and therefore this question will continue to arise for NR.
Premise 2: Better tooling would make complexity more understandable.
When I don't understand my own flows, I turn on message tracing to watch messages pass through my flows in real time. Visually I can then see where data is flowing and in the debug panel, I can see how data is altered as it flows - without deploying the flow.
Secondly, if I make changes and I forget what I changed, I use a visual comparison to visually show me what has changed in the editor - without deploying the flow.
Thirdly, the link call node doesn't have a visual representation of what it calls, i.e., no dotted grey lines. So I created a highlighter to for that uses green dots.
Fourth, visual refactoring - straightening lines, adding junctions to have straight lines. Reflecting on complexity and making it simpler to understand is also a "tool" that I use. Textual coding has many rules for refactoring (DRY, KISS, code smells, etc). There are no rules for visual refactoring.
I don't believe that removing nodes and replacing them with textual code will fix complexity in the long run. Of course everyone has their own level of visual complexity that they can understand, so pushing that to a textual complexity makes sense.
Here the flow using linkcall and not using linkcall:
For me, the bottom is clearer - the non-linkcall version. Why? Because I see that other bits of the flow are being called. In the top version I can read that the function node is doing the same. By reading, I mean I have to read the source code of the function node - the documentation may or may not be up to date. This limits the number of folks who can understand this flow - those that can code NodeJS have a clear advantage in this case.
The logical complexity of the flow hasn't changed, what has changed is that extra complexity is hidden in the function node, so that there is less visual complexity.
The intention of the post is not to discuss the virtues of the linkcall functionality, it is to point out that better tooling can help understand complexity and secondly, that NR isn't standardised - which is a shame since these kind of "discussions" will continue to arise as there are not standardised lines in the sand.
I made an attempt to standardise node functionality (granularity), creating a repository with visual unit tests to ensure that the inbuilt NR nodes do what they promise to do. I did that for my Erlang-Red project so that I could be assured that functionality was compatible. Again, a kind of effort to standardise node functionality so that NR becomes a pseudo-visual programming standard.


