Flow-based Programming

Panta rhei (Panta rhei) - Everything flows.

NoFlo vs. "Classical" FBP

Some readers may have arrived at Flow-Based Programming (FBP) by way of NoFlo, which is a JavaScript-based system motivated by my book (Flow-based Programming, 2nd edition), and which uses a number of the same terms and concepts. This project, started by Henri Bergius in 2012, implements a number of the FBP concepts, and has been creating a significant buzz world-wide since then, due largely to the technical and marketing skills of Henri, Dan Tocchini IV, and their talented team at The Grid.

In August, 2013, they started a KickStarter project to raise $100,000 for future development, and had raised $115,677 by the end of the 45-day period. NoFlo has been recognized by Forbes, O'Reilly, FastCompany, and a number of other companies and publications.

NoFlo is integrated with an open-ended graphics tool called NoFlo-UI, developed by The Grid.

While a lot of credit is due the NoFlo team for bringing FBP to the attention of the computer world, what the developers of NoFlo call "FBP" in fact differs in a number of respects from FBP as it has evolved over the last 40+ years. Although NoFlo shares with FBP some of its terminology and characteristics, NoFlo does not truly embody the "FBP paradigm shift", in which application development is more akin to designing a data processing "factory", as described elsewhere in this web site.

Ali Razeen, currently at Duke University, has pointed out, in a very insightful note, that a number of people have built software which has the componentry and "configurable modularity" (indirect connections between input and output ports) features only of FBP, usually in combination with some visual representation, and assume they have built an FBP implementation. However, he goes on to say that these should not be viewed as true FBP implementations, as they typically miss out on the requisite paradigm shift. NoFlo is an example of this type of system. Because of the prevalence of such packages, we have started using the term "classical" FBP for FBP implementations such as JavaFBP which truly support the paradigm shift.

NoFlo is an example of what might be called a FBP-like system, and is based on Node.js, which is based on JavaScript, and therefore is still constrained by the standard, synchronous, "von Neumann" paradigm, even though JavaScript can achieve some asynchronism by the use of "callbacks". The von Neumann paradigm is the paradigm that almost all programmers have grown up with, so that they cannot easily envision a different way of building applications. Programmers trained in the latter paradigm (the vast majority) tend to assume that they can build an FBP implementation by just adding configurable modularity to a fairly conventional program structure. Unfortunately the difference is actually much more fundamental. The developers of NoFlo are currently working towards the goal of making NoFlo more "classical", but there are fundamental reasons to doubt how successful this effort will be. This is not to deny that NoFlo has a well-defined role in certain areas of computing, such as graphics and music, where it has been remarkably successful, but it seems that it is not well adapted to the type of application where FBP shines.

For those unfamiliar with the term "von Neumann paradigm", it refers to a computer design where a single instruction counter walks through a program accessing a uniform array of non-destructive readout memory cells. This has in fact been the standard computer architecture for several decades, but people are increasingly finding it inadequate for today's challenges, as shown by frequent cost and schedule overruns, weird bugs, and difficulty maintaining large applications. More and more writers have started to point out that these problems have now been shown to derive in large part from the architecture itself. Unfortunately programmers are exposed to this approach from the very start, and have a great deal of difficulty breaking loose from it! Ken Kan has pointed out this quote from Edsger Dijkstra (thanks, Ken!):

It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.

With all due respect to Dijkstra, it's not just BASIC!

We sometimes refer to classical FBP as a "new/old" paradigm, because in fact its approach and methodology has parallels with Unit Record systems, which were used for the first data processing applications, until these systems started to be replaced by today's computers. In the process, however, a lot of useful functions were lost... which FBP is now reintroducing.

An application built using FBP may be thought of as a "data processing factory": a network of independent "machines", communicating by means of conveyor belts, across which travel structured chunks of data, which are modified by successive "machines" until they are output to files or discarded. The various "machines" run in parallel, or intermingled, as determined by the number of processors in the machine. Of course these "machines" can be real hardware machines, or simulated on one or more hardware machines, or combinations of the above. Granted each FBP process is a von Neumann program, but it runs independently of all other processes, and so tends to be quite simple internally. Unlike in conventional programming, the programmer does not have to worry about controlling the exact sequence of events - all s/he needs to concentrate on is the transformations that apply to the data to convert the original inputs to the desired output.

Classical FBP supports data processing applications (business or scientific), typically long-running and high volume, and, as we have shown, involves a way of thinking (the new "paradigm") that is fundamentally different from that of conventional programming. This paradigm is actually more similar to engineering than conventional programming. While similar models have been used for application design for a number of years, up until now there was no easy way of converting these designs into running programs. Programmers could indeed design systems using data-oriented thinking, but then had to laboriously convert these designs into procedural code. In comparison, FBP supports a seamless transition from design to implementation, and our experience with it shows that it results in more maintainable and in fact better performing systems. It also facilitates communication between designers, programmers, maintenance staff and users. One large program written using an early ("green thread") implementation of FBP was running in production for almost 40 years (as of the beginning of 2014) processing millions of transactions a night, while undergoing continuous maintenance during all that time, often by people who weren't even born when it was written!

While an FBP process is a "black box" component with its own internal environment and control thread, a NoFlo process is essentially a cloud of callbacks linked by instance variables. Henri Bergius was able to simulate many FBP-like characteristics on the Node.js infrastructure, but some rather basic FBP techniques have no obvious counterpart in NoFlo. For instance, basic FBP business functions such as "Collate" require a process to be specific about which port it wants to receive from, and to be able to suspend until data arrives at that port - this function, or something similar, is being introduced gradually into NoFlo, but it logically requires a related architectural concept, missing from NoFlo, called "back pressure", where an upstream process will be suspended if the connection it feeds into becomes full. Finally, NoFlo lacks the concept of information packet (IP) "lifetimes", by which an IP is tracked from creation to destruction and can only be "owned" by a single process at a time, or be in transit between processes. The NoFlo team has been making changes to NoFlo to bring it closer to classical FBP, but unfortunately it appears that this will be at the cost of greater complexity and overhead.

While NoFlo is appealing because of its ability to support both client- and server-side processing, thanks to Node.js, and because of JavaScript's close integration with HTML, it is still tied closely to "von Neumann thinking". This in turn leads NoFlo designers to break up applications into finer-grained components, resulting in more complex networks. Also all existing implementations of classical FBP on my GitHub directory can take advantage of multiple cores, with the exception of JSFBP (see below). Because of JavaScript's restriction to a single core (similarly to the early FBP "green thread" implementations) neither NoFlo nor JSFBP support CPU-intensive applications, which are in fact well supported by JavaFBP, C#FBP and C++FBP using Boost.

Because the NoFlo people use the term FBP so prominently when talking about NoFlo, you will notice that we have been adding the term "classical" to "FBP" when it is necessary to distinguish it from NoFlo and other FBP-like frameworks. A number of the latter are starting to appear, such as IBM's recent NodeRed, but these systems are different in important ways from classical FBP, based as they are on von Neumann thinking. There is clearly common ground, as both FBP and NoFlo are component-oriented, with multiple instances of components communicating indirectly via a list of connections, giving what is called "configurable modularity", and both supporting stepwise decomposition using "subnets". However, our experience shows that it is the classical FBP paradigm change that offers the most leverage for improved productivity and maintainability in application development. At base, the problem with NoFlo is JavaScript - quoting Ken Kan:

It is too easy to just make FBP work for JS, but what we really want to do is make JS work for FBP!

Recently two colleagues and I have been working on a classical FBP implementation, written in JavaScript, called JSFBP, based on node-fibers, developed by Marcel Laverdet, and therefore in turn on Node.js. This is actually a "green thread" implementation, as were the first two FBP implementations running on IBM mainframes. These systems supported asynchronous I/O, so performance was good enough that the first FBP implementation was able to support most of the batch processing for a major bank for over 40 years! However, "green threads" do not support multiple cores, a limitation shared by NoFlo, and JSFBP's dependence on "node-fibers" will likely prevent it from gaining wide acceptance. At least two more implementations of FBP in JavaScript are currently being worked on, based on the advanced (main stream) JavaScript ideas of Promises and Streams, but more work needs to be done to see how well they will be able to support the basic concepts of classical FBP.

Because of classical FBP's highly asynchronous nature, it naturally results in components with lower granularity (coarser-grained), working with more complex data objects, than NoFlo. As stated above, classical FBP data objects (Information Packets or IPs) behave more like objects in the real world than variables in conventional programming (including NoFlo): they have a well-defined lifetime, from creation to destruction, and can only be owned by one process at a time, or be in transit between processes. While NoFlo allows one output port to be connected to two input ports, FBP does not allow this as this would entail magically cloning IPs (potentially even complex IP trees), and FBP designers feel this should be left to the discretion of the network designer. In addition, every IP that a process takes ownership for (by creating or receiving) must be explicitly disposed of (by sending or destroying) before that process deactivates. In fact, there is almost no "global" data in an FBP application - all data is either local to a method within a process or held within IPs. This is very different from the storage management concept underlying conventional programming (and NoFlo and similar products).

Given that classical FBP may be thought of by some as more "alien" than NoFlo, it has in fact a fairly simple set of scheduling rules. This in turn means that classical FBP components have a fairly simple internal structure. I therefore thought I would compare one commonly used component in a classical FBP dialect against the same function written in NoFlo. The result is in "Concat" Component. I may be biassed, but I think I prefer the "classical" version...

A common philosophy which is shared by classical FBP and NoFlo-UI (not NoFlo, obviously) is that they are both "language-agnostic". NoFlo-UI has successfully been used to generate networks in several different languages (including JavaFBP), and on several different types of hardware. Jon Nordby has also tied together a number of different FBP-like languages under his MsgFlo project, using AMQP (no back pressure though, as far as I know). As far as I know, he hasn't yet incorporated any of the classical FBP implementations, although there doesn't seem to be any theoretical reason why he can't. A few years ago I ran a network linking JavaFBP and C#FBP using sockets - this was necessary because of the different virtual machines underlying Java and C#. These various projects point the way to "super-networks" combining the strengths of multiple languages, with sockets providing the linkages. Since these ideas can be extended up or down ("fractally"), FBP provides a consistent application view from very high level (e.g. documents flowing between departments), down to the implementation level.

For those wishing to gain experience with classical FBP, there is no substitute for reading the book (Flow-based Programming, 2nd edition), and then starting to use one of the FBP implementations such as JavaFBP or C#FBP, or even the C++/Boost implementation currently under development, as described on the FBP web site. JavaFBP has the advantage of being closely integrated with a powerful diagramming tool, DrawFBP (see below).

For the time being, users wishing to work with classical FBP can code up networks using JavaFBP, C#FBP or CppFBP by hand, or JSFBP. Alternatively, they can use the DrawFBP drawing tool, written using Java Swing, which is also quite general, and can in fact generate the .fbp notation used by NoFlo and CppFBP, as well as NoFlo JSON networks. While DrawFBP does not support run-time network execution, it can generate runnable networks for JavaFBP (immediately runnable) and C#FBP. DrawFBP diagrams are stored in XML format, and additional generators can be added easily, or users can build their own generators using the XML format as input.

FBP and OO

For a discussion of the differences and similarities between FBP and OO, see Comparison between FBP and Object-Oriented Programming (Chapter 25 of the 2nd edition).