The meaning of upstream / downstream dependencies

Hi, I can see developers often use terms “upstream” and “downstream” to point to the dependencies or dependents of something, either in the context of building software from modules / subprojects or using source control systems that allow cloning / forking. However I’ve encountered developers who apply contradictory meanings to these terms and it made me quite confused. So I ask here, which interpretations of “upstream” and “downstream” do you find correct. As a non-native speaker I’d like to be understood correctly and avoid messing up these terms.

Consider there are three projects: A, B and C (e.g. in SBT). Project C depends on code in B, and project B depends on code in project A. You have to first build project A, then B, then finally C.

Interpretation 1:
Project A is upstream from B, and project C is downstream from B. This is because information flows in the direction A -> B -> C, and such is also the order of building. Therefore, by manufacturing analogy, A can be considered raw materials, B a half-product and C the final product. In manufacturing raw materials / suppliers are upstream, final product / consumers are always downstream. Also any change in B affects only B and C, but not A, so changes are propagated down with the stream, so C must be called a downstream dependent of B.

Interpretation 2:
Project A is downstream from B and project C is upstream from B. This is because we can draw the dependency graph as A <- B <- C. Therefore the “dependency stream” flows from C to A, so A must be downstream and C must be upstream.

Obviously both can’t be correct, so which one is correct?
Or is it totally messed up and one should just avoid using these terms, because noone really grasps what they mean?

Thank you!

interpretation 1. there is no ambiguity IMO. pretty sure I have literally never encountered interpretation 2

1 Like

Oh, so this is not controversial? Anybody here disagrees with interpretation 1?

I agree with Seth – I don’t believe I’ve ever heard of interpretation 2. While I guess I can see how you arrived at it, this is the first time I can recall hearing that interpretation put forth – interpretation 1 is pretty universal, across a number of languages…

I’ve only seen #2 from a system perspective. Two or more subsystems that have intertwined functions. Once system for ACLs and another for secure storage as an example. In that case both systems need independent bootstrap code before they sync.

Maven is a hub as well as a spoke. The system is modular enough that neither side needs a bootstrap.

If it is at a project level, it likely is a problem with engineering. Either multiple projects need to be merged, or a fourth project “D” needs to be created with “A” and “C” depending on it.

Not sure if I understand. Can you give an example? And what is upstream and downstream in that case?

If two or more systems are intervined then the flow is bidirectional and speaking of upstream or downstream makes no sense.

I think that’s exactly what we’re discussing.

If a->b->c “a” is upstream (as I understood the original post), use case #1. I’m presuming each is a library. The pattern a<-b<-c is the same, just written differently.

Case #2, I took as a->b->c<-a. A cyclical directed graph. The only places I’ve worked with are multiple systems, or things like a compiler. In both cases, a bootstrap is required. Some things like maven, which is a maven project is a looser case, doesn’t really require a bootstrap.*

The bad case is a single development project. In that case, the system architect isn’t doing their job. I’ve never seen a real example of case #2 other than projects that are DOA.

  • Cyclic directed graphs are common enough in category and type theory. There, the functors & mutators are considered separate from the category. So category U doesn’t depend on V, even though the functors/mutators establish the cyclical graph. So that’s a separate case. The edges of the graph depend on vertexes, but the vertexes don’t depend on each other nor the edges. So I don’t think that is use case #2, even different enough that #1 isn’t quite right either.

So far I have also never seen interpretation #2 until I stumbled upon the following fragment of the documentation:

https://scalacenter.github.io/bloop/docs/usage#compile-downstream-projects

Compile downstream projects
The compilation of a project always requires the compilation of all downstream projects (its dependencies).

Compile upstream projects
The --cascade flag allows you to change the public signature of a project (say, foo ) and have bloop compile all the transitive projects depending on foo to detect compilation errors.

Usage of words upstream/downstream look incorrect and reversed to me or did I not understand something?

2 Likes

Agree. I’d suggest opening a ticket in the bloop repo on it.

Already did.

See the following conversation: https://github.com/scalacenter/bloop/issues/999

Looks like pointing out mistakes and offering help / debating solutions is not welcome in this otherwise amazing project. :frowning:

I can see why the original wording of the ticket got the reaction it did, although I think people should give more allowance for non-native speakers.

That said the fact that it was rejected and locked seems absurd to me. The docs are confusing and fixing them is a clear improvement.

3 Likes

Honestly, I didn’t know that using the word “wrong” twice is an offense.

It’s not about counting how many times you used the word. It’s that

Wrong.

as its own sentence, especially the first in a paragraph, come across like someone speaking in a condescending, gruff way. People read text by imagining someone speaking the same words with cadence matching the punctuation, in the first way that comes to mind. And that is the tone that I hear when reading the original version – even though I know that the author did not intend it to sound that way. (I myself have often written things that sounded differently than I intended.)

Maybe it’s even more subjective than I thought, and many native English speakers would never interpret it that way.

In any case my main point is that we should all be less quick to jump to conclusions: if someone posts something that sounds rude, read it again carefully to see whether it may have not been intended that way. And if you posted something that someone wrongly interpreted as rude, consider whether there’s a reasonable explanation. (Of course, sometimes someone is intentionally being rude, and sometimes someone is overly edgy and makes a big deal over nothing.)

In any case it doesn’t explain the ticket being closed and locked.

2 Likes

Yeah, I think I have learnt something from this and I’ll be more careful with language usage. I got emotionally attached to this project very much :wink:

But now we need to move on - do you have any ideas what can we do now to improve the docs ?It seems we all agree it should be fixed.

Without changing the meaning of upstream/downstream in the docs, or dependent/dependency, I don’t think there really is anything to. And that’s pretty much ruled out on the ticket:

Nope, I’m not removing these words from the docs. Let’s move on.

That sounds pretty final. We can agree all we want, but if the maintainer of some project disagrees, well, it’s their project.