For all the vitriol and dogma surrounding these two approaches to programming, there are only three core I consider genuinely important:
- Should one allow functions to modify state information, or merely return a value?
- Should one allow functions to access information not directly passed to them?
- Should functions be explicitly tied to classes, or can they stand alone as occupants in a system?
Should one allow functions to modify state information, or merely return a value?
At the heart of this question is the concept of consistency. Should functions be permitted side effects? Arguably, this is the source of most instability in programs: the program enters an unexpected state as a result of functional side-effects and can no longer operate properly.
From a performance perspective, there's a lot of good reason to permit inter-function state modifications: it prevents the creation of an abundance of temporary values that need to be held in memory. From a mathematical perspective, it's just allowing noise into the system. Ultimately, these side-effects are a relic of modern hardware: The Von Neumann bottleneck makes frequent creation of temporary variables incredibly expensive. This is a by-product of the fact the modern architectures separate programs from data. This will change as our approaches to computing change: a well-designed quantum system will require no side-effects, since these intermediary calculations can be processed synchronously and in a highly-optimized fashion (multiple calculations on the same machinery at the same time, something currently impossible); a well-designed biocomputational system will contain densely-linked side effects, such that every function affects all others.
Should one allow functions to access information not directly passed to them?
This is largely a question of syntax, really. Effectively, every function in a standard class has the explicitly-declared parameters sent to it, as well as every member variable. This can reduce verbosity (no need to explicitly pass in the majority of data being used) but can also obfuscate the data being functionally used.
Sophisticated IDEs will eliminate this problem--they can present all the data a function is actually using concisely, and use that information in compilation.
Should functions be explicitly tied to classes, or can they stand alone as occupants in a system?
Strategy pattern. It works. If you don't accept this, you probably work in a terminal and refuse to accept that better development tools exist.
Both of these approaches are Turing-complete. Both can organize in most any way a developer wishes, as long as they can think in the right abstractions. Object-oriented programming is a highly-pragmatic approach to modern programming that trades mathematical purity for organizational clarity.
These paradigms evolve with hardware, however. We will see a return to something more similar to functional programming as our hardware begins to evolve, but that does not necessitate the abolition of useful organizational patterns--it simply requires densely reflective languages, powerful optimizing compilers, and hardware that isn't burdened by the replication of data.
We won't always be using Von Neumann computers. Even Von Neumann knew this.
No comments:
Post a Comment