An Existential Model for FBP

495 views
Skip to first unread message

Kenneth Kan

unread,
Aug 28, 2015, 5:40:37 PM8/28/15
to Flow Based Programming
Hi all, I know this is a long post, but I'd like some feedback if someone has the time for a 10-minute read. :)


I’ve been hesitant to dive into FBP again (my first attempt was a few years back) because of this fundamental question that I cannot answer.

What is the right granularity level for an FBP component?

The question bothers me so much because a wrong understanding of the correct granularity creates so much complexity that after a while you would be asking: why even bother with FBP? I believe most who have tried "fine-grained" FBP in practice with a non-trivial project have encountered at least once, if not many times, that the running graph is so complicated that maintaining a mental model of it becomes a problem in and of itself. In fact, this is the reason why I decided to take a “sabbatical” away from FBP after my first attempt.

I want to put into words my approach to answering this irritating question and see if other FBP practitioners see the same problems and/or solutions that I do. If not, suggestions for refinement would be greatly appreciated!

Please note that there is ABSOLUTELY NO original content in this post. I’m merely re-packaging what I’ve learned about FBP into one universal model.


My mental exploration begins with this question: Why did FBP even appeal to me in the first place? On my first attempt several years back it was mostly that I could visualize my code with a clean separation of concerns between components. After my “sabbatical" and having re-read JPM’s book, I realized that the real pot of gold at the end of the rainbow was actually to escape the von Neumann model. Yes, visualization is important; modularity is important; reusability is important; but there are well-researched (and implemented) solutions to these problems in the von Neumann world.

As an aside, I want to stress that I’m abstaining from the discussion of non-von Neumann programming languages, and programming languages in general, as (I hope) we are thinking on a more abstract level when it comes to FBP.

I believe that FBP (or at least frameworks that are FBP-like) is gaining momentum because we’re finally catching up with reality that the physical world cannot be captured in a shared-memory model, nor can our *mental* world handle one gargantuan bloc of code that shares memory. The need is there, and there’s been a plethora of approaches on how to manage this "post-von Neumann" world, such as microservices and software agents.


For the sake of a comprehensive analysis, here is my own mental model of different software layers in relative abstraction, from the abstract to the concrete:
  • Software system/application, which serves a collection of one or more business objective(s)
  • Software agents[1], a logically independent entity that handles a single aspect of a business problem
  • Microservice, an independently running service that tackles a single technical problem
  • Computer program, which solves an engineering problem with clearly defined domain, parameters, and results (e.g. take two streams of documents and merge them into one, but not present two lists of documents and allow the user to interactively select which to keep as documents arrive)
  • Function, the basic unit of logical computation
Each layer handles a specific concern and breaks down a higher-level problem into lower-level one(s). For instance, a software agent breaks down a particular aspect of a business problem, such as “fetch the most relevant videos” into some more fine-grained technical problems, such as “fetch this video” and “fetch the avatar of the video author", for the lower-level layer. In short, each layer separates a concern by “breaking” the abstraction spectrum into two parts: a more abstract world and a more concrete world.

So I asked myself, where does (or should) FBP break the spectrum? From what I’ve understood by reading JPM’s book and my limited experiences in a few FBP-like implementations, I call this layer the “von Neumann limit”, above which shared memory does not exist, but below which there is an illusion that the entire world is single-threaded with a single memory space, which is where the von Neumann model excels.

In other words, we have two rules (here onward called the “Existential Rules”) to determine whether a system implements FBP:
  1. There may not be asynchronous operations. e.g. putting a process to sleep and sending an HTTP request are blocking operations.
  2. There must not be state shared between components. This may seem obvious but what this constraint implies is that there cannot be any free variable in each component. An example violation would be a call to write to a file by name on the filesystem if the two processes happen to be running on the same machine.
The two constraints are by no means new as they are mentioned in JPM’s book, though I would like to highlight them since these two constraints are together the single most important concept in FBP, as they define what FBP is by placing it along the software abstraction spectrum, at least under this model.


To demonstrate why this limit is significant, imagine that we set the breaking point on a more abstract level (i.e. making a component “coarser”): each component, like a microservice or a full-fledged service, may now take and send asynchronous operations at will. This results in unpredictable behaviors for obvious reason. Of course, there are strategies dealing with this problem in “conventional” programming paradigm, but a more robust alternative to this problem is exactly what FBP is offering. Whereas conventional solutions requires a number of runtime checks, validations, and logs, FBP offers the guarantee at the framework level!

On the contrary, let’s push the breaking point down to a more concrete level (i.e. making a component “finer"): each component, like a computer program or a function, may now access some global state. This is an obvious problem to a seasoned programmer so no further elaboration is needed on this topic. What is interesting is the corollary to that. One may ask what if there is no shared state whatsoever? Well, in order for that to happen, a lot of copying in memory is needed and it becomes more expensive as one moves down towards finer components. One may also suggest that a sufficiently sophisticated compiler can effectively remove a lot of run-time copying (a la Haskell). This approach requires purity at the function level and the ability to infer types across all the components, which is impractical given FBP concerns itself not with the implementation details of individual components, opting for flexibility and modularity over performance.

In short, we have three rules (here onward called the “Granularity Rules”) when it comes determining the (approximately) right granularity for an FBP component:
  1. Start with the von Neumann model in a component. i.e. just start programming the way one always has, well, for most at least, that the programming language must be synchronous.
  2. As soon as one reaches the point where she needs asynchronous operations within a component, break it apart into multiple components.
  3. Combine components into a graph, but when performance becomes unacceptable (i.e. too much copying in memory), combine components without violating the first Existential Rule. Note that the second Existential Rule must be violated (rightfully) in this step because the point is exactly to introduce shared state to remove the copying.

Again, there is no new information in this post. This is simply a model repackaged from existing knowledge about how a properly implemented FBP system should work. The purpose is to provide a comprehensive mental framework to understand what constitutes an FBP system and the reasoning behind why these rules form the definition of FBP, and hence its existential value.

If you have read this far, you must at least understand the frustration that I have. Please let me know what you think, or better yet, let me know if something is not sound! Thank you!


References
  1. Wooldridge, M. (1997). Agent-based software engineering. IEE Proceedings-software, 144(1), 26-37.

Raoul Duke

unread,
Aug 28, 2015, 5:44:51 PM8/28/15
to flow-based-...@googlegroups.com
> Start with the von Neumann model in a component. i.e. just start programming
> the way one always has, well, for most at least, that the programming
> language must be synchronous.
> As soon as one reaches the point where she needs asynchronous operations
> within a component, break it apart into multiple components.
> Combine components into a graph, but when performance becomes unacceptable
> (i.e. too much copying in memory), combine components without violating the
> first Existential Rule. Note that the second Existential Rule must be
> violated (rightfully) in this step because the point is exactly to introduce
> shared state to remove the copying.

nice, good to see this kind of explanation.

sounds a lot like actors.

Alfredo

unread,
Aug 28, 2015, 10:53:19 PM8/28/15
to Flow Based Programming
> I believe most who have tried "fine-grained" FBP in practice with a non-trivial project have encountered at least once, if not many times, that the running graph is so complicated that maintaining a mental model of it becomes a problem in and of itself. In fact, this is the reason why I decided to take a “sabbatical” away from FBP after my first attempt.

My experience with noflo was that the way graph execution works makes some things much more complicated compared to classical fbp. It is not apparent at first but it makes complexity grow.
From what I understand, common dataflow systems are very hard to use because they limit computations to a hierarchy of functions that get evaluated upon some change in inputs, programming this way is very hard compared to conventional structured/oop programming.
FBP was inspired by this kind of machine, and this is where your answer may reside. We really like to make small things that do a single thing well, this is quite fashionable today in the world of programming, but each time new information is created by a function, all the meaning it has attached is lost. It needs to be carried over to the next function in some way to complete the program correctly, it might just be the memory of the programmer, the types involved or some other technique. In that slice of time where the new information is being built, ready to be returned or sent, we may want to produce more information related to the processed data, and FBP acknowledges this. In the case of the mechanical card sorter, it produced not only a sorted stack, but additional information like card count, faults, etc. The machine "understands" the domain of what is being done, it is not just a responsibility or a task, it encapsulates a job.
Now, I might be writing too much but try to follow this idea: The granularity is not dictated by the need for asynchronicity, but the need for information to perform a job. Is a job something like "function(x){ return x * 2 }" ? To me it seems like this is just evaluating a formula, so the job could be "evaluate formula". Or if we go with the machine analogy, "Formula Evaluator". Then we could think the kind of information it can produce while doing its job, like the greatest result produced, smallest, divisions by zero, etc. All of this will not be useful for most programs, but it could be available as an output port, or configurable via IIPs.
Another important idea is Information Packets. Originally I understood them as just a number or a string, or any basic type, but operating on that scale everywhere is not very useful, as you might have seen with other dataflow systems. The next step is records, structs, POJOs, dictionaries, hashmaps,  or any name you like, the idea is similar. Many languages have immutable versions of them or you can fake them, so even if you are sharing a reference to a certain record, it will be read only, or make a copy to create a new version, so the performance cost is paid only if writes are made. Again we are working on traditional PC hardware, if you used some many-cpu system with dedicated ram for each cpu the story would be different.

Humberto Madeira

unread,
Aug 29, 2015, 11:16:27 AM8/29/15
to Flow Based Programming


On Friday, 28 August 2015 17:40:37 UTC-4, Kenneth Kan wrote:

What is the right granularity level for an FBP component?

Whatever level works best for you.  Seriously.

FBP is not an appliance.  Some assembly required.
 
The question bothers me so much because a wrong understanding of the correct granularity creates so much complexity that after a while you would be asking: why even bother with FBP?

Because it lets you change things around quickly, without fear of breaking something. 
 
I believe most who have tried "fine-grained" FBP in practice with a non-trivial project have encountered at least once, if not many times, that the running graph is so complicated that maintaining a mental model of it becomes a problem in and of itself.

If the model is getting too complex, you should try breaking it up into subnets.


My mental exploration begins with this question: Why did FBP even appeal to me in the first place? On my first attempt several years back it was mostly that I could visualize my code with a clean separation of concerns between components.

FBP is only one kind of programming technique that does this.
 
After my “sabbatical" and having re-read JPM’s book, I realized that the real pot of gold at the end of the rainbow was actually to escape the von Neumann model. Yes, visualization is important; modularity is important; reusability is important; but there are well-researched (and implemented) solutions to these problems in the von Neumann world.
 
FBP also gives you some defence against Amdahl's world.
 

I believe that FBP (or at least frameworks that are FBP-like) is gaining momentum because we’re finally catching up with reality that the physical world cannot be captured in a shared-memory model, nor can our *mental* world handle one gargantuan bloc of code that shares memory. The need is there, and there’s been a plethora of approaches on how to manage this "post-von Neumann" world, such as microservices and software agents.


You can believe what you want, but I've seen nothing in the market to reflect this.  

AFAIK, most programmers just get by with what they have, and they will accept any lumps they get as long as they don't have to learn anything new. 


For the sake of a comprehensive analysis, here is my own mental model of different software layers in relative abstraction, from the abstract to the concrete:
  • Software system/application, which serves a collection of one or more business objective(s)
  • Software agents[1], a logically independent entity that handles a single aspect of a business problem
  • Microservice, an independently running service that tackles a single technical problem
  • Computer program, which solves an engineering problem with clearly defined domain, parameters, and results (e.g. take two streams of documents and merge them into one, but not present two lists of documents and allow the user to interactively select which to keep as documents arrive)
  • Function, the basic unit of logical computation
 Unfortunately, these aren't really a hierarchy.
 
So I asked myself, where does (or should) FBP break the spectrum?

FBP is somewhere below Microservices, and above functions.  Computer programs are some other thing that doesn't belong in the hierarchy.
Agents don't quite fit in the hierarchy either.
 
From what I’ve understood by reading JPM’s book and my limited experiences in a few FBP-like implementations, I call this layer the “von Neumann limit”, above which shared memory does not exist, but below which there is an illusion that the entire world is single-threaded with a single memory space, which is where the von Neumann model excels.


I think of it this way:  inside a component, we use stack-oriented programming (von Neumann) outside, we let the framework do its thing.
 

In other words, we have two rules (here onward called the “Existential Rules”) to determine whether a system implements FBP:
  1. There may not be asynchronous operations. e.g. putting a process to sleep and sending an HTTP request are blocking operations.
  2. There must not be state shared between components. This may seem obvious but what this constraint implies is that there cannot be any free variable in each component. An example violation would be a call to write to a file by name on the filesystem if the two processes happen to be running on the same machine.
The two constraints are by no means new as they are mentioned in JPM’s book, though I would like to highlight them since these two constraints are together the single most important concept in FBP, as they define what FBP is by placing it along the software abstraction spectrum, at least under this model.

I'm not sure I follow - I think you mean rules for an FBP component, not a system - I will defer to Paul on this. 

To demonstrate why this limit is significant, imagine that we set the breaking point on a more abstract level (i.e. making a component “coarser”): each component, like a microservice or a full-fledged service, may now take and send asynchronous operations at will. This results in unpredictable behaviors for obvious reason. Of course, there are strategies dealing with this problem in “conventional” programming paradigm, but a more robust alternative to this problem is exactly what FBP is offering. Whereas conventional solutions requires a number of runtime checks, validations, and logs, FBP offers the guarantee at the framework level!

You are redefining what it means to be a component here.  Meaning you are not really talking about FBP at this point.
 
On the contrary, let’s push the breaking point down to a more concrete level (i.e. making a component “finer"): each component, like a computer program or a function, may now access some global state. This is an obvious problem to a seasoned programmer so no further elaboration is needed on this topic.
 
I would suggest you elaborate - I missed your point here.  Components have access to shared state - file system, database, etc.
 
What is interesting is the corollary to that. One may ask what if there is no shared state whatsoever? Well, in order for that to happen, a lot of copying in memory is needed and it becomes more expensive as one moves down towards finer components.
 
I'm not sure I follow this either.  How do you lock a file for writing if you don't have shared state?
 
One may also suggest that a sufficiently sophisticated compiler can effectively remove a lot of run-time copying (a la Haskell). This approach requires purity at the function level and the ability to infer types across all the components, which is impractical given FBP concerns itself not with the implementation details of individual components, opting for flexibility and modularity over performance.

In short, we have three rules (here onward called the “Granularity Rules”) when it comes determining the (approximately) right granularity for an FBP component:
  1. Start with the von Neumann model in a component. i.e. just start programming the way one always has, well, for most at least, that the programming language must be synchronous.
  2. As soon as one reaches the point where she needs asynchronous operations within a component, break it apart into multiple components.
  3. Combine components into a graph, but when performance becomes unacceptable (i.e. too much copying in memory), combine components without violating the first Existential Rule. Note that the second Existential Rule must be violated (rightfully) in this step because the point is exactly to introduce shared state to remove the copying.

 
I'm not sure I would agree with 2 or 3.  AFAIK nothing in FBP requires the problem it is solving to have preexisting asynchrony.  And neither does FBP require copying.



If you have read this far, you must at least understand the frustration that I have. Please let me know what you think, or better yet, let me know if something is not sound! Thank you!



I think you might have some misunderstanding about FBP and how it fits in to the big picture.

Although some people here have extended or are extending FBP into the higher orders,
in general, from an architectural point of view, FBP is similar to an orchestration script, such as BPEL or even Ant.

FBP does't have a coordination language per se (or at least, not yet), bu it does have fbp files that describe a network (very similar to a markup language).
This is what allows easy recombination, and even graphical programming.

FBP is also a software engine of sorts, and has to run in a software process, so an FBP network is below a microservice 
(actually a microservice could be implemented as a set of FBP networks).

An FBP job normally runs like a batch file, from start to completion.  
But I'm fairly certain you can also leave it running, so that it will continue to accept data on it's input ports.  (Someone please confirm)

Otherwise, the work moves between components, as in assembly line, in a manner very similar to streaming.
(It is my understanding that FBP is very compatible with data streaming approaches such as audio streaming).

If you want to understand FBP, I recommend you try a craftsman's approach - try to build something small but real, then go for the bigger things.
Maybe try one of the other orchestration frameworks, so you can compare.   Maybe take a look at a real assembly line.

Hopefully, you should be able to get a feel for how FBP fits in somewhere along the way.

John Cowan

unread,
Aug 29, 2015, 11:42:22 AM8/29/15
to flow-based-...@googlegroups.com
Humberto Madeira scripsit:

> FBP is somewhere below Microservices, and above functions.

I agree. Perhaps FBP and its components should be renamed "Nanoservice
Architecture" and "nanoservices" for marketing purposes. This would also
suggest sexy connections with nanomachines and nanoscale culture generally.

> I think of it this way: inside a component, we use stack-oriented
> programming (von Neumann) outside, we let the framework do its thing.

Pedantic historical note: Except for special cases like program loading,
modern architectures are Harvard rather than von Neumann. I haven't
written any self-modifying programs for many decades.

> FBP does't have a coordination language per se (or at least, not yet), bu
> it does have fbp files that describe a network (very similar to a markup
> language).

I sketched such a coordination language some time back. It's essentially
just a functional programming language, though with the ability to have
multiple values returned from a function (as distinct from returning a tuple).
It would be easy to make it a subset of Python or Lisp.

> This is what allows easy recombination, and even graphical programming.

If you want it.

> An FBP job normally runs like a batch file, from start to completion.
> But I'm fairly certain you can also leave it running, so that it will
> continue to accept data on it's input ports. (Someone please confirm)

Yes, absolutely. Such things were often done in mainframe days.

> (It is my understanding that FBP is very compatible with data streaming
> approaches such as audio streaming).

Indeed.

--
John Cowan http://www.ccil.org/~cowan co...@ccil.org
A witness cannot give evidence of his age unless he can remember being born.
--Judge Blagden

Kenneth Kan

unread,
Aug 29, 2015, 4:17:48 PM8/29/15
to Flow Based Programming
nice, good to see this kind of explanation.

Thanks. I'm more looking for a "model" in which we can say with confidence this implementation is FBP but that implementation is not. This is by no means a complete one, so I want to throw it out there for ideas.
 
sounds a lot like actors.

To my limited knowledge, actors are different from FBP in that FBP *completely* separates the two worlds: a component operate in this synchronous, von Neumann world without ANY knowledge of other components, while all a graph sees is how these components are related. An actor still needs to "know" to whom a message it wants to send.

That's why I try to label and separate the two sets of rules. The three granularity rules only apply on how to move towards the ideal granularity of a component. I'm trying to come up with the smallest set of existential rules which we could use to validate/invalidate an implementation as FBP.

The actor model violates the first existential rule in that it's asynchronous at the actor level.

Kenneth Kan

unread,
Aug 29, 2015, 4:47:21 PM8/29/15
to Flow Based Programming
My experience with noflo was that the way graph execution works makes some things much more complicated compared to classical fbp. It is not apparent at first but it makes complexity grow.

Agreed. My attempt to devise a model is to understand what that something is that makes an FBP-like implementation the wrong approach, so a new-comer to FBP can say, "oh, it doesn't do X and Y, and this is why it wouldn't work."
 
From what I understand, common dataflow systems are very hard to use because they limit computations to a hierarchy of functions that get evaluated upon some change in inputs, programming this way is very hard compared to conventional structured/oop programming.

Do you have some examples of what these common dataflow systems are?

What do you mean by "a hierarchy of functions"? "Get[ting] evaluated upon some change in inputs" sounds like event-based programming. Am I getting the right idea?
 
FBP was inspired by this kind of machine, and this is where your answer may reside. We really like to make small things that do a single thing well, this is quite fashionable today in the world of programming, but each time new information is created by a function, all the meaning it has attached is lost. It needs to be carried over to the next function in some way to complete the program correctly, it might just be the memory of the programmer, the types involved or some other technique. In that slice of time where the new information is being built, ready to be returned or sent, we may want to produce more information related to the processed data, and FBP acknowledges this. 
In the case of the mechanical card sorter, it produced not only a sorted stack, but additional information like card count, faults, etc. The machine "understands" the domain of what is being done, it is not just a responsibility or a task, it encapsulates a job.


Thanks for the reference! I have certainly not been fortunate enough to see one in action... On this specific problem though, I believe why monads are fairly popular in FP circles, because it allows encapsulation of some contextual information why keeping a certain degree of purity. What does FBP bring to the table on this front vs frameworks/languages that provide context-sensitive programming that maintain purity?
 
Now, I might be writing too much but try to follow this idea: The granularity is not dictated by the need for asynchronicity, but the need for information to perform a job. Is a job something like "function(x){ return x * 2 }" ? To me it seems like this is just evaluating a formula, so the job could be "evaluate formula". Or if we go with the machine analogy, "Formula Evaluator". Then we could think the kind of information it can produce while doing its job, like the greatest result produced, smallest, divisions by zero, etc. All of this will not be useful for most programs, but it could be available as an output port, or configurable via IIPs.

I see where you are coming from. My only objection would be: that applies to any computation at all granularity level. The example you raised is obviously at the finest level, which still satisfies the constraint "something that needs some information in the relevant domain to perform a job". In the end, that's what computation is: it takes some information that it needs (i.e. defining the domain) and produces some output (i.e. performing the job). Maybe I have misunderstood your argument?
 
Another important idea is Information Packets. Originally I understood them as just a number or a string, or any basic type, but operating on that scale everywhere is not very useful, as you might have seen with other dataflow systems. The next step is records, structs, POJOs, dictionaries, hashmaps,  or any name you like, the idea is similar. Many languages have immutable versions of them or you can fake them, so even if you are sharing a reference to a certain record, it will be read only, or make a copy to create a new version, so the performance cost is paid only if writes are made. Again we are working on traditional PC hardware, if you used some many-cpu system with dedicated ram for each cpu the story would be different.

Yea, I agree. IP is a very powerful concept. The only reason why I put a constraint of performance in granularity evaluation is because there is really no theoretical basis for why a component cannot be just a simple addition or if-else function; I would be delighted to be convinced otherwise though. In fact, your example above is a valid instance of this.

My intuition is that those of us who have tried "fine-grained" FBP know from experience that "fine-grained" FBP doesn't work, and my exploration is to understand why. Of course, when starting out in solving a new problem, one doesn't know where to begin when it comes to granularity. What I want is a model that can inform me in which direction I should move towards as I'm exploring and developing software for a particular domain, without accidentally "breaking" FBP just because it is an easy way out.

Alfredo

unread,
Aug 29, 2015, 5:53:04 PM8/29/15
to Flow Based Programming


El sábado, 29 de agosto de 2015, 17:47:21 (UTC-3), Kenneth Kan escribió:
My experience with noflo was that the way graph execution works makes some things much more complicated compared to classical fbp. It is not apparent at first but it makes complexity grow.
 
Agreed. My attempt to devise a model is to understand what that something is that makes an FBP-like implementation the wrong approach, so a new-comer to FBP can say, "oh, it doesn't do X and Y, and this is why it wouldn't work." 
A key thing that wasn't mentioned is Groups or Brackets. Dealing with substreams has larger implications. 
 
From what I understand, common dataflow systems are very hard to use because they limit computations to a hierarchy of functions that get evaluated upon some change in inputs, programming this way is very hard compared to conventional structured/oop programming.

Do you have some examples of what these common dataflow systems are?
What do you mean by "a hierarchy of functions"? "Get[ting] evaluated upon some change in inputs" sounds like event-based programming. Am I getting the right idea?
 
 Yes, systems like shader editors, excel, procedural geometry generators, they are built around an algorithm that re evaluates values upon changes in dependencies. So if we had a node that adds two numbers, and a node that squares the result of the first, if we change one of the addends, the sum is re evaluated, and then the square is re evaluated. I bet that you used excel and it works for math formulas, but the paradigm breaks very fast if you need anything more complicated. Hence macros and plugins were created. This is what people think about when they hear "dataflow". 

 
FBP was inspired by this kind of machine, and this is where your answer may reside. We really like to make small things that do a single thing well, this is quite fashionable today in the world of programming, but each time new information is created by a function, all the meaning it has attached is lost. It needs to be carried over to the next function in some way to complete the program correctly, it might just be the memory of the programmer, the types involved or some other technique. In that slice of time where the new information is being built, ready to be returned or sent, we may want to produce more information related to the processed data, and FBP acknowledges this. 
In the case of the mechanical card sorter, it produced not only a sorted stack, but additional information like card count, faults, etc. The machine "understands" the domain of what is being done, it is not just a responsibility or a task, it encapsulates a job.


Thanks for the reference! I have certainly not been fortunate enough to see one in action... On this specific problem though, I believe why monads are fairly popular in FP circles, because it allows encapsulation of some contextual information why keeping a certain degree of purity. What does FBP bring to the table on this front vs frameworks/languages that provide context-sensitive programming that maintain purity?
FBP components have a similar role, but they are much easier to program, you can explain how to build a component for a FBP framework in minutes, try to do that with monad transformers and arrows. But I digress, there's a tendency to make everything pure and minimalistic, but as we know from experience, the world isn't pure and requirements are not minimalistic, things change and it is much easier to alter a FBP graph or some component code than it is to keep the whole system pure. I really like the idea of writing components in the language that is best for the "job" the component has, so if the best is haskell, then use that, if it is APL, then use that. In other words, the advantage is that the "job" can be approached alone without the need to comply with the type requirements of the system as a whole. ( I would really like to see a FBP framework for F#, and if I have time for it might try to make one.)
 
 
Now, I might be writing too much but try to follow this idea: The granularity is not dictated by the need for asynchronicity, but the need for information to perform a job. Is a job something like "function(x){ return x * 2 }" ? To me it seems like this is just evaluating a formula, so the job could be "evaluate formula". Or if we go with the machine analogy, "Formula Evaluator". Then we could think the kind of information it can produce while doing its job, like the greatest result produced, smallest, divisions by zero, etc. All of this will not be useful for most programs, but it could be available as an output port, or configurable via IIPs.

I see where you are coming from. My only objection would be: that applies to any computation at all granularity level. The example you raised is obviously at the finest level, which still satisfies the constraint "something that needs some information in the relevant domain to perform a job". In the end, that's what computation is: it takes some information that it needs (i.e. defining the domain) and produces some output (i.e. performing the job). Maybe I have misunderstood your argument?
 
 It's hard to discuss this kind of topic, as the terminology we use has such an overloaded meaning, but I'll try again. What I mean by this is that there is a human factor in making components, that can predict that some events during the job might be useful , some might not, and they might be available for sending before the whole job is done, or maybe the job never stops like a server and data is produced at intervals. Computing things is easy once we have the algorithm, but that's not the problem we are trying to solve here. We don't want to do much algorithmic work with the graph, what we want to do is coordination.
Say that you have a component that reads files, it accepts a stream of file names. As file names come, they are read from disk, the usual way of dealing with this kind of task in a conventional system is to read files one by one, check exceptions, allocate memory if needed, etc. In FBP the component programmer can provide several outputs for this kind of task, and configuration. For example, send file contents as they are read, send the whole thing when done, send an ok or error packet after each file read with associated file data, output file sizes, only check if files exist, etc. It works as a machine that deals with the job, with some configuration , it isn't "just a function the returns more than one value". The output of "ok/error" could be used to feed a progressbar or a timeout process watching the file reader, or the next stage of processing. The reality of it is that the component might be a graph made out of simpler components but that's an implementation detail.

 
Another important idea is Information Packets. Originally I understood them as just a number or a string, or any basic type, but operating on that scale everywhere is not very useful, as you might have seen with other dataflow systems. The next step is records, structs, POJOs, dictionaries, hashmaps,  or any name you like, the idea is similar. Many languages have immutable versions of them or you can fake them, so even if you are sharing a reference to a certain record, it will be read only, or make a copy to create a new version, so the performance cost is paid only if writes are made. Again we are working on traditional PC hardware, if you used some many-cpu system with dedicated ram for each cpu the story would be different.

Yea, I agree. IP is a very powerful concept. The only reason why I put a constraint of performance in granularity evaluation is because there is really no theoretical basis for why a component cannot be just a simple addition or if-else function; I would be delighted to be convinced otherwise though. In fact, your example above is a valid instance of this.

My intuition is that those of us who have tried "fine-grained" FBP know from experience that "fine-grained" FBP doesn't work, and my exploration is to understand why. Of course, when starting out in solving a new problem, one doesn't know where to begin when it comes to granularity. What I want is a model that can inform me in which direction I should move towards as I'm exploring and developing software for a particular domain, without accidentally "breaking" FBP just because it is an easy way out.
I think that Paul would agree with me on this that solving a problem is more important than theoretical purity, but I get where you are trying to go with this.

Kenneth Kan

unread,
Aug 29, 2015, 6:01:44 PM8/29/15
to Flow Based Programming
On Friday, 28 August 2015 17:40:37 UTC-4, Kenneth Kan wrote:

What is the right granularity level for an FBP component?

Whatever level works best for you.  Seriously.

FBP is not an appliance.  Some assembly required.

Yes, I understand that FBP is not an appliance. What I try to avoid though, is intuition-based development. The more I learn from experience with software, the more I mistrust my intuition. The reason why frameworks in general and FBP specifically exist in the first place is so that we don't program whatever we feel like. Sufficient empirical evidences in our industry have already proven that that is not the ideal approach.

More importantly, any non-trivial software project is not the work of one single person. What works best for me may not work best for a lot of people. The purpose of a structured mental framework is to provide that common understanding. Wouldn't you say?
 
 
The question bothers me so much because a wrong understanding of the correct granularity creates so much complexity that after a while you would be asking: why even bother with FBP?

Because it lets you change things around quickly, without fear of breaking something. 

So do OOP, FP, AOP, and basically what all paradigm/framework/stack promise. I want to understand why; otherwise, the fuzzy definition of what "flow-based" means is exactly why there are many FBP-like frameworks that end up not delivering that promise of productivity.
 
 
I believe most who have tried "fine-grained" FBP in practice with a non-trivial project have encountered at least once, if not many times, that the running graph is so complicated that maintaining a mental model of it becomes a problem in and of itself.

If the model is getting too complex, you should try breaking it up into subnets.

That is a common feature of FBP-like implementations. Apparently that by itself is not sufficient, if the implementation does not follow FBP principles (and I'm trying to figure out what those are and why they are important).
 


My mental exploration begins with this question: Why did FBP even appeal to me in the first place? On my first attempt several years back it was mostly that I could visualize my code with a clean separation of concerns between components.

FBP is only one kind of programming technique that does this.
 
After my “sabbatical" and having re-read JPM’s book, I realized that the real pot of gold at the end of the rainbow was actually to escape the von Neumann model. Yes, visualization is important; modularity is important; reusability is important; but there are well-researched (and implemented) solutions to these problems in the von Neumann world.
 
FBP also gives you some defence against Amdahl's world.

Agreed on both points. We're talking about the same thing, that those qualities are not what makes FBP shine. My quest is to find what FBP really brings to the table that other techniques don't.
 
 

I believe that FBP (or at least frameworks that are FBP-like) is gaining momentum because we’re finally catching up with reality that the physical world cannot be captured in a shared-memory model, nor can our *mental* world handle one gargantuan bloc of code that shares memory. The need is there, and there’s been a plethora of approaches on how to manage this "post-von Neumann" world, such as microservices and software agents.


You can believe what you want, but I've seen nothing in the market to reflect this.  

AFAIK, most programmers just get by with what they have, and they will accept any lumps they get as long as they don't have to learn anything new. 

I absolutely agree with the last point. A grim view on human nature, but true to a degree...
 


For the sake of a comprehensive analysis, here is my own mental model of different software layers in relative abstraction, from the abstract to the concrete:
  • Software system/application, which serves a collection of one or more business objective(s)
  • Software agents[1], a logically independent entity that handles a single aspect of a business problem
  • Microservice, an independently running service that tackles a single technical problem
  • Computer program, which solves an engineering problem with clearly defined domain, parameters, and results (e.g. take two streams of documents and merge them into one, but not present two lists of documents and allow the user to interactively select which to keep as documents arrive)
  • Function, the basic unit of logical computation
 Unfortunately, these aren't really a hierarchy.

Nope. Never meant a hierarchy. In fact, I intentionally avoided that term as each of them represents a range and a software architect may very well drop some of them in her design. These are relative comparison. e.g. a function can never be more abstract than a program, or, a microservice can never be more concrete than a program.
 
 
So I asked myself, where does (or should) FBP break the spectrum?

FBP is somewhere below Microservices, and above functions.  Computer programs are some other thing that doesn't belong in the hierarchy.
Agents don't quite fit in the hierarchy either.

Again, no hierarchy is intended. Perhaps I should've explicitly stated that from the beginning.

On "computer programs", I understand it's easy to get into a semantics discord. Use whatever term appropriate, as long as that abstraction level deals with a clearly defined domain, parameters, and results.

Agreed on your placement though. That's what was in my mind as well.
 
 
From what I’ve understood by reading JPM’s book and my limited experiences in a few FBP-like implementations, I call this layer the “von Neumann limit”, above which shared memory does not exist, but below which there is an illusion that the entire world is single-threaded with a single memory space, which is where the von Neumann model excels.


I think of it this way:  inside a component, we use stack-oriented programming (von Neumann) outside, we let the framework do its thing.

What do you mean by "let the framework do its thing"?
 
 

In other words, we have two rules (here onward called the “Existential Rules”) to determine whether a system implements FBP:
  1. There may not be asynchronous operations. e.g. putting a process to sleep and sending an HTTP request are blocking operations.
  2. There must not be state shared between components. This may seem obvious but what this constraint implies is that there cannot be any free variable in each component. An example violation would be a call to write to a file by name on the filesystem if the two processes happen to be running on the same machine.
The two constraints are by no means new as they are mentioned in JPM’s book, though I would like to highlight them since these two constraints are together the single most important concept in FBP, as they define what FBP is by placing it along the software abstraction spectrum, at least under this model.

I'm not sure I follow - I think you mean rules for an FBP component, not a system - I will defer to Paul on this.  

To demonstrate why this limit is significant, imagine that we set the breaking point on a more abstract level (i.e. making a component “coarser”): each component, like a microservice or a full-fledged service, may now take and send asynchronous operations at will. This results in unpredictable behaviors for obvious reason. Of course, there are strategies dealing with this problem in “conventional” programming paradigm, but a more robust alternative to this problem is exactly what FBP is offering. Whereas conventional solutions requires a number of runtime checks, validations, and logs, FBP offers the guarantee at the framework level!

You are redefining what it means to be a component here.  Meaning you are not really talking about FBP at this point.

Yes, sorry for the confusion, I do mean rules for a component, as the semantics of FBP depends on that.

Ultimately, I want to have some rules of thumbs (note that I'm not calling these "Laws") on determining what makes a component, since components are the building blocks of FBP. In the same spirit, a function, as in functional programming, is defined as a relation between a domain and a codomain, without any side effect. The definition of the foundational entity of any paradigm should be clear to a new-comer; if the axioms are wrong, any discussion on top of that would be meaningless.

 
On the contrary, let’s push the breaking point down to a more concrete level (i.e. making a component “finer"): each component, like a computer program or a function, may now access some global state. This is an obvious problem to a seasoned programmer so no further elaboration is needed on this topic.
 
I would suggest you elaborate - I missed your point here.  Components have access to shared state - file system, database, etc.
 
What is interesting is the corollary to that. One may ask what if there is no shared state whatsoever? Well, in order for that to happen, a lot of copying in memory is needed and it becomes more expensive as one moves down towards finer components.
 
I'm not sure I follow this either.  How do you lock a file for writing if you don't have shared state?

Sorry for being fuzzy here. Before I elaborate on this point, let me define what I mean by "shared state".

It's a given that any useful system needs to change the state ultimately, otherwise it's just a useless box that heats up and does nothing. By shared state I mean effect that can be accidentally introduced to another part of a software system in a different layer of abstraction.

To illustrate this point, imagine this FBP hierarchy (now this is definitely a hierarchy because each layer depends on the one below):

- User of the software system/application/program
- Graph
- Component
- Instruction

We can at least agree that all state is "shared" at the highest level. To the user, it's just one giant "thing" that performs some desired task(s).

Let's take the database example. A component can of course connect to the database, but to a component it is the *only* component connecting to the database. Of course, what good is it if a database is only "shared" with one? This is the illusion that I mentioned.

A component's behavior does not depend on other parts of system changing the state of what it perceives is its "dedicated" resource. That concern lies one level up. To a graph, the intent is clear: you have these components accessing the same database so that they could work together to produce some useful result. To a component, however, FBP should be able to give it this guarantee/illusion: "You are the only one in the world. Don't worry about anything else." It's this separation of concerns that drove me to believe that this "world-splitting" constraint is so fundamental to defining FBP, or any good abstraction.

Paul can confirm on this one: I also believe that this is why externalizing relationships between components (in contrast to the actor model) is so important in FBP. It gives all components the guarantee that they don't need to know anything but their own domains.
 
 
One may also suggest that a sufficiently sophisticated compiler can effectively remove a lot of run-time copying (a la Haskell). This approach requires purity at the function level and the ability to infer types across all the components, which is impractical given FBP concerns itself not with the implementation details of individual components, opting for flexibility and modularity over performance.

In short, we have three rules (here onward called the “Granularity Rules”) when it comes determining the (approximately) right granularity for an FBP component:
  1. Start with the von Neumann model in a component. i.e. just start programming the way one always has, well, for most at least, that the programming language must be synchronous.
  2. As soon as one reaches the point where she needs asynchronous operations within a component, break it apart into multiple components.
  3. Combine components into a graph, but when performance becomes unacceptable (i.e. too much copying in memory), combine components without violating the first Existential Rule. Note that the second Existential Rule must be violated (rightfully) in this step because the point is exactly to introduce shared state to remove the copying.

 
I'm not sure I would agree with 2 or 3.  AFAIK nothing in FBP requires the problem it is solving to have preexisting asynchrony.  And neither does FBP require copying.

No, FBP doesn't require copying. The point was that copying is inevitable given how a proper FBP implementation should work. Because FBP requires isolation of shared state (as defined above), copying is inevitable as the system wouldn't produce anything useful otherwise.

The granularity rules do not define FBP. They merely serve as a guideline to reaching the "right" granularity for a particular component. One may certainly ignore #2 and #3 if performance isn't critical to the problem that she's trying to solve. In fact, most problems are well-served by the von Neumann model. That's why the model is so successful. What FBP brings to the table is a model that works for problems that lie *outside* of the von Neumann model.

On the comment on pre-existing asynchrony, that's the area that I want to explore. What do you think is the value of FBP if there isn't an asynchrony issue in a particular problem? My gut reaction to such a problem would be to just use a pure FP language as it is well-suited for that domain.
 



If you have read this far, you must at least understand the frustration that I have. Please let me know what you think, or better yet, let me know if something is not sound! Thank you!



I think you might have some misunderstanding about FBP and how it fits in to the big picture.

You are too kind. :) I know I have misunderstood FBP for sure, hence my "sabbatical" away from it before and my hesitation to dive back in now.
 

Although some people here have extended or are extending FBP into the higher orders,
in general, from an architectural point of view, FBP is similar to an orchestration script, such as BPEL or even Ant.

FBP does't have a coordination language per se (or at least, not yet), bu it does have fbp files that describe a network (very similar to a markup language).
This is what allows easy recombination, and even graphical programming.

That's what I want to know myself: is FBP only just BPEL/Ant/etc with a graphical interface?
 

FBP is also a software engine of sorts, and has to run in a software process, so an FBP network is below a microservice 
(actually a microservice could be implemented as a set of FBP networks).

Completely agreed.
 

An FBP job normally runs like a batch file, from start to completion.  
But I'm fairly certain you can also leave it running, so that it will continue to accept data on it's input ports.  (Someone please confirm)

Otherwise, the work moves between components, as in assembly line, in a manner very similar to streaming.
(It is my understanding that FBP is very compatible with data streaming approaches such as audio streaming).

If you want to understand FBP, I recommend you try a craftsman's approach - try to build something small but real, then go for the bigger things.
Maybe try one of the other orchestration frameworks, so you can compare.   Maybe take a look at a real assembly line.

Hopefully, you should be able to get a feel for how FBP fits in somewhere along the way.

Perhaps I have not been fortunately enough to use a real FBP system, because my previous experiences have not been too satisfactory, as a user at least. Do you have some recommendations on this front?

Kenneth Kan

unread,
Aug 29, 2015, 6:12:16 PM8/29/15
to Flow Based Programming, co...@mercury.ccil.org

> FBP is somewhere below Microservices, and above functions.  

I agree.  Perhaps FBP and its components should be renamed "Nanoservice
Architecture" and "nanoservices" for marketing purposes.  This would also
suggest sexy connections with nanomachines and nanoscale culture generally.

I'd suggest the opposite. Having a hot term is a problem because it's easily misunderstood. The term Flow-Based Programming is one such example.

And the term nanoservices usually carries a negative connotation. See http://arnon.me/wp-content/uploads/2010/10/Nanoservices.pdf
 

> I think of it this way:  inside a component, we use stack-oriented
> programming (von Neumann) outside, we let the framework do its thing.

Pedantic historical note:  Except for special cases like program loading,
modern architectures are Harvard rather than von Neumann.  I haven't
written any self-modifying programs for many decades.

I think this is another such term. :) The term "von Neumann" architecture is easy to understand (and misunderstand). What I wanted to convey originally was the idea of shared state.
 

> FBP does't have a coordination language per se (or at least, not yet), bu
> it does have fbp files that describe a network (very similar to a markup
> language).

I sketched such a coordination language some time back.  It's essentially
just a functional programming language, though with the ability to have
multiple values returned from a function (as distinct from returning a tuple).
It would be easy to make it a subset of Python or Lisp.

So is this really what FBP is? An equivalent of a functional programming language with a visual face?

Kenneth Kan

unread,
Aug 29, 2015, 7:04:12 PM8/29/15
to Flow Based Programming

A key thing that wasn't mentioned is Groups or Brackets. Dealing with substreams has larger implications. 

Yes. Groups/Brackets are powerful concepts. If I were to compare a "reactive" FBP framework like NoFlo and "classical" FBP, we wouldn't say adding proper implementations of groups/brackets would bring NoFlo on par with FBP right?
 
 
From what I understand, common dataflow systems are very hard to use because they limit computations to a hierarchy of functions that get evaluated upon some change in inputs, programming this way is very hard compared to conventional structured/oop programming.

Do you have some examples of what these common dataflow systems are?
What do you mean by "a hierarchy of functions"? "Get[ting] evaluated upon some change in inputs" sounds like event-based programming. Am I getting the right idea?
 
 Yes, systems like shader editors, excel, procedural geometry generators, they are built around an algorithm that re evaluates values upon changes in dependencies. So if we had a node that adds two numbers, and a node that squares the result of the first, if we change one of the addends, the sum is re evaluated, and then the square is re evaluated. I bet that you used excel and it works for math formulas, but the paradigm breaks very fast if you need anything more complicated. Hence macros and plugins were created. This is what people think about when they hear "dataflow". 

I see. So you don't really mean event-based programming. This is more in line with logical programming (my apology for another use of loaded terms) like Prolog and friends and denotational design like Conal Elliott's FRP?
 
FBP components have a similar role, but they are much easier to program, you can explain how to build a component for a FBP framework in minutes, try to do that with monad transformers and arrows.

haha. Good point!
 
But I digress, there's a tendency to make everything pure and minimalistic, but as we know from experience, the world isn't pure and requirements are not minimalistic, things change and it is much easier to alter a FBP graph or some component code than it is to keep the whole system pure. I really like the idea of writing components in the language that is best for the "job" the component has, so if the best is haskell, then use that, if it is APL, then use that. In other words, the advantage is that the "job" can be approached alone without the need to comply with the type requirements of the system as a whole. ( I would really like to see a FBP framework for F#, and if I have time for it might try to make one.)

The language-agnostic nature of FBP was what drew me into FBP as well. I certainly advocate against complete purity and minimalism, otherwise I'd be using Lisp or something like that. What I'm pursuing is a realm in which FBP shines, which is still a bit shadowy for me. In fact, FBP is itself the manifestation of purity and minimalism in the realm of "non-von Neumann" (please suggest a better term if you have one) world; otherwise I would just use some Java-based orchestration tool or something like Akka in Scala, Apache Storm, etc.

You mentioned that it's much easier to write a component than a monad transformer, with which I cannot agree more. The pain point that I see isn't the difficulty of writing a component; it's that it's hard to use FBP at the system level. I know that FBP is used in multiple places, but it isn't exactly well-known as a technique, despite having been in existence for decades with much community interest.

Perhaps it's just marketing, though I'd say it's not exactly easy to get an FBP system set up and running either.
 
 
 It's hard to discuss this kind of topic, as the terminology we use has such an overloaded meaning, but I'll try again. What I mean by this is that there is a human factor in making components, that can predict that some events during the job might be useful , some might not, and they might be available for sending before the whole job is done, or maybe the job never stops like a server and data is produced at intervals. Computing things is easy once we have the algorithm, but that's not the problem we are trying to solve here. We don't want to do much algorithmic work with the graph, what we want to do is coordination.

Yep. Agreed. Hence my use of the term "non-von Neumann world".
 
Say that you have a component that reads files, it accepts a stream of file names. As file names come, they are read from disk, the usual way of dealing with this kind of task in a conventional system is to read files one by one, check exceptions, allocate memory if needed, etc. In FBP the component programmer can provide several outputs for this kind of task, and configuration. For example, send file contents as they are read, send the whole thing when done, send an ok or error packet after each file read with associated file data, output file sizes, only check if files exist, etc. It works as a machine that deals with the job, with some configuration , it isn't "just a function the returns more than one value". The output of "ok/error" could be used to feed a progressbar or a timeout process watching the file reader, or the next stage of processing. The reality of it is that the component might be a graph made out of simpler components but that's an implementation detail.

Right. Would I be right if I say that this particular problem can also be solved by using something like Apache Storm? More generally, I'm trying to answer the question: why use FBP vs other mature tools for coordination? 
 
I think that Paul would agree with me on this that solving a problem is more important than theoretical purity, but I get where you are trying to go with this.

I agree that solving a problem is more important as well. It's not so much purity or theory that I'm after. It's some kind of common understanding, without which is why we have this fragmentation of FBP implementations. Note that I didn't use the term diversity of FBP implementations because apparently we are still having discussions around "reactive" vs "classical" FBP. When we don't even have that understanding, it's rather hard to solve a problem or get things done. Maybe individually we could, but not as a community.

John Cowan

unread,
Aug 29, 2015, 8:51:18 PM8/29/15
to flow-based-...@googlegroups.com
Kenneth Kan scripsit:

> The language-agnostic nature of FBP was what drew me into FBP as well. I
> certainly advocate against complete purity and minimalism, otherwise I'd be
> using Lisp or something like that.

Lisp is the opposite of purity and minimalism: it is the Big Ball of Mud
antipattern language.
Is it not written, "That which is written, is written"?

John Cowan

unread,
Aug 29, 2015, 9:03:42 PM8/29/15
to Kenneth Kan, Flow Based Programming
Kenneth Kan scripsit:

> And the term nanoservices usually carries a negative connotation. See
> http://arnon.me/wp-content/uploads/2010/10/Nanoservices.pdf

Ah, I didn't know that.

> So is this really what FBP is? An equivalent of a functional programming
> language with a visual face?

I think the insight is that pure lazy functional programming and dataflow
are two sides of the same coin. A Haskell program, for example, has a
stateless inside and a stateful outside, because the main program lives
in the IO monad. FBP networks have a stateless outside (the graph)
and potentially stateful insides (the components).

Of course a component can be written in Haskell and have a pure core
wrapped in a stateful mantle running in a pure network!
May the hair on your toes never fall out! --Thorin Oakenshield (to Bilbo)

Humberto Madeira

unread,
Aug 30, 2015, 9:25:42 AM8/30/15
to Flow Based Programming


On Saturday, 29 August 2015 18:01:44 UTC-4, Kenneth Kan wrote:
On Friday, 28 August 2015 17:40:37 UTC-4, Kenneth Kan wrote:

What is the right granularity level for an FBP component?

Whatever level works best for you.  Seriously.

FBP is not an appliance.  Some assembly required.

Yes, I understand that FBP is not an appliance. What I try to avoid though, is intuition-based development. The more I learn from experience with software, the more I mistrust my intuition. The reason why frameworks in general and FBP specifically exist in the first place is so that we don't program whatever we feel like. Sufficient empirical evidences in our industry have already proven that that is not the ideal approach.

I wasn't suggesting intuition as the basis for granularity.  Actually the basis for granularity needs to be whatever you are focusing on when you model.  A modeling context.

If you need to model other, more fine-grained contexts to support your main one, that is OK and even expected - but those contexts need to be separate. Black boxes to each other.

If I'm modeling a financial transaction, I might refer to accounts and payments, but the details of the calculations will be buried in a component, inside which it will either be implemented as a subnet, or simply, using von neumann style.
The determining factor being, whether there is any value in making that context easier to orchestrate. With the understanding that if the determination changes, the implementation can also change as needed.
 
More importantly, any non-trivial software project is not the work of one single person. What works best for me may not work best for a lot of people.

Over time, I have come to the understanding that software written by multiple people is a mess.  Even in teams with the best of intentions.
Teams where people are working at cross-purposes produce an even worse mess.

The new "special-snowflake" generation of programmers is particularly good at ignoring preexisting conventions.

My ideal is one programmer per modeling context.
 
The purpose of a structured mental framework is to provide that common understanding. Wouldn't you say?

I would suggest that the purpose of any framework is to generate (and enforce) sufficient numbers of independent modeling contexts so that programmers can be kept apart (work independently).

Good fences make good neighbours.

Keeping contexts separate also offers the benefits of componentization.  You can assign each component separately for programming, possibly even outsource it.
 
 
 
The question bothers me so much because a wrong understanding of the correct granularity creates so much complexity that after a while you would be asking: why even bother with FBP?

Because it lets you change things around quickly, without fear of breaking something. 

So do OOP, FP, AOP, and basically what all paradigm/framework/stack promise. I want to understand why; otherwise, the fuzzy definition of what "flow-based" means is exactly why there are many FBP-like frameworks that end up not delivering that promise of productivity.
 
Neither OOP nor AOP require orchestration.  They can't deliver a clean separation of concerns (lack of interdependency) without it.

FP is better at separating concerns, but without orchestration, the resulting code isn't very malleable.  Plus, it has several warts that make it unacceptable for mainstream development.
 
 
I believe most who have tried "fine-grained" FBP in practice with a non-trivial project have encountered at least once, if not many times, that the running graph is so complicated that maintaining a mental model of it becomes a problem in and of itself.

If the model is getting too complex, you should try breaking it up into subnets.

That is a common feature of FBP-like implementations. Apparently that by itself is not sufficient, if the implementation does not follow FBP principles (and I'm trying to figure out what those are and why they are important).
 

I'm not sure I follow...  Could you please expand on why you don't think it is sufficient?

 


My mental exploration begins with this question: Why did FBP even appeal to me in the first place? On my first attempt several years back it was mostly that I could visualize my code with a clean separation of concerns between components.

FBP is only one kind of programming technique that does this.
 
After my “sabbatical" and having re-read JPM’s book, I realized that the real pot of gold at the end of the rainbow was actually to escape the von Neumann model. Yes, visualization is important; modularity is important; reusability is important; but there are well-researched (and implemented) solutions to these problems in the von Neumann world.
 
FBP also gives you some defence against Amdahl's world.

Agreed on both points. We're talking about the same thing, that those qualities are not what makes FBP shine. My quest is to find what FBP really brings to the table that other techniques don't.

I think the most important thing is that FBP (and its cousins) allow you to model the code (behaviour) more like it was data.  

I create a bunch of behavioural components, assign them names, and attach them in whatever order I want.  
And then (providing all the components are available) I can change my mind at run-time.

I don't have to go back to a compiler to change something around.

  
 
 
From what I’ve understood by reading JPM’s book and my limited experiences in a few FBP-like implementations, I call this layer the “von Neumann limit”, above which shared memory does not exist, but below which there is an illusion that the entire world is single-threaded with a single memory space, which is where the von Neumann model excels.


I think of it this way:  inside a component, we use stack-oriented programming (von Neumann) outside, we let the framework do its thing.

What do you mean by "let the framework do its thing"?

Just reinforcing that the component is not the only black box. The flow framework also needs  to also be a black box to its components.

Each flow framework will have its own approach to queuing , stack management, exception handling, etc. 
You can use a stack-based debugger to debug the component, from the point where the component picked up its data to the point where it pushed out its data.

Otherwise you can only say that the data is between components somewhere in the framework. (even though you are actually still inside a von Neumann machine)
Depending on the framework, you could be in a different thread, or in a queue or some other thing.  Stack-based debuggers need not apply.

Debugging between components needs a different approach.  Depending on the maturity of the framework, it may even provide some support.


Ultimately, I want to have some rules of thumbs (note that I'm not calling these "Laws") on determining what makes a component, since components are the building blocks of FBP. In the same spirit, a function, as in functional programming, is defined as a relation between a domain and a codomain, without any side effect. The definition of the foundational entity of any paradigm should be clear to a new-comer; if the axioms are wrong, any discussion on top of that would be meaningless.

Unfortunately, the metaphysical "flooring" is a bit slippery here.  The component interface is dependent on its specific framework.  components written for one will not necessarily work in another.

This also means that different frameworks may need different rules of thumb.  Other than a general "avoid side effects in components", I'm not sure what else to say.

Specific frameworks will definitely have their own.
 
 
On the contrary, let’s push the breaking point down to a more concrete level (i.e. making a component “finer"): each component, like a computer program or a function, may now access some global state. This is an obvious problem to a seasoned programmer so no further elaboration is needed on this topic.
 
I would suggest you elaborate - I missed your point here.  Components have access to shared state - file system, database, etc.
 
What is interesting is the corollary to that. One may ask what if there is no shared state whatsoever? Well, in order for that to happen, a lot of copying in memory is needed and it becomes more expensive as one moves down towards finer components.
 
I'm not sure I follow this either.  How do you lock a file for writing if you don't have shared state?

Sorry for being fuzzy here. Before I elaborate on this point, let me define what I mean by "shared state".

It's a given that any useful system needs to change the state ultimately, otherwise it's just a useless box that heats up and does nothing. By shared state I mean effect that can be accidentally introduced to another part of a software system in a different layer of abstraction.

To illustrate this point, imagine this FBP hierarchy (now this is definitely a hierarchy because each layer depends on the one below):

- User of the software system/application/program
- Graph
- Component
- Instruction

We can at least agree that all state is "shared" at the highest level. To the user, it's just one giant "thing" that performs some desired task(s).

Let's take the database example. A component can of course connect to the database, but to a component it is the *only* component connecting to the database. Of course, what good is it if a database is only "shared" with one? This is the illusion that I mentioned.

A component's behavior does not depend on other parts of system changing the state of what it perceives is its "dedicated" resource. That concern lies one level up. To a graph, the intent is clear: you have these components accessing the same database so that they could work together to produce some useful result. To a component, however, FBP should be able to give it this guarantee/illusion: "You are the only one in the world. Don't worry about anything else." It's this separation of concerns that drove me to believe that this "world-splitting" constraint is so fundamental to defining FBP, or any good abstraction.

I have some bad news then.  A framework like FBP has no way to constrain its components.

The fact you can program a component in a normal programming language means you can do anything the language can.

Having said that, you can establish conventions for accessing shared data - even support it with library code - which is very important - but you just can't enforce/guarantee it.
 
Paul can confirm on this one: I also believe that this is why externalizing relationships between components (in contrast to the actor model) is so important in FBP. It gives all components the guarantee that they don't need to know anything but their own domains.
 
Sadlly, not quite.
 
I am personally working on such a framework, so I have gone over this issue a lot.

To make such guarantees about what a component can do, you either have to deliver it with the framework or in an addon, or you need to certify it.
Or you can make a special component-only programming language constrained in the way you want.

 
 
One may also suggest that a sufficiently sophisticated compiler can effectively remove a lot of run-time copying (a la Haskell). This approach requires purity at the function level and the ability to infer types across all the components, which is impractical given FBP concerns itself not with the implementation details of individual components, opting for flexibility and modularity over performance.

In short, we have three rules (here onward called the “Granularity Rules”) when it comes determining the (approximately) right granularity for an FBP component:
  1. Start with the von Neumann model in a component. i.e. just start programming the way one always has, well, for most at least, that the programming language must be synchronous.
  2. As soon as one reaches the point where she needs asynchronous operations within a component, break it apart into multiple components.
  3. Combine components into a graph, but when performance becomes unacceptable (i.e. too much copying in memory), combine components without violating the first Existential Rule. Note that the second Existential Rule must be violated (rightfully) in this step because the point is exactly to introduce shared state to remove the copying.

 
I'm not sure I would agree with 2 or 3.  AFAIK nothing in FBP requires the problem it is solving to have preexisting asynchrony.  And neither does FBP require copying.

No, FBP doesn't require copying. The point was that copying is inevitable given how a proper FBP implementation should work. Because FBP requires isolation of shared state (as defined above), copying is inevitable as the system wouldn't produce anything useful otherwise.

In classic FBP, you can pass around an object and modify it - no copying whatsoever.  You just have to make sure the object ownership is passed on.

Not sure if this is the case for noflo.

In my own framework, copying is a must as all IPs are immutable. (but copying is mostly reference copying, so it is relatively cheap)
 
The granularity rules do not define FBP. They merely serve as a guideline to reaching the "right" granularity for a particular component. One may certainly ignore #2 and #3 if performance isn't critical to the problem that she's trying to solve. In fact, most problems are well-served by the von Neumann model. That's why the model is so successful. What FBP brings to the table is a model that works for problems that lie *outside* of the von Neumann model.

On the comment on pre-existing asynchrony, that's the area that I want to explore. What do you think is the value of FBP if there isn't an asynchrony issue in a particular problem? My gut reaction to such a problem would be to just use a pure FP language as it is well-suited for that domain.

Disagree.  FBP was originally designed to speed up batch processing by adding in asynchrony.
Pure FP is also not as malleable as FBP.

The only reason to avoid FBP is if you don't have the experience with it.Or lack an implementation in the language you are using. 
Or if you have limited libraries in the language you are using.  Mind you - these are all definite issues.
 
 

Although some people here have extended or are extending FBP into the higher orders,
in general, from an architectural point of view, FBP is similar to an orchestration script, such as BPEL or even Ant.

FBP does't have a coordination language per se (or at least, not yet), bu it does have fbp files that describe a network (very similar to a markup language).
This is what allows easy recombination, and even graphical programming.

That's what I want to know myself: is FBP only just BPEL/Ant/etc with a graphical interface?
 
No.  There is also the asynchrony part, and the flow part.  Neither BPEL or Ant have task asynchrony (at least, not by default).

Also, BPEL is more of an RPC-like, while Ant's sets are rather limited (mostly file).
 

FBP is also a software engine of sorts, and has to run in a software process, so an FBP network is below a microservice 
(actually a microservice could be implemented as a set of FBP networks).

Completely agreed.
 

An FBP job normally runs like a batch file, from start to completion.  
But I'm fairly certain you can also leave it running, so that it will continue to accept data on it's input ports.  (Someone please confirm)

Otherwise, the work moves between components, as in assembly line, in a manner very similar to streaming.
(It is my understanding that FBP is very compatible with data streaming approaches such as audio streaming).

If you want to understand FBP, I recommend you try a craftsman's approach - try to build something small but real, then go for the bigger things.
Maybe try one of the other orchestration frameworks, so you can compare.   Maybe take a look at a real assembly line.

Hopefully, you should be able to get a feel for how FBP fits in somewhere along the way.

Perhaps I have not been fortunately enough to use a real FBP system, because my previous experiences have not been too satisfactory, as a user at least. Do you have some recommendations on this front?

Hmmm.  I'm not quite sure what would float your boat here.

How about, a web-page walker that searches for occurrences of a provided phrase? (provides list of URLs)
It should accept an initial URL a domain scope (a host name), and a phrase.

Scan each page for linked URL's, If a URL is outside of scope, drop it.

Only process each URL once.

Bonus points for showing intermediate results.

Now go back and take the rejected URLs and list them, but only if they also have the phrase.
Do not follow the rejected URLs to other URL's.

Feel free to replace with any other idea of a similar complexity.

Hope this helps

Paul Morrison

unread,
Aug 30, 2015, 10:16:31 PM8/30/15
to flow-based-...@googlegroups.com, bro...@gmail.com, Kenneth Kan
Hi Ken,

There is so much good stuff in this conversation that I haven't had time to digest.  However, one thing jumped out at me and I wanted to comment quickly, although it may open another bag of snakes...  ;-)

On Fri, Aug 28, 2015 at 5:40 PM, Kenneth Kan <ken...@gmail.com> wrote:

...snip...
 

In short, we have three rules (here onward called the “Granularity Rules”) when it comes determining the (approximately) right granularity for an FBP component:
  1. Start with the von Neumann model in a component. i.e. just start programming the way one always has, well, for most at least, that the programming language must be synchronous.
  2. As soon as one reaches the point where she needs asynchronous operations within a component, break it apart into multiple components.
  3. Combine components into a graph, but when performance becomes unacceptable (i.e. too much copying in memory), combine components without violating the first Existential Rule. Note that the second Existential Rule must be violated (rightfully) in this step because the point is exactly to introduce shared state to remove the copying.



Sorry, Ken, I really didn't relate to this!  I feel you are overthinking this problem.  This sounds more like a procedure than a set of rules.  And, if it is a procedure, I don't know how to follow it.

Define "start"!   I think the very first word is ambiguous!  I thought I described very clearly in my book how we designed applications - but maybe I just took it for granted...

FBP is a new/old paradigm - I don't believe you can get to it by starting with the von Neumann (Harvard?) paradigm - you have to start completely afresh - "become as a little child"!  Actually that's a good idea!

For me, FBP has always been an engineering type of discipline.  What we are trying to do when we build an FBP application is design a data processing factory - using standard types of machines.  In the real world we don't usually build our machines (components) from the atomic level up (except in nanotechnology!), but we do in programming - over and over again!   And the real world machine types follow a sort of paradigm - this was well-developed in the Unit Record world - we had sorters, collators, accounting machines (printers), calculators with various levels of computing power.  A designer did not have to design a brand new type of machine.  FBP is rather similar.  And unit record machines were parametrized using plugboards - so each machine had a fairly wide range of behaviours.

In today's programming world, the lowest level is a programming language statement!  If we're lucky, we get some standard subroutines like square root!

An engineering discipline requires training and experience.  But such disciplines don't build all their components - there is usually a hierarchy, from small to large.  In FBP, these might be components, subnets, networks, applications, company- or world-spanning networks...   As I've said elsewhere, you don't give an engineer a pile of girders and a manual, and tell her to build a bridge.  There is school, on-the-job training, and progress up through the ranks, all of which takes a while.  A bridge or a cathedral is also a team effort, so you have to be able to carve up the design early and hand off sections of it to different team members - for that you need clean interfaces between the chunks, and well-defined functions.

http://www.jpaulmorrison/fbp/image010.jpg is the middle 3rd of a large program which ran for 40 years (maybe is still running) in production at least once a night.  Note the components whose names start with MAX - they are all "off the shelf", and have no business knowledge.  INFQUEUE is a subnet consisting of a Writer-File-Reader sandwich, used to prevent deadlocks involving Sort, as described in the book.  The rest were written specifically for this application - and by a team of people following a predesigned schema.

The IPs were all business entities: e.g. accounts, transactions, plus a number of tables - not dates or currency amounts.

I don't remember that we had any particular trouble designing this - it probably had around 60 processes, and just grew quite naturally!

How did we design this network?   First we carved off the I/O and put it in separate components, most of which already existed  (I had been running this software for 5 years previously at a Data Centre).    Note MCBSIM at the centre top - this was a pretty general direct access file reader component, but it had business-related data in it. You will note it is in a loop structure, but in other networks it ran in flow-through mode.

In a multitasking environment, you might want to carve out CPU-intensive components as well.

MCBSER looks a bit too complex to me - 7 output ports - most likely, it started out simpler, and then people just added additional output ports without rearchitecting.

Somewhere in the book I describe various "directions" of development we use in FBP, sometimes all at once: top down, bottom up (you know these), centre out (build a skeleton or prototype, and then add editing, formatting of output, and other bells and whistles), and back-end forward (work back from the desired output).

FBP lends itself to prototyping and simulation.

Finally you seem preoccupied with granularity - if your IPs are objects of interest to your application, I think the component granularity falls right out naturally.   Remember that, in "classical" FBP, you don't disassemble an IP if you ever want to see it intact further on!  It's way too much trouble!  And why would you want to anyway?!  So a classical component will accept a small number of IPs (often one), perhaps do some transformation on it/them, perhaps create a new IP or drop an old one, and then go back to "receive".

Oh, and please reread http://www.jpaulmorrison.com/fbp/reuse.shtml  if you haven't recently.  Dave Brooks kindly said it was his favorite chapter!  The diagram at the end of the this illustrates the way I believe all disciplines evolve.  I just want to see this cycle keep rolling along!  

All the best

Paul M.




Ged Byrne

unread,
Aug 31, 2015, 6:39:59 AM8/31/15
to flow-based-...@googlegroups.com, bro...@gmail.com, Kenneth Kan
Can I just quote from the end of the reuse chapter.

"I believe that, unless companies start to bring engineering-type disciplines to application development, not only will they fail to take full advantage of the potential of computers, but they will become more and more swamped with the burden of maintaining old systems. You can't do a lot about old systems - I know, I've seen lots of them - but new systems can be built in such a way that they are maintainable. It should also be possible to gradually convert old programs over to the FBP technology piece-meal, rather than "big bang". "

How prophetic. There's so much hype around new software but the majority of developers are stuck nursing legacy systems.

Could this be where FBP's "killer app" lies - in a systematic approach to converting legacy software?

Any ideas what that approach would look like?
--
You received this message because you are subscribed to the Google Groups "Flow Based Programming" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flow-based-progra...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Humberto Madeira

unread,
Aug 31, 2015, 8:49:04 AM8/31/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com
Hi Ged,


On Monday, 31 August 2015 06:39:59 UTC-4, Ged Byrne wrote:
Can I just quote from the end of the reuse chapter.

"I believe that, unless companies start to bring engineering-type disciplines to application development, not only will they fail to take full advantage of the potential of computers, but they will become more and more swamped with the burden of maintaining old systems. You can't do a lot about old systems - I know, I've seen lots of them - but new systems can be built in such a way that they are maintainable. It should also be possible to gradually convert old programs over to the FBP technology piece-meal, rather than "big bang". "

How prophetic. There's so much hype around new software but the majority of developers are stuck nursing legacy systems.

Could this be where FBP's "killer app" lies - in a systematic approach to converting legacy software?

Any ideas what that approach would look like?



I'm going to go out on a limb and suggest that it is very likely to involve the Strangler pattern.
(a technique that is also recommended when converting legacy apps into microservices)

 --Bert

Ged Byrne

unread,
Aug 31, 2015, 11:36:55 AM8/31/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com
Hi Bert,

Is developing new code from scratch required for a strangler application?

Does it allow for mining existing assets and rewriting them within a new framework?

Regards,



Ged.
--

Ged Byrne

unread,
Aug 31, 2015, 11:37:56 AM8/31/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com
That's should say rewiring, not rewriting. My phone thinks differently, but it is wrong.

Paul Morrison

unread,
Aug 31, 2015, 1:36:08 PM8/31/15
to flow-based-...@googlegroups.com
Great article!   Sounds very similar to my then boss's "turning icebergs into ice cubes"...  And yes, I'd start at the periphery too - carve off the I/O processes first, and then work inwards - sort of like carving a turkey!   Remember that an old-fashioned single-thread application is one FBP process, so you just add a few input and output ports to your ever-diminishing "old app process", and connect up your network!

--

Paul Morrison

unread,
Aug 31, 2015, 2:36:03 PM8/31/15
to flow-based-...@googlegroups.com
I am surprised - if a microservice is bigger than an FBP component, I think we have to change the name "microservices" to something like "midiservices", not go smaller!  And it seems to me "nano" has been grabbed by nanotechnology!   Now Figure 15.6 is almost "nano", but IMO totally impractical for real work!  So what prefixes are left? Pico, femto, atto...?

What seems strangest to me is bundling communication in with the service - FBP components can be considered services, but they have almost minimal communication with their outside world - "send" and "receive" - which don't have much much more overhead than a "call".   In Chap. 15 of the 2nd edition (see Fig. 15.4) I argued against cluttering up the FBP driver with more complex communication techniques - I still believe that is correct!

Ged Byrne

unread,
Aug 31, 2015, 3:18:58 PM8/31/15
to flow-based-...@googlegroups.com
Hi Paul,

I think the key difference is that with micro services the level of granularity is based on deployment rather than development.

It's the minimum that can be independently deployed, usually within a cloud environment.

Including a full communication stack is needed to keep that deployability. You don't have to worry about component versioning, just the protocols being used.

Also, since the components are communicating over http connections complex protocols are needed for security. Communication must be encrypted to avoid men in the middle and throttled to prevent denial of service.

So micro services will represent a level above the flow components. I think you could easily build micro services from flow components, but I think you'd want to keep service reserved for exposed endpoints.

Regards,


Ged

Paul Morrison

unread,
Aug 31, 2015, 3:56:05 PM8/31/15
to flow-based-...@googlegroups.com
So microservices would actually be subnets, which in turn would contain components for encryption, throttling and communication generally...  Makes sense!

Alfredo Sistema

unread,
Aug 31, 2015, 3:59:34 PM8/31/15
to flow-based-...@googlegroups.com
Microservices are a nebulous subject but think of them as programs that provide only a few services for the system, for example a payment processing microservice that gets requests and replies the status of a payment, dealing with the details of that by itself. It's related to splitting monolithic services into smaller ones that can be deployed and developed independently. In the case of FBP it could be just one graph, the micro part is tied to the responsibilities it has and not the scale of the implementation.

Humberto Madeira

unread,
Aug 31, 2015, 9:33:38 PM8/31/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com
Hi Ged,


On Monday, 31 August 2015 11:36:55 UTC-4, Ged Byrne wrote:
Hi Bert,

Is developing new code from scratch required for a strangler application?

You will write some new code initially.  Typically some sort of shim or "legacy adapter" (a.k.a facade).  And it will need to be placed in as a "component" of the new framework.

Initially, the app makes calls through the framework, and then the shim to reach the "legacy component(s)"

You can deploy it at this point.

Then you slowly copy/rewrite logic chunk-by-chunk from the legacy component into new code that you call instead of the legacy component.

Eventually you no longer need to call the legacy component, and you can drop it out.

There are several subtle variations, of course, including an inside-out "reverse shim" approach.

It also helps if you have good regression testing of the app as a whole while going through this process.

I recommend searching for Strangler Pattern on Google and reading at least a few variations.

Back in the olden days, we used to call this "code evolution, not revolution".
 
Does it allow for mining existing assets and rewriting them within a new framework?

Yes.  Precisely.  

It also prevents you from having to do it all at once.

All or nothing ports/rewrites are very risky things.  Look what happened to Netscape.

--Bert



Paul Morrison

unread,
Aug 31, 2015, 9:49:59 PM8/31/15
to flow-based-...@googlegroups.com, bro...@gmail.com, Kenneth Kan
Trivial in FBP!  Calling the interface that allows the old code to run within an FBP network a shim, legacy adapter or facade seems to me to give it more gravitas than it really deserves!  It's about 10 minutes work in FBP, if that!  But yes, it's exactly the same idea as described in my previous post!

Ged Byrne

unread,
Sep 1, 2015, 12:28:55 AM9/1/15
to flow-based-...@googlegroups.com, bro...@gmail.com, Kenneth Kan
So I could approach it like this?

1. Create a simple pass through proxy FBP network. All requests and responses are simply forwarded on.
2. Add routing logic that handles request that meet certain criteria but continues to forward the rest.
3. It may be desirable to both handle and forward the request and then compare the results. It the new code produces a different result log the error and return the legacy response. Once the new code has proven itself reliable this can be removed.
4. Keeping adding additional routing criteria and implementation components so that the coverage of the new code steadily increases.
5. Keep going until the new code coverage is 100% and the old system can be turned off.

Humberto Madeira

unread,
Sep 1, 2015, 5:28:59 AM9/1/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com
Hi Ged,


On Tuesday, 1 September 2015 00:28:55 UTC-4, Ged Byrne wrote:
So I could approach it like this?

1. Create a simple pass through proxy FBP network. All requests and responses are simply forwarded on.
2. Add routing logic that handles request that meet certain criteria but continues to forward the rest.
3. It may be desirable to both handle and forward the request and then compare the results. It the new code produces a different result log the error and return the legacy response. Once the new code has proven itself reliable this can be removed.
4. Keeping adding additional routing criteria and implementation components so that the coverage of the new code steadily increases.
5. Keep going until the new code coverage is 100% and the old system can be turned off.



Yes. This could be a reasonable approach.  It all depends on your starting point.  The devil is in the details.

I did this once for a medium-sized enterprise app where we also had to replace the entire UI, because the previous team had made a total mess of mixing logic with UI code.

The 3 man portion of the team that did the "service shim" took about 3 months to produce a pure service shim that could handle all the requests.
They had to find all the mixed in bits of logic in the UI section and stuff them back down into the service layer.
This was particularly slow and painful since the original team had been disbanded already and wasn't available for guidance.

If the original app had already been request based (nowadays much more likely), the initial shim would have been so much simpler.

In any case, the general steps you outlined in your approach should be fine.  
It is just that, depending on what you start with, some of the initial steps may be surprisingly bigger than you would expect.

--Bert

Paul Morrison

unread,
Sep 1, 2015, 10:04:02 AM9/1/15
to flow-based-...@googlegroups.com
Ah, I see!  I was assuming a single stand-alone app - the initial stage of converting to FBP would be trivial.

Ged's solution is oriented towards keeping a real-time system running continuously - very much like Wayne Stevens' idea of how you fix a dam (p. 72 of the 2nd edition).  I agree, converting a UI could get pretty complex!

Paul Morrison

unread,
Sep 1, 2015, 3:46:33 PM9/1/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com


On Sunday, August 30, 2015 at 10:16:31 PM UTC-4, Paul Morrison wrote:

FBP is a new/old paradigm - I don't believe you can get to it by starting with the von Neumann (Harvard?) paradigm - you have to start completely afresh - "become as a little child"!  Actually that's a good idea!

For me, FBP has always been an engineering type of discipline.  What we are trying to do when we build an FBP application is design a data processing factory - using standard types of machines.
    ...

An engineering discipline requires training and experience.  But such disciplines don't build all their components - there is usually a hierarchy, from small to large.  In FBP, these might be components, subnets, networks, applications, company- or world-spanning networks...   As I've said elsewhere, you don't give an engineer a pile of girders and a manual, and tell her to build a bridge.  There is school, on-the-job training, and progress up through the ranks, all of which takes a while.  A bridge or a cathedral is also a team effort, so you have to be able to carve up the design early and hand off sections of it to different team members - for that you need clean interfaces between the chunks, and well-defined functions.


I thought there would be more discussion of this idea.  One of the things that appeals to me about "classical" FBP is the "tangible" nature of IPs.  Given that old-style programming tends to be loops within loops, and that memory is an array of pigeonholes, one of the major sources of system bugs is that you can stuff one pigeon in on top of another one without noticing, and you can reach in and extract what you think is a pigeon, and don't know if you have retrieved a real pigeon, or complete garbage.

That's why I keep saying you can't just start off coding in von Neumann (Harvard?) style, and suddenly when it gets too complex, switch over to FBP - you have to start thinking about your data factory from the start, and maybe start with a small network - your prototype or simulation -  and then start growing it organically.   I also strongly suggest you look at the networks in my book, and look at the component list in JavaFBP - there are (is?) a variety of types of component in the list, so that should be enough to get started.

We should also start thinking about designing courses in FBP, and also grabbing students' hearts and minds as early as possible!

Raoul Duke

unread,
Sep 1, 2015, 4:00:15 PM9/1/15
to flow-based-...@googlegroups.com
> That's why I keep saying you can't just start off coding in von Neumann
> (Harvard?) style, and suddenly when it gets too complex, switch over to FBP

What style are the individual data processor components written in?

Paul Morrison

unread,
Sep 1, 2015, 5:24:11 PM9/1/15
to flow-based-...@googlegroups.com
As you know, the components are simple von Neumann programs - maybe I should have said "You can't just start off coding an application in von Neumann style..."

Raoul Duke

unread,
Sep 1, 2015, 5:29:11 PM9/1/15
to flow-based-...@googlegroups.com
> As you know, the components are simple von Neumann programs - maybe I should
> have said "You can't just start off coding an application in von Neumann
> style..."

Then I think what you said about pigeon hole programming doesn't
entirely go away?

John Cowan

unread,
Sep 1, 2015, 5:37:14 PM9/1/15
to flow-based-...@googlegroups.com, bro...@gmail.com, ken...@gmail.com
Paul Morrison scripsit:

> That's why I keep saying you can't just start off coding in von Neumann
> (Harvard?) style, and suddenly when it gets too complex, switch over to FBP

Oh, absolutely. But components will still typically be written in traditional
imperative style, or else in functional style.
An observable characteristic is not necessarily a functional requirement.
--John Hudson

Alfredo

unread,
Sep 1, 2015, 10:27:16 PM9/1/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com
I would like to help , since the main problem with FBP is the lack of available material with modern solutions. We started a "documenting" effort with the flowbased wiki but It got stale, I'd rather spend effort in making example programs made with FBP, with the thought process behind them. Nothing beats that kind of material.

Paul Morrison

unread,
Sep 2, 2015, 10:41:58 AM9/2/15
to flow-based-...@googlegroups.com
Good point, Raoul, but I think the "pigeon hole" problem is vastly diminished, for the following reasons

- typically FBP components are simple loops (receive; exit if end of stream; do some logic; repeat)  - the pigeon hole problem tends to show up when you have complex logical structures

- the data the component works with is in:

   - mostly: IPs, which behave like tangible objects, with a well-defined lifetime, from creation to destruction
   - short term method memory,
   - a small number of process-wide instance variables, and
   - an even smaller amount of global, app-wide, memory (we try to avoid that type, and are aware of its risks when we have to!).

This is the reason why I keep stressing the need for a process to account for IPs that it is given responsibility for (all the classical implementations have a count which is increased by create and receive, and decreased by send and drop, and must be zero when the process deactivates) 

In AMPS, the first FBP implementation, we had what we called "shunts", which were like 1-slot connections, with both ends attached to the same process!  These behaved exactly like a desk drawer, with space for one object.  Of course send and receive couldn't suspend, so we provided an error return code.  These have since been replaced by a process stack service, but we could easily reintroduce them!

HTH

Paul

Raoul Duke

unread,
Sep 2, 2015, 2:16:27 PM9/2/15
to flow-based-...@googlegroups.com
Thanks for the insights, great food for thought.

Kenneth Kan

unread,
Sep 7, 2015, 3:23:44 AM9/7/15
to Flow Based Programming
Hi everyone, thank you for all the input and sorry for going MIA! It's been quite a long week for me and I also wanted some time to absorb the info here before responding.

I realized that I framed the original post so horribly that attention was fixated on the granularity aspect and the three steps (vs the first set of rules that actually tries to define FBP). And yes, Paul you are right that it is more like a procedure. For now, let's disregard that. I feel the need to clarify why I even went down this line of thinking in the first place.

The problem that I see with FBP right now is that it suffers, for lack of a better term, a marketing problem. Alfredo mentioned that microservices was a nebulous term, and I would agree with him; sadly, FBP is even more nebulous for those who are not familiar with it. There is the book, and some examples mentioned somewhere on the internet. The more unfortunate fact is that the "Flow-Based" part is rather generic; we have implementations like noflo that any new-learner would intuitively associate with FBP, to no one's fault really, as it's natural to think noflo, or other reactive, flow-like frameworks, as "flow-based".

I am aware that FBP is supposed to be a different school of philosophy when it comes to programming. It isn't a "framework", an "implementation", or a "technology". The issue is, that's too much for someone who just stumbled upon this (going back to the "nebulous" aspect). There should be one or two frameworks that a new-comer could get up and running within hours, if not minutes, and "test the waters" without having to adjust her mindset too much.

Such a framework should be familiar enough that it still resembles "traditional programming", but what it is "under the hood" is still FBP and will become apparent for this new-comer as she becomes more experienced with it in her transition into the FBP mindset. What I've been trying to get at is that guiding principle (or what I call the "foundational theory").

Humberto pointed out that I should go for a craftsman's approach, and that was my original intention. I just had a tiny problem: there wasn't much direction. Let me correct myself: there was some direction, but it was too "nebulous". I can't simply run some system and be able to understand what FBP can do in the real world. Yes, I can go take a look at an assembly line or a factory, but how does this translate into a software architecture? History has shown what the likely result of such an unguided craftsman's exploration would be: creation of another reactive/dataflow framework.

What I want to do is not to generalize FBP. Quite the contrary. I think FBP is too loosely defined. I want to "specify" FBP so that it is not too unreachable for conventional programmers.

Paul, you mentioned that there's school, on-the-job training, and so on. Essentially, there is a progression in learning. That's the gap that I want to bridge, a framework so that conventional programmers can slowly ease into FBP, but there will be a progression. That's why I was trying to get at a theory. That's why I think a detailed procedural approach is important. And that's why the granularity, the definition of a component, FBP's place within the "software stack", and the details are important to me.

Hopefully this has clarified my position a bit better than my previous attempt.

Kenneth Kan

unread,
Sep 7, 2015, 3:27:01 AM9/7/15
to Flow Based Programming, ken...@gmail.com, co...@mercury.ccil.org
I think the insight is that pure lazy functional programming and dataflow
are two sides of the same coin.  A Haskell program, for example, has a
stateless inside and a stateful outside, because the main program lives
in the IO monad.  FBP networks have a stateless outside (the graph)
and potentially stateful insides (the components).

Of course a component can be written in Haskell and have a pure core
wrapped in a stateful mantle running in a pure network!

That's a very interesting insight. Thank you for bringing this up. I think FBP's "stateful-inside" approach is far superior. There's a reason why large stacks of monad transformers and *Unsafe functions are needed in large applications in Haskell.

Kenneth Kan

unread,
Sep 7, 2015, 3:29:08 AM9/7/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com
I would like to help , since the main problem with FBP is the lack of available material with modern solutions. We started a "documenting" effort with the flowbased wiki but It got stale, I'd rather spend effort in making example programs made with FBP, with the thought process behind them. Nothing beats that kind of material.

I think that would be really helpful! I'd love to help as well but I get the sense that my FBP-chops aren't quite there yet. Looking forward to seeing your tutorials!

Alfredo

unread,
Sep 7, 2015, 11:34:32 AM9/7/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com
I think that you are reflecting the thoughts of many Kenneth. I think that noflo requires too much setup ( software and mental ), because the whole experience with noflo-ui is not finished. But that's normal with any big project like that.
Since ES6 is a reality now, I started a small project to bring classical FBP anywhere with an ES6 based engine, it still requires a lot of work but the goals are : 
  • Almost zero setup ( should be as simple as using jquery )
  • A new DSL and editor ( already implemented )
  • Easy to integrate in existing applications
  • As classical as I can get it to be ( considering cooperative coroutines )
  • Run with io.js for server and batch applications
Since I'm using BabelJs , pretty much any system that can run ES5 will be able to run it.
This is a preview of how a component like ConcatStr from JavaFBP would look like in this engine : 

It's a work in progress and everything is subject to change, etc.

Alfredo

unread,
Sep 7, 2015, 11:41:10 AM9/7/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com
Made a mistake in the sample code posted, this is the fixed version :
http://i.imgur.com/nTERkSv.png

Kenneth Kan

unread,
Sep 7, 2015, 12:38:56 PM9/7/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com
I think that you are reflecting the thoughts of many Kenneth. I think that noflo requires too much setup ( software and mental ), because the whole experience with noflo-ui is not finished. But that's normal with any big project like that.
Since ES6 is a reality now, I started a small project to bring classical FBP anywhere with an ES6 based engine, it still requires a lot of work but the goals are : 
  • Almost zero setup ( should be as simple as using jquery )
  • A new DSL and editor ( already implemented )
  • Easy to integrate in existing applications
  • As classical as I can get it to be ( considering cooperative coroutines )
  • Run with io.js for server and batch applications
Since I'm using BabelJs , pretty much any system that can run ES5 will be able to run it.


This is great news! It'd be nice to see it in action. I've been trying to write a classical FBP framework in JS myself, but realized that I may not be fully trained in the FBP way just yet. It's great to see someone working on one in the pipeline!

By the way, it's been my impression that the core problem of noflo isn't that it's hard to setup (though that is one of the issues), but that it is fundamentally different from FBP. I was trying to argue that we need both to succeed. What are your thoughts on that?

Alfredo

unread,
Sep 7, 2015, 1:26:53 PM9/7/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com
I think that variety is great, but it differs quite a bit from classical FBP ( we went through this many times ), all in all I can understand the design decisions that made it happen, there are limitations with js that only now can be addressed thanks to ES6 and whatnot.
IMHO what we call FBP is tied to waiting on queues, back pressure and concurrency, and both of those things are not present in noflo. You can still make graphs designs that make sense for both classical and noflo, but in my limited experience with noflo, you need more complex graphs to tie things together since execution of a send can lead to a chain of activations that don't let other parts of the graph update, so it becomes in a way synchronous.
But still, I learned a lot from it, and I hope that it gets better, we really need variety.

Kenneth Kan

unread,
Sep 7, 2015, 2:16:01 PM9/7/15
to Alfredo, Flow Based Programming
I see where you are coming from. And yea, I learned a lot from noflo as well.

Variety is definitely key to exploration and improvement. One of the reasons why I want to write an FBP framework myself as well, is to learn from building something from first principles, though even to this day I'm a bit unclear what those first principles are. Haha. I have a sense of them but no clear conviction.

Paul Morrison

unread,
Sep 7, 2015, 10:04:34 PM9/7/15
to flow-based-...@googlegroups.com, Alfredo
The elephant in the room, it seems to me, is that JS can still only handle one core - unless you use Workers, in which case you don't have really good communication between the Workers - no back pressure, etc.

Please tell me I'm wrong...!  :-).

--

Alfredo Sistema

unread,
Sep 7, 2015, 10:14:40 PM9/7/15
to Paul Morrison, flow-based-...@googlegroups.com
It's not really about cores or threads, right now we can get concurrency, and parallelism can be done by handling workers from within a process. If you check the example code I posted and compare it to ConcatStr from JavaFBP, you can tell that they are both similar. A yield here and there because the coroutines need to be cooperative, but overall you can get the same experience, like backpressure and blocking sends/receives.
Right now thanks to some complex efforts like emscripten, multi threaded programs can be compiled into js and run, obviously by simulating threads.

Alfredo Sistema

unread,
Sep 7, 2015, 10:49:43 PM9/7/15
to Paul Morrison, flow-based-...@googlegroups.com
It'd be nice to have threads though, even if simulated, to take advantage of the parallelism provided by FBP. What's important for me now is growing the software design knowledge base related to FBP, writing frameworks is a nice hobby but we need to talk more about doing software with them IMHO.
I'll share a design next weekend to kickstart discussion.

Raoul Duke

unread,
Sep 8, 2015, 12:22:09 AM9/8/15
to flow-based-...@googlegroups.com

Kenneth Kan

unread,
Sep 8, 2015, 9:51:23 AM9/8/15
to Flow Based Programming, sistemas...@gmail.com
To add to what Alfredo has mentioned, I thought that native support of threads wasn't a requirement as the first versions of FBP implementations were done in green threads. And I thought the problem was that JS was by design "asynchronous" in that it is guaranteed to run to completion without blocking, which is mitigated by ES6 as pointed out by Alfredo. The issue seems to be that the syntax (i.e. `yield`) is unconventional to those outside of the JS world. Is that right?
To unsubscribe from this group and stop receiving emails from it, send an email to flow-based-programming+unsub...@googlegroups.com.

Paul Morrison

unread,
Sep 8, 2015, 12:08:58 PM9/8/15
to flow-based-...@googlegroups.com, Alfredo Sistema, Kenneth Kan, John Cowan
Hi Ken, glad to see you're back getting your teeth into these issues! 

On Tue, Sep 8, 2015 at 9:51 AM, Kenneth Kan <ken...@gmail.com> wrote:
To add to what Alfredo has mentioned, I thought that native support of threads wasn't a requirement as the first versions of FBP implementations were done in green threads.

The first two implementations of FBP ran on IBM mainframes, which in those days I believe only had one CPU. Later, more cores were introduced, but we assigned different OS jobs to the other cores, so green threads with overlapped I/O, within a single job, still made a lot of sense for those machines.  IBM machines did have multiple tasks, which later on could take advantage of multiple cores, but these tasks were synchronized via a wait/post mechanism, and I never succeeded in building a viable FBP system using wait/post.  Later other synchronization mechanisms were introduced, but IIRC they were only available under pthreads, which were not universally available...   John, maybe you can correct me...?

Of course IBM could have supported FBP 40 years ago, in which case we would probably have had much more sophisticated scheduling!  Parenthetically, the internal architecture of AMPS (supported by 1 person, me) was actually very similar to that of CICS (IBM's other main transaction management system) (supported by a small army).

I now have a 4-core machine on my desk, and I like seeing JavaFBP keeping all the cores busy!  I suppose we could just run our "modern" FBP implementations just on one core, and have the other cores doing other work... but it seems a bit restrictive!
 
And I thought the problem was that JS was by design "asynchronous" in that it is guaranteed to run to completion without blocking, which is mitigated by ES6 as pointed out by Alfredo.

If "run to completion without blocking" refers to deadlocks - we have always considered deadlocks a design issue.  We never had a deadlock show up in a properly designed network, with the emphasis on "properly designed".  Are you saying that deadlock avoidance is one of the reasons for the limitations in JS - if so, I kind of doubt that!
 
The issue seems to be that the syntax (i.e. `yield`) is unconventional to those outside of the JS world. Is that right?

I don't mind 'yield' so much, but I seem to remember that you can't bury 'yield' inside a service - why does 'yield' have to be 'visible'?   Also, I believe you can only use the "top" frame - I think we can live with that, but IMHO it's just a stupid restriction, arising not from philosophical reasons, but because the JS gurus are too stubborn to use multiple fibers!

Regards,

Paul M.

John Cowan

unread,
Sep 8, 2015, 12:50:00 PM9/8/15
to flow-based-...@googlegroups.com, Alfredo Sistema, Kenneth Kan, John Cowan
Paul Morrison scripsit:

> I don't mind 'yield' so much, but I seem to remember that you can't bury
> 'yield' inside a service - why does 'yield' have to be 'visible'? Also, I
> believe you can only use the "top" frame - I think we can live with that,
> but IMHO it's just a stupid restriction, arising not from philosophical
> reasons, but because the JS gurus are too stubborn to use multiple fibers!

These are basically the same point: JS yield is not "stackful", to use
the terminology of Lua. See the paper at
<http://www.inf.puc-rio.br/~roberto/docs/MCC15-04.pdf> and/or the slides
at <http://laser.inf.ethz.ch/2012/slides/Ierusalimschy/coroutines-4.pdf>.

Lua would make a good FBP language, not just for extension as in C++-FBP,
but all by itself.
Unless it was by accident that I had offended someone, I never apologized.
--Quentin Crisp

Paul Morrison

unread,
Sep 8, 2015, 2:42:31 PM9/8/15
to flow-based-...@googlegroups.com, John Cowan, Kenneth Kan, Alfredo Sistema
Hi John,

I agree.  IIUC Lua internally uses green threads, but apparently it's quite easy to use pthreads threading, as e.g. https://github.com/hnakamur/lua-native-thread-experiment

Looks like Hiroaki hasn't worked on this since 2012, but it might be interesting to work on extending it...

As you mentioned, I built a Lua interface in C++FBP, using Boost, and that seems to give good native threading - my thinking was that C++ would be a good base language to build DSLs on, and it would be up to the users whether they wanted to use Lua - wholly, partially, or not at all - rather than mandating the language they used..

Interesting slides and presentation!  Thanks!

Paul


--
You received this message because you are subscribed to the Google Groups "Flow Based Programming" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flow-based-progra...@googlegroups.com.

Paul Morrison

unread,
Sep 8, 2015, 8:25:58 PM9/8/15
to flow-based-...@googlegroups.com, bro...@gmail.com, Kenneth Kan
Hi Alfredo,

I have to admit - it looks pretty good... except IMHO for those totally unnecessary "yield"s! :-)   So I assume you have figured out how to receive selectively from different input ports...

A nit (made visible by the 'yield' convention) is that you really don't need to suspend on the 'drop'.  But yes, it's very clear - and you just used standard ES6...?  This could be the answer to the maiden's prayer!

--

Paul Morrison

unread,
Sep 8, 2015, 8:29:14 PM9/8/15
to Alfredo Sistema, flow-based-...@googlegroups.com
Yup, if you have a manageable application that we could use to demonstrate the approach on, it would be great!

I always liked the Appkata idea, as it emphasizes maintainability - which, to me, is the key advantage of FBP.  The group showed some interest in them a few years ago, but it seems to have died down!

Alfredo Sistema

unread,
Sep 8, 2015, 9:27:10 PM9/8/15
to flow-based-...@googlegroups.com

I know that it looks unnecessary but it can work as a nice trick to avoid "pass" yields, to allow cooperative coroutines without breaking the illusion. Of course sometimes a "pass" yield will be needed. But don't think of a drop as blocking.

Alfredo Sistema

unread,
Sep 9, 2015, 2:05:09 AM9/9/15
to flow-based-...@googlegroups.com
I have to add that you are right Paul, this is plain ES6.
Also I have to add, it is much easier to reason about the source of a classical FBP component compared to a noflo one, unless wirepattern is being used.
Anyway, regarding AppKatas, I'd prefer something more interesting, but coming up with small projects is quite hard, maybe we should start a thread about that.

Kenneth Kan

unread,
Sep 9, 2015, 9:45:26 AM9/9/15
to Flow Based Programming, sistemas...@gmail.com, ken...@gmail.com, co...@ccil.org
If "run to completion without blocking" refers to deadlocks - we have always considered deadlocks a design issue.  We never had a deadlock show up in a properly designed network, with the emphasis on "properly designed".  Are you saying that deadlock avoidance is one of the reasons for the limitations in JS - if so, I kind of doubt that!
I don't mind 'yield' so much, but I seem to remember that you can't bury 'yield' inside a service - why does 'yield' have to be 'visible'?   Also, I believe you can only use the "top" frame - I think we can live with that, but IMHO it's just a stupid restriction, arising not from philosophical reasons, but because the JS gurus are too stubborn to use multiple fibers!

It's not so much about the deadlock. I think Alfredo explained it well. Cooperative multitasking is so fundamental in JS' programming semantics. Breaking that by removing the yields but still allowing blocks would render it not JS. Imagine extending a class in Java doesn't guarantee you a sub-class, but instead it only "probably" gives you one. Concurrency is explicit and required in JS just like type declarations are explicit and required in Java.

Having said that, personally I think the JS model of concurrency is inferior. I try to avoid the language like a plague when possible. My point is that you may as well use another language and have it compile to JS if you break that model, because the larger implication is that most JS programmers would not be able to effectively program in a JavaScript that blocks.

Kenneth Kan

unread,
Sep 9, 2015, 9:49:03 AM9/9/15
to Flow Based Programming, jpau...@gmail.com
Can't wait! I've been hoping for someone with the necessary knowledge in both FBP and JS to make it work. It's a non-trivial challenge. Please let me know if I could be of help on the JS side!
To unsubscribe from this group and stop receiving emails from it, send an email to flow-based-programming+unsub...@googlegroups.com.

Paul Morrison

unread,
Sep 9, 2015, 10:29:45 PM9/9/15
to Flow Based Programming, Alfredo, Kenneth Kan, John Cowan, bro...@gmail.com

On Tuesday, September 8, 2015 at 9:27:10 PM UTC-4, Alfredo wrote:

I know that it looks unnecessary but it can work as a nice trick to avoid "pass" yields, to allow cooperative coroutines without breaking the illusion. Of course sometimes a "pass" yield will be needed. But don't think of a drop as blocking.


Sorry, Alfredo, the words are all English, but I don't have the least idea what they mean in what you wrote!  :-)   I have 'yield's in JSFBP, but they're all buried in services, such as 'receive' and 'send' - which is where IMHO they belong!  What is the "illusion"?  Are green threads an illusion of some kind?  What is a '"pass" yield' - it sounds like something from football...!

Ken, you say, "Cooperative multitasking is so fundamental in JS' programming semantics" - I don't see it anywhere, unless you mean callbacks, which are pretty simplistic - or are you referring to Promises or Futures, in which case I would say they are not fundamental - they seem to me to be more of an afterthought...

And, Ken, why on earth would JS without 'yield's being visible not be JS?!

Aha, wait a second!  For me, JS is just a way of building FBP components!  Do you mean that there are people out there for whom it is something different?!  And they'd be offended if I use their shiny new language for actually building real-life applications...?!!   Pinch me - the rabbit hole is getting deeper, and I can't get out!  :-)

 

Alfredo Sistema

unread,
Sep 9, 2015, 11:00:03 PM9/9/15
to Paul Morrison, Flow Based Programming, Kenneth Kan, John Cowan, bro...@gmail.com
Paul, when writing a coroutine you usually have a loop in the coroutine function/process and yield either values or pass if there's nothing to return, example:
while(true){
     foo();
     bar();
     yield; // pass execution and wait for my turn
}

I do not know the details of why are yields only supported in the body of a generator function, but we don't have much choice in that.
What Kenneth might be referring to with the nature of js is that there's an event loop, and blocking execution is very frowned upon, so hidden blocking functions can cause much trouble. It might be one of the motivations for the yield limitation, or it might be that generators are translated into a state machine and going more than one level deep could have implications that escape my understanding. It would be such if generators were implemented differently I guess, like in lua or when you use fibers with node.

Paul Morrison

unread,
Sep 10, 2015, 11:28:08 AM9/10/15
to Alfredo Sistema, Paul Morrison, Flow Based Programming, Kenneth Kan, John Cowan, bro...@gmail.com
Thanks, Alfredo!  That starts to make sense... a bit! 

I guess, for me, the pass yield isn't necessary as 99.9% of components do sends or receives or both, so there is an implicit 'yield' when a buffer fills up or goes empty, respectively.  The concern about blocking might make sense in non-FBP environments, but FBP processes' main job is communication! 

 I guess an example of a process which doesn't do sends or receives might be a "Heartbeat" process which monitors the general health of a network - but that probably doesn't make sense in a green threading environment, as a heartbeat should maintain some kind of regularity...  Using native threads, I would give a Heartbeat process a slightly higher priority than other processes as you really don't want it suspending at random intervals...

Re your other point: I am wondering if the "visible yield" rule is related to the fact that the new JS facilities only work with the top frame - and that IIUC is basically because they don't support multiple stacks!  So an implementation restriction is used to justify a language "standard" - isn't this a "leaky abstraction"?  And as you said, fibers get around this problem - so why are the JS people resisting them?!

Regards,

Paul

Alfredo Sistema

unread,
Sep 10, 2015, 11:47:30 AM9/10/15
to flow-based-...@googlegroups.com, Paul Morrison, Kenneth Kan, John Cowan, bro...@gmail.com
Purity of abstraction was never a goal of JavaScript, it is what it is, don't ask for much more.
In my particular case I want to allow processes to register callbacks and then callbacks will write into result queues for each process, so when their execution time comes, they can do sends, and whatnot with the resulting data from callbacks. So we get both things, classical fbp and parallel execution of some facilities, for example a process that starts a worker or many, and the results fromt he workers are then handled when the turn of the owning process comes. IMHO this is a nice compromise, we get parallelism when it's needed or makes sense, and coroutines for coordination.
In other words, for example a process called ExpensiveComputation would simply gather required packets from inports, start up a webworker, set the callback to get the results inside an internal queue only known by the worker and the process, and then pass. When the turn of ExpensiveComputation comes, checks for results and the continues normal execution, either sending results, dropping, etc.
A concept I'm experimenting with is "internal inports" to make this even easier, so that a process can wait on callbacks the same way it can read from inports.

Paul Morrison

unread,
Sep 11, 2015, 5:05:25 PM9/11/15
to Flow Based Programming, paul.m...@rogers.com, ken...@gmail.com, co...@ccil.org, bro...@gmail.com
This sounds a lot like our JSFBP function runtime.runAsyncCallback - https://github.com/jpaulm/jsfbp/blob/master/core/runtimes/FiberRuntime/index.js - I think@comFreek or possibly @tlrobinson (apologies if I gave credit to the wrong person) came up with this - great minds think alike!  But can you do it with only ES6?! 

Regards,

Paul

Kenneth Kan

unread,
Sep 11, 2015, 5:16:44 PM9/11/15
to Flow Based Programming, paul.m...@rogers.com, ken...@gmail.com, co...@ccil.org, bro...@gmail.com

On Wednesday, September 9, 2015 at 11:00:03 PM UTC-4, Alfredo wrote:

What Kenneth might be referring to with the nature of js is that there's an event loop, and blocking execution is very frowned upon, so hidden blocking functions can cause much trouble. It might be one of the motivations for the yield limitation, or it might be that generators are translated into a state machine and going more than one level deep could have implications that escape my understanding. It would be such if generators were implemented differently I guess, like in lua or when you use fibers with node.

That's right, though I wouldn't say blocking execution is frowned upon per se. The trend into generators and friends is a sign that people are wising up that blocking functions may not be a bad thing after all. It's that *implicitly* (I assume this was what you meant by "hidden"?) blocking. In the end, it's the semantics of the language that is so fixed in users' minds that it'll take forever to change.

A concept I'm experimenting with is "internal inports" to make this even easier, so that a process can wait on callbacks the same way it can read from inports.

What does "waiting on callbacks" mean exactly?

Ged Byrne

unread,
Sep 12, 2015, 5:51:08 AM9/12/15
to flow-based-...@googlegroups.com, John Cowan, Kenneth Kan, Paul Morrison, bro...@gmail.com
I see your using web workers as well as generators here.

Can I just take a step back and clarify my understanding o how this all fits together.

We start with a single processes within which the main script is executed. This is related to the page being displayed (I'm assuming a browser because of the web workers).

When we start up the weekend worker we begin a second process. This is the process in which we run our Flow based processes.

So we have the event driven process related to the User and the DOM they are interacting with. We have three event sources: the user, timeouts and the flow processes. Let's call this the DOM process.

We have the flow driven process running on a web worker handling background asynchronous activities that are not driven by User generated events. Let's call this the FBP process There will be queue endpoints that the DOM process will push IPs onto. The FBP processes can also raise events for the DOM process to handle. We can have multiple FBP processes on separate web workers if we want.

Does this sound right?

What about talking to external services? For example, talking to a RESTful or SOAP service. Woudl both the DOM and FBP process potentially make these calls, or should all such calls be delegated to the FBP or DOM process?

Regards,



Ged


Paul Morrison

unread,
Sep 12, 2015, 11:10:57 AM9/12/15
to Ged Byrne, flow-based-...@googlegroups.com, John Cowan, Kenneth Kan, Paul Morrison, bro...@gmail.com
Hi Ged, I assume weekend worker is web worker...?

I have attached a very simple client-server diagram - would it be possible for you to mark it up to show how your workers relate to it?  Maybe the two approaches are totally unrelated, but I feel more comfortable with diagrams!

Regards,

Paul
ClientServer.png

Alfredo Sistema

unread,
Sep 12, 2015, 11:30:52 AM9/12/15
to flow-based-...@googlegroups.com, John Cowan, Kenneth Kan, Paul Morrison, bro...@gmail.com

Ged, the main graph is ran within an interval in the main window, to allow for event processing. inside the main graph processes are generators, which may or may not fire up workers or child processses in the case of node or iojs. Spawned workers or child processes would write to a parent owned queue, and when the turn of the parent to execute comes, the queued data can be used. Communication with the main graph ( or other graphs running in the same page) is though pushing data into queues and passing a callback for output data if needed.
Running the graph inside a worker might not be feasible due to how restricted they are , but it is something worth exploring.
I hope that this description is clear.

Ged Byrne

unread,
Sep 13, 2015, 3:23:26 AM9/13/15
to flow-based-...@googlegroups.com, John Cowan, Kenneth Kan, Paul Morrison, bro...@gmail.com
HI Alfredo,

Won't running the graph within the main window using yields make the page extremely unresponsive to the user? 

Having user initiated events feed straight into an flow graph seems like a bad idea.  If the component that the user facing component is sending to becomes blocked the UI freezes until it becomes unblocked.

This is why blocking IO is seen as unacceptable in Javascript apps.  The user is king, they can never be ignored, there requests must always be handled immediately.  If the process is blocked at any point then the page will lock up and we can expect the user to hit refresh.  Then all in page state will be lost.  This can never happen, from a UX perspective.

It was developers doing to much work on the user interaction thread that killed Swing.  It has been the JS developers devotion to the UX that has made it so successful.  Any FBP iemplementation running in the browser must respect that discipline.  The main window must remain responsive.

Regards, 


Ged

Alfredo Sistema

unread,
Sep 13, 2015, 12:18:17 PM9/13/15
to flow-based-...@googlegroups.com, John Cowan, Kenneth Kan, Paul Morrison, bro...@gmail.com
This is how execution would look like : http://i.imgur.com/sXnTMJe.png
Sometimes an action takes too long in js, so an intermediate result is displayed, like a loading image or whatever, but if the user is hammering the system with events there's no way around it. Blocking from the perspective of the process does not mean that the execution is blocked or that no new events will be queued. There's no busy wait involved. Also expensive cpu operations can be interleaved by yielding a pass, like it's normal in cooperative multitasking systems.
I don't think that it would be reasonable to have a situation where the user is generating so much input that the system can't process it. And worst case, making the queue bigger would fix it.

Ged Byrne

unread,
Sep 13, 2015, 12:29:22 PM9/13/15
to flow-based-...@googlegroups.com, John Cowan, Kenneth Kan, Paul Morrison, bro...@gmail.com
Hi Alfred,

Ok. Just two questions:

1) Does yield return control to the event loop so that the user events will be processed? The documentation I've see says that control is returned to the calling function.

2) increasing the size of the queue for user events will just increase the poor response time. Consider a mouse over event. If that gets added to a queue with a backlog then there will be a delay between my mouse passing over and the event being handled.

Paul Morrison

unread,
Sep 13, 2015, 12:51:25 PM9/13/15
to Ged Byrne, flow-based-...@googlegroups.com, John Cowan, Kenneth Kan, bro...@gmail.com
Hi Ged,

I think you have to design the overall flow first - you're right that you can't afford to have one user's function block others, so you try to get each user's functions through as fast as possible, or "out of the way" if it's going to take a little time.  This is also why we tend to keep screen management in a different subsystem.  In our JavaFBP-based Brokerage application we multiplexed processes which were I/O- or CPU-intensive (fed by a Load Balancer process), and also used caching to reduce the amount of I/O.  See the cover of my book (2nd edition) for a schematic - it doesn't show multiplexing or caching, but they were key to improving performance.  I believe our screen management was managed by IBM's WebSphere, now InfoSphere.

Interestingly the new Facebook architecture, Flux, uses the same basic architecture, as they found that their previous MVC architecture didn't scale up adequately.  See Jing Chen's presentation in https://facebook.github.io/flux/ .

Of course, I don't know if you can do this easily with JavaScript, with its single stack - maybe someone could enlighten me why people are even trying to use JavaScript for this kind of work...?  IIUC web workers do support multiple cores, but communication between them doesn't seem to me to readily support FBP-style design.   Since JS is now #7 on the TIOBE popularity stats, maybe we should turn our attention to Python or C[++], both of which easily support this kind of thing...  See http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html .

PS I didn't know Swing was dead!  DrawFBP seems to work pretty well, and it's based on Swing!

PPS In the diagram I attached to my previous post, WS means "web sockets" - that was probably obvious, but just in case!  This of course means that the two halves of that diagram could be written in totally different languages!  In the case of the running example in https://github.com/jpaulm/javafbp-websockets - the lefthand subsystem is html + JS, and the righthand subsystem is Java.

Alfredo Sistema

unread,
Sep 13, 2015, 1:07:58 PM9/13/15
to flow-based-...@googlegroups.com
Documentation is too generous of a term for this.
Yields return control to the fbp engine, the engine returns control to the main window. The engine interleaves execution of processes.
As for the mouse movement case, imagine a "normal" js application, if a mouse over event is fired, and the application takes a while to respond, it will be laggy, it doesn't matter if you are using an fbp engine or not. The idea here is to use techniques like debouncing , which is used in normal js applications, to discard useless events before they even get processed.
There's nothing in this architecture that makes things inherently slower, a well made application will work fast enough.

Paul Morrison

unread,
Sep 13, 2015, 1:33:44 PM9/13/15
to flow-based-...@googlegroups.com
I love the term "debouncing"!  The JavaFBP "dropOldest" connection attribute might be useful here.

Alfredo Sistema

unread,
Sep 13, 2015, 1:37:21 PM9/13/15
to flow-based-...@googlegroups.com
http://davidwalsh.name/javascript-debounce-function
Here's a description of this technique. Mechanical keyboard circuits do this too to avoid misfires, as mechanical contacts bounce.

Kenneth Kan

unread,
Sep 13, 2015, 1:39:43 PM9/13/15
to Flow Based Programming, ged....@gmail.com, co...@ccil.org, ken...@gmail.com, bro...@gmail.com

On Sunday, September 13, 2015 at 12:51:25 PM UTC-4, Paul Morrison wrote:

I think you have to design the overall flow first - you're right that you can't afford to have one user's function block others, so you try to get each user's functions through as fast as possible, or "out of the way" if it's going to take a little time.  This is also why we tend to keep screen management in a different subsystem.  In our JavaFBP-based Brokerage application we multiplexed processes which were I/O- or CPU-intensive (fed by a Load Balancer process), and also used caching to reduce the amount of I/O.  See the cover of my book (2nd edition) for a schematic - it doesn't show multiplexing or caching, but they were key to improving performance.  I believe our screen management was managed by IBM's WebSphere, now InfoSphere.

Interestingly the new Facebook architecture, Flux, uses the same basic architecture, as they found that their previous MVC architecture didn't scale up adequately.  See Jing Chen's presentation in https://facebook.github.io/flux/ .

I concur with this. The only sane way when dealing with a user interface that demands instantaneous response time is to have two loops--one for just the GUI and another for logic, with the GUI loop having higher precedence in resource. That's how iOS works under the hood as well. The UI (i.e. main) thread has "super right" over computing resources. That's also how Conal Elliott's implementation of his Functional Reactive Programming world worked, which of course ultimately leads to Flux, so no surprise on the separation there.
 

Of course, I don't know if you can do this easily with JavaScript, with its single stack - maybe someone could enlighten me why people are even trying to use JavaScript for this kind of work...?  IIUC web workers do support multiple cores, but communication between them doesn't seem to me to readily support FBP-style design.   Since JS is now #7 on the TIOBE popularity stats, maybe we should turn our attention to Python or C[++], both of which easily support this kind of thing...  See http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html .
 

I think we need to have at least one web worker that handles the logic, given that JS is cooperative. Maybe someone could correct me but I think the JS community is simply trying to shoehorn things into JS even though they don't make sense. If anything, I think a compile-to-JS approach is better for FBP.

Paul Morrison

unread,
Sep 13, 2015, 2:01:26 PM9/13/15
to flow-based-...@googlegroups.com, bro...@gmail.com, Kenneth Kan
Did you guys ever look at JSFBP - https://github.com/jpaulm/jsfbp ?  I am becoming more and more convinced that this is the only way to support FBP using JS - and no complicated Promises, Futures, etc.   When you allow multiple stacks, everything becomes dead easy! 

Regards,

Paul

Kenneth Kan

unread,
Sep 13, 2015, 2:09:54 PM9/13/15
to Flow Based Programming, bro...@gmail.com, ken...@gmail.com


On Sunday, September 13, 2015 at 2:01:26 PM UTC-4, Paul Morrison wrote:
Did you guys ever look at JSFBP - https://github.com/jpaulm/jsfbp ?  I am becoming more and more convinced that this is the only way to support FBP using JS - and no complicated Promises, Futures, etc.   When you allow multiple stacks, everything becomes dead easy!


Yes I have. My opinion against using fibers is not at all technical. It's more because it's a very hard sell to the JS community at large. Plus, somehow it needs to be compiled into a version without fibers to work in the browser. That is, if we want an FBP to work in browsers; maybe making it work in Nodejs is good enough?

Humberto Madeira

unread,
Sep 13, 2015, 2:25:38 PM9/13/15
to Flow Based Programming, ged....@gmail.com, co...@ccil.org, ken...@gmail.com, bro...@gmail.com
Hi Paul,


On Sunday, 13 September 2015 12:51:25 UTC-4, Paul Morrison wrote:
Hi Ged,

I think you have to design the overall flow first - you're right that you can't afford to have one user's function block others, so you try to get each user's functions through as fast as possible, or "out of the way" if it's going to take a little time.  This is also why we tend to keep screen management in a different subsystem.  In our JavaFBP-based Brokerage application we multiplexed processes which were I/O- or CPU-intensive (fed by a Load Balancer process), and also used caching to reduce the amount of I/O.  See the cover of my book (2nd edition) for a schematic - it doesn't show multiplexing or caching, but they were key to improving performance.  I believe our screen management was managed by IBM's WebSphere, now InfoSphere.



If you are running JavaScript in the browser, the main thread _is_ your "screen management".  

The main thread works by processing events one after another from the thread's event queue.
Very much like Windows 3.0

You will want to avoid performing any long-running task in the display thread, so that it can be able to respond to input events in a responsive manner.

Up until the introduction of webworkers, the only way to deal with this in the browser was to break up the work into chunks and post them to the event queue one at a time.

Alternatively, if the work was big enough to be worthwhile, and you didn't mind some delay, you could just fire it over to the server via AJAX


Of course, I don't know if you can do this easily with JavaScript, with its single stack - maybe someone could enlighten me why people are even trying to use JavaScript for this kind of work...? 

I'm going to suggest that JavaScript is where all the cool kids are - where all the new ideas are happening.

Currently, it still has quite a few warts, but JavaScript is evolving more rapidly than any other non-proprietary language.
 
IIUC web workers do support multiple cores, but communication between them doesn't seem to me to readily support FBP-style design.  

I suspect the webworker comes with event queue. If so, it could directly be useful.  But someone will still have to come up with something to deal with selector and back pressure blocking.
 
Since JS is now #7 on the TIOBE popularity stats, maybe we should turn our attention to Python or C[++], both of which easily support this kind of thing...  See http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html .


Python, maybe.  Although, looking at the longer trends - it seems to have gone flat.  Trend-wise, C++ has been in a state of relatively sharp decline over the last decade - I would suggest C# instead.
 
PS I didn't know Swing was dead!  DrawFBP seems to work pretty well, and it's based on Swing!

Dead for over a decade.  It pretty much coincided with the rise of Javascript, which was seen as a way to get better UI performance without sacrificing the cross-platform capability.

Another, better performing alternative to Swing (for those who still want a Java UI) is SWT (the library underlying the Eclipse editor).
 
Regards,
--Bert 

Paul Morrison

unread,
Sep 13, 2015, 2:25:43 PM9/13/15
to flow-based-...@googlegroups.com
You're right - I forgot that aspect of it! 

Suppose you have a high-performing web sockets implementation, how do you split function between the client and the server?  Maybe we could come up with some criteria...? Because the less function you have on the client side, the less advantage there will be to using FBP for clients.

Ged Byrne

unread,
Sep 13, 2015, 2:26:59 PM9/13/15
to Flow Based Programming, Kenneth Kan, bro...@gmail.com, co...@ccil.org
And can you have both those loops running on a single thread and still stay sane?

John Cowan

unread,
Sep 13, 2015, 2:43:12 PM9/13/15
to Paul Morrison, Ged Byrne, flow-based-...@googlegroups.com, John Cowan, Kenneth Kan, bro...@gmail.com
Paul Morrison scripsit:

> PS I didn't know Swing was dead! DrawFBP seems to work pretty well, and
> it's based on Swing!

Swing is only dead in the sense that the kool kids don't like it any more
(or desktop apps of any sort, only web apps and native mobile apps).
That doesn't mean support for it in Java is going away.

--
John Cowan http://www.ccil.org/~cowan co...@ccil.org
BALIN FUNDINUL UZBAD KHAZADDUMU
BALIN SON OF FUNDIN LORD OF KHAZAD-DUM

Humberto Madeira

unread,
Sep 13, 2015, 3:00:21 PM9/13/15
to Flow Based Programming, ged....@gmail.com, co...@ccil.org, ken...@gmail.com, bro...@gmail.com


On Sunday, 13 September 2015 13:39:43 UTC-4, Kenneth Kan wrote:

 Maybe someone could correct me but I think the JS community is simply trying to shoehorn things into JS even though they don't make sense.

JS is now dominating cross-platform UI programming, which is dominant over native everywhere except mobile (and even there has a large presence).  

With the advent of Node.js, they have joined in the fray for cross-platform server development.

I suspect they have already overtaken Scala and Ruby and are working on overshadowing Python.

If they can help take out PHP, I'll be in the cheering section. 

As for Java, they can use it as a call-out.  This lets them leverage Java libraries while killing off Java frameworks (which are mostly pretty poor)
Embrace, extend, maybe eventually extinguish.

The only other possibly real player I see in the cross-platform server scene is C# (slowly moving over from windows only)
 
Regards,
--Bert


Kenneth Kan

unread,
Sep 13, 2015, 3:16:18 PM9/13/15
to Flow Based Programming, ken...@gmail.com, bro...@gmail.com, co...@ccil.org
Not sure. Maybe someone will come up with an ingenious solution. The industry has tried multiple cooperative loops being on a single thread (early versions of Windows, anyone?), but I think the consensus is to move away from that model.

Note that it'd still work, and you would be "sane" in the sense that programming in it wouldn't drive you crazy. It's just not sane in the sense that why not pick a better approach when one is present, at least for a GUI system if responsiveness is a requirement.

Kenneth Kan

unread,
Sep 13, 2015, 3:22:19 PM9/13/15
to Flow Based Programming, ged....@gmail.com, co...@ccil.org, ken...@gmail.com, bro...@gmail.com
Didn't we have this before? Java aimed to be the everything-language. I think John Cowan aptly said somewhere in this thread that Common Lisp was a big ball of mud. There's simply no one way of thinking that fits even the majority of the use cases. It is my prediction that JS will subside in 5-10 years, just like how Java kinda does right now, in the sense that it's not "cool" anymore. Only then will the industry stop looking to JS as the savior of Java's original vision, but use JS only for what it is good at.

Kenneth Kan

unread,
Sep 13, 2015, 3:36:19 PM9/13/15
to Flow Based Programming
If we go this route, we're really banking on a future where a consistently reliable high-performance internet exists. I doubt that's going to happen, but let's say it does, I think it'll be what Humberto kind of alluded to: the client being the screen management. It'd probably be just a component and everything else is running "in the cloud", in the form of subnets of course. Then again, isn't that the pipe-dream of the industry? ;)

Humberto Madeira

unread,
Sep 13, 2015, 4:43:55 PM9/13/15
to Flow Based Programming, jpau...@gmail.com, ged....@gmail.com, co...@ccil.org, ken...@gmail.com, bro...@gmail.com, co...@mercury.ccil.org
Hi John,


On Sunday, 13 September 2015 14:43:12 UTC-4, John Cowan wrote:
Paul Morrison scripsit:

> PS I didn't know Swing was dead!  DrawFBP seems to work pretty well, and
> it's based on Swing!

Swing is only dead in the sense that the kool kids don't like it any more
(or desktop apps of any sort, only web apps and native mobile apps).
That doesn't mean support for it in Java is going away.



More like kool dads haven't liked it for a long while.  Swing died out over a decade ago because it was sluggish, had problems with painting after invalidation, 
memory leakage (oh sorry, I forgot, Java doesn't leak -"loitering") issues, poor event handling and a stubborn development manager.

Java UI's generally sucked because Sun, as a company was never focused on the UI.  

Their UI Guidelines/Standards people complained to me that they were always being dissed by the Swing UI development team and were unsupported by upper management.

When I switched from Swing to Web - even with all the browser quirkiness of IE 5.5 at the time, the improvement was so dramatic that no one was inclined to switch back.

I'm not sure what I would have happened if SWT had been more popular (and as cross-platform as it is today) at the time.

The only reason Java didn't drop Swing was 
1) stubbornness in management, 
2) avoiding embarrassment, specially after killing off the far superior MS WFC
3) nothing to replace it with
4) once Oracle bought Sun, because Oracle DB tools were still based on Swing

Regards,
--Bert

Regards,
--Bert

Paul Morrison

unread,
Sep 13, 2015, 6:03:59 PM9/13/15
to John Cowan, Ged Byrne, flow-based-...@googlegroups.com, John Cowan, Kenneth Kan, bro...@gmail.com
Thanks, John, that's a relief!  I am beginning to wonder how grounded inn reality the kool kids are!  It's not that we oldsters know better - it's just that it's important not to lose decades of experience!

John Cowan

unread,
Sep 13, 2015, 6:18:00 PM9/13/15
to flow-based-...@googlegroups.com, Ged Byrne, John Cowan, Kenneth Kan, bro...@gmail.com
Paul Morrison scripsit:

> Thanks, John, that's a relief! I am beginning to wonder how grounded inn
> reality the kool kids are! It's not that we oldsters know better - it's
> just that it's important not to lose decades of experience!

I don't mean that Swing isn't pretty awful; it is, but lots of awful
things have staying power (OS/360 and its descendants being a fine
example). It's just that in the domain of desktop apps in Java, there's
really no alternative. SWT is a portable wrapper around native UI, and
as such is simpler and thinner, but lacks much of Swing's functionality.
Do I contradict myself?
Very well then, I contradict myself.
I am large, I contain multitudes.
--Walt Whitman, Leaves of Grass

John Cowan

unread,
Sep 13, 2015, 6:25:15 PM9/13/15
to Humberto Madeira, Flow Based Programming, jpau...@gmail.com, ged....@gmail.com, co...@ccil.org, ken...@gmail.com, bro...@gmail.com
Humberto Madeira scripsit:

> When I switched from Swing to Web - even with all the browser quirkiness of
> IE 5.5 at the time, the improvement was so dramatic that no one was
> inclined to switch back.

You're talking about desktop apps running as local web servers? Running
on centralized web servers is a whole different thing, with completelyl
different security and performance profiles. In any case, there are
still a lot of limitations in HTML5, particularly in the area of direct
manipulation UI, though things like drag and drop are now decently supported.

> 3) nothing to replace it with

Two tries (AWT and Swing) is probably all that Sun management could stand.
Note that Mono has never supported C# Windows Forms either.
But that, he realized, was a foolish thought; as no one knew better than
he that the Wall had no other side.
--Arthur C. Clarke, "The Wall of Darkness"

Alfredo Sistema

unread,
Sep 13, 2015, 6:52:30 PM9/13/15
to flow-based-...@googlegroups.com, Humberto Madeira, jpau...@gmail.com, ged....@gmail.com, co...@ccil.org, ken...@gmail.com, bro...@gmail.com
I think that two distinctions need to be made.
First: I am not advocating for server applications running on the browser, what I want to have is a common engine that can run on any ES5 compatible system, so that code can be reused and designs shared. We are making a tradeoff by using FBP in the first place, maybe we don't get the whole parallelism advantage but not all programs really require such a thing. If you need to do some expensive operation just do it serverside, the rest of the graph doesn't have to know the details.
Maybe you have a normal existing application but you want to add some FBP to it, add a graph, send some data to it, register a callback or let the graph do its thing. I'm not proposing "let's replace all javascript with an FBP engine", it's just not smart.
Making fully fledged desktop-like applications in javascript is generally awful, only a handful of them are usable, like gmail or google docs.
Second: I'm not worried about problems that do not exist, I just want to see a "real" FBP system that can run in as many computers as possible, and javascript provides that. The value proposition that I see in FBP is concurrency that's easy to reason about, and the skills developed in this kind of engine can be translated almost 1:1 to a fully threaded engine like JavaFBP or CppFBP, etc.
I want to have a "drop in" fbp system that's easy to use, that's all I expect, there's no universal solution.

Humberto Madeira

unread,
Sep 13, 2015, 8:08:39 PM9/13/15
to Flow Based Programming, kuna...@gmail.com, jpau...@gmail.com, ged....@gmail.com, co...@ccil.org, ken...@gmail.com, bro...@gmail.com, co...@mercury.ccil.org
Hi John,


On Sunday, 13 September 2015 18:25:15 UTC-4, John Cowan wrote:
Humberto Madeira scripsit:

> When I switched from Swing to Web - even with all the browser quirkiness of
> IE 5.5 at the time, the improvement was so dramatic that no one was
> inclined to switch back.

You're talking about desktop apps running as local web servers?  Running
on centralized web servers is a whole different thing, with completelyl
different security and performance profiles.
 
 Uh, not exactly.  The way I remember it - it was.

1) Java desktop app - local document file
2) Java desktop app - local DB as fake "document"
3) Java desktop app - network shared DB
4) Java desktop app - RMI to Java glue server - server DB
5) browser UI - HTTP to Java UI server - RMI to Java glue server - server DB
6) browser UI - HTTP to Java server - server DB

The jump from 4 to 5 had the most impact on UI performance.  
We were using a technique that later came to be called AJAX (originally Remote Scripting)
and relied on WASP (reflow capable) browsers - so performance was pretty good in comparison to Swing.

And yes - security profiles changed too.
But the jump to the browser also had a major positive impact on software client delivery to the user (as in it removed the requirement completely).
 
 In any case, there are
still a lot of limitations in HTML5, particularly in the area of direct
manipulation UI, though things like drag and drop are now decently supported.


Yes, agree. 

I have been a proponent of DM UI's since the Taligent days.  And am still active in doing so.

I have considered both SVG and Canvas as possible implementation pathways for a DM UI in the browser.

Unfortunately, SVG UI is primitive for interaction and needs a serious overhaul, but at least performs OK.
And also unfortunately, Canvas performance is still slow on some browsers, and has no way to embed widgets.

Even worse, attempting to create widgets from scratch in either canvas or SVG suffers from their poor capability for hit-testing.
(but at least they are talking about fixing it for Canvas)

However, you can still manage to deliver enterprise apps if you're willing to scale back on your UI bling-bling. 

My latest, most successful attempt uses the latest SVG with embedded HTML, but still has some frustrations.

Regards,
--Bert 

Paul Morrison

unread,
Sep 14, 2015, 12:00:14 PM9/14/15
to flow-based-...@googlegroups.com, Ged Byrne, John Cowan, Kenneth Kan, bro...@gmail.com
Thanks, Bert,

You and John seem to differ about Swing!  But maybe I should take a look at SWT...

Any ideas why C should be ahead of C++?  I know that C++ is sort of a hybrid, but I found that adding some OO stuff to my C implementations improved the clarity, without requiring massive changes to the original C code.   Plus, C seems to be dropping marginally, while C++ is going up - equally marginally!

Finally, this comment about what the kool kids are doing seems to be cropping up fairly often - so I have to ask: can they take advantage of the experience of us unkool oldies, or do they just keep on reinventing the wheel?!

Regards,

Paul

John Cowan

unread,
Sep 14, 2015, 12:55:16 PM9/14/15
to Paul Morrison, flow-based-...@googlegroups.com, Ged Byrne, John Cowan, Kenneth Kan, bro...@gmail.com
Paul Morrison scripsit:

> Any ideas why C should be ahead of C++? I know that C++ is sort of a
> hybrid, but I found that adding some OO stuff to my C implementations
> improved the clarity, without requiring massive changes to the original C
> code.

That's usually called "C++ as a better C", and is perfectly legitimate,
though it's not where C++ is going these days. Personally, I detest
C++, a language in which you cannot trust your code, you cannot trust
your compiler, you cannot trust your libraries, and above all you cannot
trust yourself. There are 50 ways to do everything in C++, of which 49
are wrong: the straightforward way is invariably one of the 49.

> Finally, this comment about what the kool kids are doing seems to be
> cropping up fairly often - so I have to ask: can they take advantage of the
> experience of us unkool oldies, or do they just keep on reinventing the
> wheel?!

Some do, some won't. As Tolkien says, children are not a class except in
their lack of experience.
All Gaul is divided into three parts: the part that cooks with lard and goose
fat, the part that cooks with olive oil, and the part that cooks with butter.
--David Chessler

Brad Cox

unread,
Sep 14, 2015, 2:42:45 PM9/14/15
to flow-based-...@googlegroups.com, Ged Byrne, John Cowan, Kenneth Kan, bro...@gmail.com
Personal opinion: the "cool kids" have moved on from the monolithic machines we grew up with to large (aka scalable) clusters of machines in pursuit of "big data" problems. The coolest thing I've seen in that space is Spark, based on a language (Scala) which runs in an ordinary Java JVM. It is an extended language that integrates both object-oriented and functional (aka FBP) concepts. The integration is so tight that Scala and Java can call each other almost seamlessly. See http://spark.apache.org/downloads.html

For the connection with recent discussion here re threading, see https://twitter.github.io/finagle/. This supports a style of programming that eschews traditional JVM threads by using Futurew. These apply the Javascript/Node.js threading model (everything shares a single thread), but use callbacks to get hyper-light-weight cooperative multitasking. This happens on each of the many JVMs that cooperate in big data processing.

Seems to be the coming thing. Check the links I provided; its big stuff and very hard to summarize in a few sentences.

Dr. Brad J. Cox Cell: 703-594-1883 Blog: http://bradjcox.blogspot.com

Ged Byrne

unread,
Sep 14, 2015, 3:21:58 PM9/14/15
to flow-based-...@googlegroups.com, bro...@gmail.com, co...@ccil.org, ken...@gmail.com
In an age where my phone has multiple cores why are we searching for ingenious ways to run in a single thread. The problems with this approach have been known for a long time (early versions of windows, anyone?) and is thoroughly discussed on C2 http://c2.com/cgi/wiki?TheGuiThreadIsTheMainThread

What we should be searching for is a way to make building UIs on multiple threads straightforward. While FBP is great for many situations I'm not convinced that it is right for the UI. Perfect for supporting the Ui, but not for implementing it.

If you have to start doing things like dropping stale events from a queue then you are making things more complicated, not simpler.

Regards,



Ged

--

Alfredo Sistema

unread,
Sep 14, 2015, 3:49:37 PM9/14/15
to flow-based-...@googlegroups.com, bro...@gmail.com, co...@ccil.org, ken...@gmail.com
Ged, you brought up the imaginary problem of having an unresponsive user experience because of FBP, which I still fail to understand. What kind of use case do you imagine? "It will be slow" is not an argument or a problem to solve, it doesn't matter how many threads you have available, or how easy they are to use, if an operation takes X time, you can't hide that. Right now we have web workers available for intensive tasks, so even if you want to do that kind of thing in the browser, you can.

Ged Byrne

unread,
Sep 14, 2015, 5:04:37 PM9/14/15
to flow-based-...@googlegroups.com
Alfredo,

If my problem is imaginary then you have nothing to worry about.  You can safely ignore my concerns.

It is based on a principle, not a use case.  Consider Paul's description of the benefit of FBP:

When this happens, the process is suspended and some other ready process gets control. Eventually, the suspended process can proceed (because the blocking condition has been relieved) and will get control when time becomes available. Dijkstra called such processes "sequential processes", and explains that the trick is that they do not know that they have been suspended. Their logic is unchanged - they are just "stretched" in time.
So we have two time frames:  the user's and the sequential process'.  The user's is constant in real time.  The sequential process is 'stretched' in time whenever it has been blocked, a state the process is unaware of.

If the sequential process is responsible for responding to the user's events then how can it do so while in a blocked state?

The user's time and the process' time are not synchronized.   The process will not respond within the user's time frame.

For the use case I provided the mouse over.  Here is some working code: http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_onmouseover

There is a smiley face.  When my mouse is over the face then it is big.  When my mouse is not over the face then it is small.

This is achieved with two event handlers

<script>
function bigImg(x) {

    x.style.height = "64px";
    x.style.width = "64px";
}

function normalImg(x) {
    x.style.height = "32px";
    x.style.width = "32px";
}
</script>

In the JS event model bigImg and normalImg are invoked as soon as my mouse enters and exits the image thanks to the handlers:

<img onmouseover="bigImg(this)" onmouseout="normalImg(this)" border="0" src="smiley.gif" alt="Smiley" width="32" height="32">

If the event handler is not invoked immediately the effect will not work.  Having the event occur 2 seconds after the mouse has passed simply will not do.

If the events are being handled by a flow graph the mouse over event will be placed in a queue and processed by the bigImg processor when it is ready.  That could be 2 seconds later.  That simply will not do.

You can emulate the effect by adding a loop to the event handler:

function* slowFunction() {
    for (i=0;i<1000000;i++) {
      document.title = ""+i;
    }
}

function bigImg(x) {
    slowFunction();
    x.style.height = "64px";
    x.style.width = "64px";
}

Update the javascript in the 'try it now' and click see results.  Now pass your mouse over the smiley.  A few seconds later it will go big.  If you're mouse is no longer over the image then it will immediately revert back to small.

While the main thread is busy looping the UI remains unresponsive.  While your main thread is busy managing all the queues  you will have the same lag.

There's nothing special about the yield that will allow control to return to process the main event loop, as can be seen by using a generator in the above example:

function* generator() {
  var i = 0;
  while (i <= 1000000) {
    yield i++;
  }
}

function slowFunction() {
    var g = generator();
    while(!(n = g.next()).done) {
      document.title = ""+n.value;
    }
}

In Chrome the generator causes the same delay as the for loop. Other browsers may behave differently.

This problem is easily solved by introducing two separate threads - one that is synchronous with the user's time frame and another that is asynchronous for the flow graph.

Regards, 


Ged




Brad Cox

unread,
Sep 14, 2015, 5:14:27 PM9/14/15
to flow-based-...@googlegroups.com
Ged: "When this happens, the process is suspended and some other ready process gets control" is based on long habit. Please see the link I sent earlier (Twitter's finagle) for an alternative that isn't based on "processes" or "threads", and is roughly the same as what JavaScript/Node.js uses. A single unthreaded VM and cooperative hyper-lightweight multitasking. Based on a conventional Java JVM intentionally uses only a single java thread that is shared by many "processes".

Dr. Brad J. Cox Cell: 703-594-1883 Blog: http://bradjcox.blogspot.com




Ged Byrne

unread,
Sep 14, 2015, 5:32:34 PM9/14/15
to flow-based-...@googlegroups.com
Hi Brad,

This is the approach I'm arguing for in the UI. It's the introduction of FBP in the UI's main thread that I'm objecting too.

FBP deliberately decouples the processing of an IP from its creation. This simplifies the processing.

For a responsive Ui the delay between event creation and event processing must be kept to a minimum.

Regards,


Ged.
It is loading more messages.
0 new messages