Dataflow programming with “Flow”¶
Flow is an experimental dataflow package for the Go programming language, massively inspired by Paul Morrison’s Flow-based Programming (FBP) and Vladimir Sibirov’s goflow implementation. See also the node.js based NoFlo and Node-RED projects.
Dataflow programming is not new. It differs from traditional caller-callee nesting, in that the connections are made more explicit. This allows inserting additional logic anywhere in what would otherwise have been a call/return chain. The result leads to higher modularity and more reusable code.
Under development since early 2014. Next version planned is 0.9.1, to match the JeeBus and HouseMon version numbering.
The source code is here and on GitHub. For documentation, see GoDoc. For test results, see Travis.
For discussion, there’s the HouseMon forum and there’s an issue tracker for bugs and feature requests.
Flow has its own terminology. The similarity with electronics is intentional.
The smallest building blocks are called Gadgets, which can be combined into larger units called Circuits. A circuit is also a gadget, allowing the nesting of circuits within larger ones. Gadgets can have input and output Pins, which are connected together via Wires. The dataflow takes place by sending Messages over these wires.
For more information, see Flow concepts.
In traditional FBP terms, Flow’s circuits would be called networks, gadgets correspond to processes, and messages are information packets.
In addition to the above funky-sounding names, there is also behaviour - along with some conventions:
Circuits and Gadgets:
- inside a circuit, every gadget must have a unique name, normally a lowercase identifier
- the two most common pins are named “In” and “Out” - all names must start with an uppercase letter
- pins are identified via their gadget, i.e. “decoder.In” is the “In” pin of the “decoder” gadget
- the gadgets inside a circuit can only be reached from the outside if their pins have been “labeled”
- wires are connected between output and input pins, with messages always going from “out” to “in”
- only one wire can be connected to each output pin, but inputs accept multiple incoming wires
- wires have a “capacity” of 0 or more, indicating the number of messages which can be buffered
- logically, all wires connected to an input pin act as a single wire, with a single capacity
- messages arrive in the order in which they are sent out on the wire
- if the wire capacity is exceeded when sending a signal, the sender gadget will “block”
- in particular, when the wire capacity is zero, all messages will be processed synchronously
- messages can be anything, including pointers, they are defined as