[HN Gopher] Flow-Based Programming ___________________________________________________________________ Flow-Based Programming Author : hypomnemata Score : 127 points Date : 2021-01-20 16:42 UTC (6 hours ago) (HTM) web link (jpaulm.github.io) (TXT) w3m dump (jpaulm.github.io) | blackrock wrote: | Fascinating. This is how I build my programs. I never knew it had | a particular name for the style. I just assumed it was | functional-style programming. | | This allows me to build ever greater programs, that does very | complicated things, and has thousands of lines of code and logic, | but everything gets boiled down to small bite-sized pieces. | | It's a more data oriented approach. And it seems to follow an | assembly line model. | | I liken it to building code pyramids. Where I keep stacking and | chaining one function to another, to build even bigger pyramids. | | At the end, all the code is heavily unit tested, and I have a | high degree of trust in the fidelity of the codebase. | Geminidog wrote: | This type of programming is actually a subset of functional | programming called point free programming. It's equivalent to | programming using only combinators as the fundamental unit. | | https://en.wikipedia.org/wiki/Tacit_programming | | All programs are actually pipelines of data flowing from a low | entropy state to high entropy state with IO and state as the | endpoints of the pipes-. Using the point free style or flow based | programming makes this entropy and the pipelined nature of all | programs more explicit. | | Using OOP or regular programming the pipeline nature of data | flowing to and from state and IO becomes less evident and more | convoluted. | bergie wrote: | Nice to see this here, as it has been the inspiration for quite a | few years of my work: https://noflojs.org/ | leetrout wrote: | NoFlo really is impressive. Great work. | jes5199 wrote: | neat to see this here! I've recently become convinced Flow Based | Programming is the ideal that other programming paradigms are | reaching for. But in practice, there's a lot that's not obvious | to me how it would actually work-- so it's great to have a bunch | of new reading suggestions! | akavel wrote: | Mandatory fanboi mention: https://luna-lang.org/ - now Enso: | https://medium.com/@enso_org/enso-dev-blog-18th-december-202... | pantsforbirds wrote: | Luna is one of the coolest projects I've seen. I've really | enjoyed watching the progress. | | Curious to see if it (or concepts from it) gets picked up for | programming education one day. | samuell wrote: | I'm super intrigued by luna/enso. Only that every time I've | tried it, the editor has had serious stability problems. I | wonder if a more traditional tooling and editor support | wouldn't be more successful for wide adoption? | devmunchies wrote: | Similar concept to what I do when programming in F#/OCaml by | default. You create your data types and then they "flow" through | functions. Each function is `input -> output` but bigger workflow | are also input -> output. | adamnemecek wrote: | The main difference is that with data flow, the flows happen | conceptually at the same time. | voldacar wrote: | This is a good article, in the history or multithreading sections | it would have been nice to mention the various old hardware | implementations of this model, such as the transputer or | connection machine | fahrrad34 wrote: | Do I understand it correct when I think that clojure's core.async | is an example implementation? | dustingetz wrote: | not quite, but this seems close: | https://github.com/leonoel/missionary | adamkl wrote: | Rich Hickey gave a good talk on core.async and it does seem | pretty similar in concept: | | https://youtu.be/drmNlZVkUeE | teknopurge wrote: | https://nodered.org/ - great project for all sorts of needs. | jcims wrote: | I recently used nodered for some process automation and it was | absolutely fantastic for quickly prototyping, dashboarding, | doing sensor integration, etc. Highly recommended!!! | analog31 wrote: | It might not tick all of the boxes for being a complete software | development tool, but Excel strikes me as being a dataflow | programming model. I wonder if it's a reason why it's easy for | laypeople to learn. | pantsforbirds wrote: | You can write pretty interesting data pipelines using akka | streams with a very similar idea to FBP. It's probably not | technically FBP, but the whole reactive stream implementation is | similar in thought but allows for things like disparate data | source speeds without blowing out part of the flow. | smartmic wrote: | A nice and powerful C++ flow-based programming framework is | DSPatch [1]. It is definitely worth to mention here, check out | also the examples in the audio domain. | | [1] http://flowbasedprogramming.com/docs/html/index.html | jgraettinger1 wrote: | We're building a tool, Estuary Flow, which seeks to be an end-to- | end realization of practical, configuration driven, and scale-out | flow-based programming -- with an important twist. | | The central concept is a "collection", an append-only set of | schematized documents, which can be _captured_ and _materialized_ | into other systems (e.x. pub /sub, S3 buckets, etc). | "Derivations" are collections defined in terms of source | collections, and stateful transformations/joins/aggregations | which are applied to them. | | A key twist is that collections are simultaneously a batch | dataset (backed by cloud-storage) and also a real-time stream. | They unify the current dichotomy of "historical" vs "streaming" | data into a single addressed concept. Declare a new derivation, | and it automatically back-fills over history right from S3, then | seamlessly transitions to live data. | | If this sounds interesting, check out our docs [0]. We're early, | but love feedback! | | [0] https://estuary.readthedocs.io/en/latest/README.html | hpoe wrote: | As I was reading this I was enthusiastically agreeing with the | idea, but something felt super familiar about it. Then I realized | this is basically the same concept as Unix pipes. | | I have my little individual programs, grep, awk, sed, jq, etc, | and then I can endlessly mix and match those different components | to do what I want. | | The limitation that I have seen with Unix pipes isn't often with | the ability to process or manage the data it is that it only | works if all the data is setup the proper way. As I have been in | the industry longer it seems to me that most code that gets | written isn't about actual computing but just centered around | importing and transforming data that is expressed in different | ways. | | Is there something that makes reading in disparate data records | easier so I can focus on the computing part of computer program | and less time on parsing data? | adamnemecek wrote: | Unix pipes make it hard to have a large graph. Like most pipes | take one thing and produce one thing. You don't really have | complex data flow graphs. | taeric wrote: | Though, this really kind of fits with the metaphor. Pipes | typically just send liquid. | | You could have a conduit connector to join a bunch of | wires/signals, I suppose. But, realistically, that is a mess | always. | adamnemecek wrote: | Right but you generally have a complex pipe system even | with liquids. Sewers send waste to a particular processing | facility. | | A node editor makes it somewhat less messy. | ledauphin wrote: | I don't mean to derail the conversation, but this really does | remind me of the game Factorio, though sort of in reverse. | | In Factorio, you build a larger and larger factory out of pre- | established functional components (assemblers, labs, chemical | plants, etc) that take in a limited set of inputs and produce | (usually) a single output. Your challenge is not to define the | functional core processes, but instead to wire together those | functional components by connecting their inputs and outputs in | ever-more-automated fashion, starting by hand, then using simple | belts (pipes) that eventually allow arbitrary load-balancing via | "splitters", and eventually through to trains (the forking and | load balancing happening via backpressure in the train system) | and robots (where everything is managed essentially as a single | state database of requests, and backpressure is provided by | output limitations, usually per functional component). | | Naively, I think that someday a decent chunk of programming might | actually look like this, and parts even be represented visually | (though in my opinion likely still defined formally as text). | Only I think programmers will continue to write the functional | components themselves, unlike in Factorio. They'll just live on | different levels of the "codebase", and the "pipes" level will | likely be a lot more abstracted than it is in Factorio. | | As a software developer, I find this paradigm to map very well to | serverless architectures, because you generally want to think a | level higher than the per-machine basis. It does require a | willingness to forgo handy and well-established tools like the | filesystem and Unix pipes in favor of higher level abstractions | around transfer and storage of data. | freeqaz wrote: | You have, from first principles, reconstructed a huge portion | of my thought process for building https://refinery.io | | Factorio and Minecraft automation mods are a big inspiration! | Check out InfiniFactory too :) | | Bridging existing applications to the Serverless paradigm is | far from simple. That's one of the biggest struggles I've | experienced trying to build a Flow-based software platform. | | Learn more every day though. Thank you for the interesting | comment! | mikewarot wrote: | I took a look at your site (refinery.io), and the "watch | demo" is really a "read introduction"... I was expecting to | sit back and let you show me 10-15 minutes of video that | sells the idea. | | It looks very professionally done, but reading screens isn't | as easy as it used to be for me, a video is better. | | Good luck! | freeqaz wrote: | Thank you for the thoughts! I really should sit down and | record a video. I'll figure out how to get that put | together soon :) | dgb23 wrote: | Another video game that works similarly is Oxygen not Included. | | One of the most compelling arguments for a data-flow/flow-based | programming is the mental model and the visualization aspect of | it. This opens up opportunities for monitoring, visual, data- | driven programming and it is white board friendly. | | In Elements of Clojure[0], the author discusses the concept of | "principled components and adaptive systems". And a flow based | design reminds me of exactly that. The semantics of composition | and communication are well-defined and universal, but | internally the components can (should) be specific and | concrete. | | Similar can be said about Small Talk as well. A primary aspect | of its design was the mental model, understanding and learning. | The core idea was that learners (especially children) | understand things in terms of their operational semantics. | | > I don't mean to derail the conversation, but this really does | remind me of the game Factorio, though sort of in reverse. | | So no, I don't think this is a derailment, but likely one of | the most important aspects of paradigms like this. | | [0]https://elementsofclojure.com/ | ledauphin wrote: | thank you for making this connection - I had recently been | reading Elements of Clojure and noticed the concept of | principled components, and I had been slowly working my way | towards this realization/analogy myself. | u678u wrote: | Its great but surely its more like OO programming perhaps without | inheritance. | amelius wrote: | Flow-based programming is cool, until the flow starts altering | the flow. | cjohnson318 wrote: | I think at that point it's a complex dynamic system. | galaxyLogic wrote: | In Dataflow -programming (or something like that) how do you | program a decision that depends on the result of some component? | | It would seem like I need to suspend my computation then "ask" | the result from some component, get the result back, and then | alter my computation based on that result. | | Pure flow-forward would not seem to support this easily. Or can | it? Or does it come down to that we always will need BOTH sync- | and async- functions? (unless of course we limit the problem | domain) | dustingetz wrote: | I think you are talking about Self-Adjusting Computation, so | the answer is yes dataflow can do that | https://blog.janestreet.com/breaking-down-frp/ | DonaldFisk wrote: | Yes, it can. | | The simplest way is with when/unless vertices which take a | boolean input and some other inputs, and which either output | the other inputs if the boolean input is true/false, or output | nothing. | erichocean wrote: | Spreadsheets are a variant of Dataflow programming, so however | they do it. | phreeza wrote: | Apache Beam seems to be an implementation of this idea. It works | well when the things you have to do matches the logic, but it | gets tricky if you need to do stuff iteratively or recursively. | samuell wrote: | Beam has some overlap, but in my understanding it has a rather | involved syntax for defining the data flows, quite far from the | simple list of connections between in and out ports that you | see in FBP systems following J P Morrisons principles more | closely. | | Apache NiFi comes quite a lot closer, with the main difference | that they only have a single in-port, instead of separate named | ones. Also it seems to be among the more heavy and complex | implementations (for good and bad). | jpaulmorrison wrote: | "They" meaning "FBP-like" or "FBP-inspired systems", to use | Joe Witt's terminology... They are usually control-flow | oriented, and to my mind do not yield the productivity and | maintainability advantages of the "classical" FBP paradigm | shift. I recently asked Node-RED's Nick O'Leary why Node-RED | only allows one input port, and the answer was something like | "because we have never run into the requirement"... a) this | is not something that can easily be added after the fact, | without totally rethinking the product architecture, and b) | trying to build complex systems without that feature would | be, to me, like trying to hang wallpaper with only one hand! | One litmus test I use is that of concatenating data streams | using the two different paradigms - I tried to describe this | in an article a year or so ago, recently updated: | https://jpaulm.github.io/fbp/concat.html Cheers! | samuell wrote: | The core of the FBP principles are the holy grail of true | componentized function architecture. | | Instead of losing yourself in ever more complex syntax | convolutions as has happened in a lot of functional programming, | you make the components (even long running stateful ones) self | contained with ports for data input and output as the sole means | of communicating with them, over buffered channels to allow | asynchronous computation, and most importantly keep the network | definition separate. | | Just this idea in itself is just brilliant. Hats off to Mr | Morrison for that! | | It allows to decouple complex software into reusable components, | without clever FP syntax. | | (Though, FP is perfect for implementing the components | themselves. It just doesn't really scale all too well for whole | program architecture, in my experience). | | One point to note: The visual component of many fbp systems is | completely optional, as is the idea of using novel DSLs. You can | as well define your networks and components in pure code. See | GoFlow https://github.com/trustmaster/goflow) and my own little | experiment FlowBase (https://flowbase.org) for examples of that, | in Go. | | I successfully built a rather complex little app to convert from | Semantic web RDF format to (semantic) mediawiki XML dump format, | in two weeks straight, of linear development time: for each | component (of ca 7), implement, test, go to the next component | (See: https://github.com/rdfio/rdf2smw) | | The same implementation in procedural PHP took months, and still | doesn't have all bugs and strange behaviours filed out. | codetrotter wrote: | Your flowbase.org domain redirects to a different domain. I | thought that perhaps you had a typo in the URL or forgot to | renew your registration of the domain, but upon a closer look I | think it's probably just a misconfiguration in your webserver | config causing it to redirect to another one of your projects. | | My guess is that you forgot to put the definition of the domain | sans www in your webserver config. | | If my guess is correct then this link should work: | | https://www.flowbase.org | | Edit: doesn't work either. Perhaps you don't have a TLS cert | for that domain? In which case maybe this link will work | instead: | | http://www.flowbase.org | | Edit 2: Without https it works. And like the person responding | to this comment said it redirects to the GH repo. | samuell wrote: | Ouch, sorry, and thanks! Wrote on mobile on the go and didn't | manage to double check the link. | wizzwizz4 wrote: | The link's trying to point you here: | https://github.com/flowbase/flowbase | samuell wrote: | Thank you! | the_duke wrote: | > you make the components self contained with ports for data | input and output as the sole means of communicating with them, | over buffered channels to allow asynchronous computation | | This concept sounds exactly like actor systems like Erlang/OTP | and Akka, only with a different set of terminology. | | The submitted site and your comment don't mention those | anywhere. | | Are there appreciable differences between actor systems and | FBP? | megameter wrote: | FBP is most analogous to the unit record machines of yore: | | https://en.m.wikipedia.org/wiki/Unit_record_equipment | | What you are programming is the graph of how these machines | connect and flow data(keypunch cards) through each other, | while the machines themselves and their function are | abstracted out. Data does not stay "at rest", it's presumed | to reach a terminating point where it exits the graph. A | buildup of unprocessed data in a machine's inbox results in | an overflow. | | It's a very useful model for making a debuggable asynchronous | system since it imposes static constraints everywhere that | you can map to your real hardware resources, versus the | emphasis on dynamism seen in the actor model(actors hold | private data, modify their state, create new actors - all | explicitly disallowed in FBP). | samuell wrote: | Actor systems differ in their means of communication. While | actor systems use the actors as the main units that you | connect, with fire and forget messaging to each actor's | inbox, FBP proposes communication between named ports over | channels with bounded buffers, very much like the CSP | implementation in Go (just that you have long running | components as in actor systems - something that can easily be | implemented in Go with structs with go channels in fields for | the ports, as shown in the FlowBase library I mentioned in | another comment). | | The FBP model provides implicit backpressure, because of the | bounded buffers on the channels. The actor model on the other | hand is more loosely coupled and flexible. | | This actually means FBP systems are slightly more optimal for | efficient within-one-node, in-memory parallellisation, | whereas actor systems shine more for distributed systems. | | They shine on different scales, in other words. | | I wrote a post many years ago on this, that seems to have | aligned with the experience of a number of people, based on | the reactions in the comments: | https://rillabs.com/posts/flowbased-vs-erlang-message- | passin... | bcrosby95 wrote: | > The FBP model provides implicit backpressure, because of | the bounded buffers on the channels. The actor model on the | other hand is more loosely coupled and flexible. | | Note that this is why people recommend using GenServer's | "call" instead of "cast" in Elixir/Erlang by default - it | applies a sort of backpressure because call waits for the | process to return a result rather than being fire and | forget. | | It's not exactly the same thing, or as configurable as Go | channels, but it is an option. | Nullabillity wrote: | Akka Streams adds named ports and defined backpressure, as | well as a graphical-ish DSL for connecting everything.[0] | | [0]: https://doc.akka.io/docs/akka/current/stream/stream- | graphs.h... | samuell wrote: | That is nice to see! I was evaluating Akka a bit some | years ago. | dustingetz wrote: | FP decouples the AST (symbolic functions with input ports and | an output port) from the evaluation context, which might be | async, or sync, backpressured, stateful, exceptional, | incremental/reactive ... mix-n-match whatever behaviors you | want, all for the same _abstract_ AST | samuell wrote: | I actually didn't want to make this too much of an FP-bashing | comment, as I find great use of many FP concepts, daily. | | I have yet to see an FP concept for composition though, that | is as simple and generic in its implementation, as the FBP | principles. | | I have sometimes thought FBP networks provide roughly the | same function (pun not intended) as a monad, although I never | seem to fully grasp what a monad is, so I can't tell for sure | :o) | dustingetz wrote: | Yes, dataflow with dynamic topologies (self-adjusting | computation) forms a monad. If the "flowchart" is merely | static, that forms an applicative. | https://blog.janestreet.com/breaking-down-frp/ In my | opinion, understanding the monad is essential to | understanding how to fully separate an AST from its | evaluation behavior. That is basically what a monad _is_ , | the monad is the computational structure that _does that_. | samuell wrote: | Thanks, that clarifies a lot! | dmbarbour wrote: | I think most FP languages don't decouple AST from evaluation | context. E.g. I cannot perform abstract interpretation on a | function's AST, nor rewrite a function's AST for incremental | computation, nor perform explicit partial evaluation during | function composition by composing the ASTs. I only can access | opaque `Input -> Output`. | | Also, FP algorithms developed for one evaluation context | cannot easily be ported to another. They are implicitly | entangled with assumptions. For example, I cannot evaluate a | lazy algorithm in an eager evaluation context without paying | a huge price. Adding back-pressure for list processing where | a program was not designed for it would easily result in | deadlock. Adding exceptions without adding unwind (or | bracket, try/finally, etc.) to the existing program | expressions will easily result in buggy code. | | I think your assertion might be true for some specific | integrations of FP nodes into FBP. Is this what you mean? | FigmentEngine wrote: | Sounds like XProc 3.0 https://xproc.org/ | megameter wrote: | Having studied and implemented FBP systems in the past, one | major takeaway I've gleaned is that most automation problems | start off as a linear sequence of processes, and so the | branching-graph of FBP looks unwieldy and superfluous. But this | is deceptive; you probably don't want to have a huge number of | branches in the design, but you will want them as an | optimization step or a way to combine inputs. | | So it's useful to design with FBP in mind but with a linear | interface as the entry point. | | Another aspect of this is that FBP graphs are static but you | may have a need to reconfigure them frequently; that is, you | may want to have a graph compilation step drawn from a source | language, rather than manually wiring it up. | | A way of making that graph compilation more than a syntax is to | include a formal constraint solver: Excel, for example, flows | the data after determining a solution for how cells relate to | each other. The power of the spreadsheet paradigm really lies | in these combinations of concepts. | | Lastly, there isn't really magic in the | algorithmic/implementation aspects of FBP. It grew out of | 1960's mainframe types of problems, and so it can be | implemented in a low level way with static pools of memory and | pieces of assembly code. But it remains conceptually just as | relevant to today's massive distributed systems. | hexo wrote: | This reminds me of reactive programming, especially functional | reactive programming. | mikewarot wrote: | Side effects are forbidden by structure, flows could be monitored | in a GUI/Debugger, and as a result components can be tested as a | unit, instead of a whole system. I love it! | | It is easier to design digital circuits when you have a whole | catalog of 7400 and 4000 series gates, than it is using | individual transistors. It is easier to wire a house when you're | not making wires and switches with a hammer and a forge. | | I welcome this new higher level of abstraction, and am willing to | pay the cost in terms of CPU and Memory to get there, just as I'm | willing to waste transistors or copper wire to have something | done and working. | dang wrote: | If curious see also | | from 2015, on the same article: | https://news.ycombinator.com/item?id=8867584 | | Related: | | 2019 (a bit) https://news.ycombinator.com/item?id=20215592 | | 2019 (another bit) https://news.ycombinator.com/item?id=19203642 | | 2019 https://news.ycombinator.com/item?id=18859019 | | 2015 (not that good) | https://news.ycombinator.com/item?id=10755250 | | 2015 (a bit better) https://news.ycombinator.com/item?id=9718868 | | 2015 https://news.ycombinator.com/item?id=8992281 | | 2013 https://news.ycombinator.com/item?id=6264657 | | 2012 https://news.ycombinator.com/item?id=4239274 | homieg33 wrote: | Very useful list. Thanks for providing. ___________________________________________________________________ (page generated 2021-01-20 23:01 UTC)