Absolutely. More people need to understand the binding hierarchy:
- "early binding": function A calls function B. A specific implementation is selected at compile+link time.
- "late binding": function A calls function B. The available implementations are linked in at build time, but the specific implementation is selected at runtime.
From this point on, code can select implementations that did not even exist at the time function A was written:
- early binding + dynamic linking: a specific function name is selected at compile+link time, and the runtime linker picks an implementation in a fairly deterministic manner
- late binding + dynamic linking: an implementation is selected at runtime in an extremely flexible way, but still within the same process
- (D)COM/CORBA: an implementation of an object is found .. somewhere. This may be in a different thread, process, or system. The system provides transparent marshalling.
- microservices: a function call involves marshalling an HTTP request to a piece of software potentially written by a different team and hosted in a datacenter somewhere on a different software lifecycle.
At each stage, your ability to predict and control what happens at the time of making a function call goes down. Beyond in-process functions, your ability to get proper backtraces and breakpoint code is impaired.