I just watched an interesting talk about using data values as natural program boundaries. Some valuable ideas, but the main thing that it made me think about was unrelated to the talk itself. I learned about this talk when I was at the recent QCon conference; it was recommended by a speaker who was enraptured and completely convinced that functional programming is The Correct Way to Do It (CWDI pronounced “cow-dee”).
Programming style advocacy — whether for/against OO, imperative, declarative, functional, or whatever — has a problem. And I’m not referring (at the moment) to the language debates that they usually get mired in. The problem is that no single programming style is The Correct Way to Do It.
The proof of this is trivial:
- “Correct” must be evaluated first in terms of the functionality needed.
- All languages are Turing complete.
- All solutions are functionally equivalent.
- All solutions are “correct”.
That was stated in a bit of a light-hearted way, but don’t just gloss over it. If you disagree with the proof, it probably has to do with the way the word “correct” has been constrained. When we are talking about programming styles the word “correct” typically has a bunch of other implications, including maintainability, testability, aesthetics, expressiveness, and so on.
And this is all fine when we are having theoretical conversations and discussions. But it becomes harmful when we enter the realm of engineering non-trivial systems. (By non-trivial here I’m talking about systems whose complexity easily surpasses the capabilities of a single engineer — no “toy” problems, please!) Engineering decisions are always about trade-offs, and programming styles are no exception.
What is required is to match the programming style to what best suits the problem being solved. For a machine-control system functional programming is often considered the best solution; for complex data-modeling environments OO may be more well-suited. Real-world complex systems are often composed of multiple subsystems, each of whose solution may require different styles of programming. Add into the constraints of the problem being solved the constraints of the environment: does the team know how to use a particular style? do we need to then pick a new language? does the benefit outweigh the costs?
But it is just lazy thinking to say that OO or functional programming is always the right solution. (I don’t care about your generic arguments that “mutability == badness” either; just because immutable values are easier to test isn’t enough to trump all other factors.) (And I don’t care about your theoretical strong-typing either; sometimes type integrity enforced at run-time is just what is needed.)
Not everything is a web-page backed by MongoDB; not everything is a bespoke enterprise desktop backed by SQL; not everything is a machine control application. Tune your solutions to the problem!
But I guess the first, most important thing is to at least learn about and understand all the options available. You may not have the opportunity during your career to actually do serious projects with them, but at least be aware of the costs and benefits of all the major programming styles and don’t confuse those issues with programming language advocacy.
Stop the madness…