What makes data flow analysis higher level than control flow analysis? I feel understanding why data flow is higher level than control flow is key to writing good code (and convincing others during code reviews). I find this repeatedly when arguing why my functional style programming with immutability is superior to their mutable state code which is more common and expected.

But I don't understand why one is higher level than the other. The closest I can come up with, informally, is that ultimately end users don't care about what movement of control occurred. But they DO care what movement of data took place.

Other examples


applications which just do processing last only a couple of years, whereas files which store data can last decades)
a CPU just transforms volatile data, whereas disks store data persistently


In other words, control flow is a means of achieving data flow.

Is there a more rigorous way to explain this?


(source: slideplayer.com)
Look at Wikipedia article "Control Flow". It contains typical flow chart. Arcs are the ways where control token moves from one node to another.

Now imagine you want to employ parallelism and launch several control tokens. Immediately a problem arise: how to isolate pieces of data from simultaneous modification by different control tokens. To tackle with this problem, we divide our data in parts - one parts belong to dedicated control token, and others are  for exchanging information between control tokens. The result is a dataflow diagram (or chart). That is, to manage data in parallel environment, we have to split data into pieces and explicitly manipulate them. Data flow is no more than parallel control flow.

Functional programming is another story. While there exist both control flow (von Neumann) and data flow processors, there is no functional processor. Functional programs can be compiled both to data and control flow processors. But since ordinary imperative programs cannot be directly compiled to dataflow processors (they first have to be converted to dataflow programs, which is hard), and converting functional programs to dataflow representation is easy, we can consider functional programming as a variant of dataflow programming.

And finally, consider distributed computing. Since it involves multiple computers with no shared memory, it is best described as dataflow computing and not as imperative computing. What happens inside computer nodes, is it functional programming or imperative, does not matter. But the way how data are exchanged matters. And using functional data structures to exchange data between nodes is very appropriate.