State is not the same as context, because (nonpure) functions also perform state changes, and concurrent execution can cause shared state to change at any time during the execution of a function, including for objects the function created itself (weren’t existing context).
Bugs arise from incorrect assumptions. These can be assumptions about state or context, but really it can be any kind of assumption. Assumptions are a kind of dependency. Minimizing dependencies also helps to minimize assumptions. Similarly, statically checked type systems help by having the compiler double-check at least some of the developer’s assumptions. The more powerful the type system, the more assumptions can be expressed and hence checked.
OOP tries to minimize the assumptions and dependencies between code by encapsulation/data hiding and interface contracts. FP tries to minimize them by having the result of a function only depend on its parameters. Declarative programming tries to minimize them by having the program only describe relationships between inputs and outputs.
How to minimize the assumptions a given piece of code has to make, and minimizing its dependencies, are the bedrock of all software engineering advice, IMO.
> How to minimize the assumptions a given piece of code has to make, and minimizing its dependencies, are the bedrock of all software engineering advice
Would this be a case of managing the complexity of the developer's systems model?
Abstractions in effect clamp the complexity presented to the programmer & may include assumptions about the given piece of code. Question being are the cognitive assumptions presented to the programmer able to result in unintended consequences, how often, & how severe in systemic terms?
Bugs arise from incorrect assumptions. These can be assumptions about state or context, but really it can be any kind of assumption. Assumptions are a kind of dependency. Minimizing dependencies also helps to minimize assumptions. Similarly, statically checked type systems help by having the compiler double-check at least some of the developer’s assumptions. The more powerful the type system, the more assumptions can be expressed and hence checked.
OOP tries to minimize the assumptions and dependencies between code by encapsulation/data hiding and interface contracts. FP tries to minimize them by having the result of a function only depend on its parameters. Declarative programming tries to minimize them by having the program only describe relationships between inputs and outputs.
How to minimize the assumptions a given piece of code has to make, and minimizing its dependencies, are the bedrock of all software engineering advice, IMO.