When talking about reducing complexity in a software system, we often talk about making it "modular" by breaking it up into multiple modules that are all linked together to form the overall system. But in similar contexts, we talk about "compositionality" being a nice property. I suspect there's a more formal definition for that, but I roughly understand it as being able compose different pieces into a whole (often with the same "shape" as the underlying pieces, like GUI widgets).
So is there a meaningful difference between the terms "modular" and "compositional"?
I'm particularly interested when it comes to describing reasoning methods and how programmers reason about programs. For example, say I have these two methods with the following contracts:
abs(double x): returns the absolute value of x (as a double)
sqrt(double x): returns an approximation of the square root of x if x is non-negative, otherwise throws an exception
Then consider the expression
sqrt(abs(y)). With those two contracts, I know that for all possible (
ys, that expression will never throw an exception, because
abs(y) is always non-negative. As a programmer, I don't need to read the code of
sqrt to make that inference: I can figure it out purely from the given properties and the way the functions are composed. So is that modular reasoning, compositional reasoning, or both? Is there a difference?