I. The Why
So , what’s the difference between functional, procedural, object oriented, logic, concurrent [etc] programming languages? Ain’t a program after all, a set of 0s and 1s?
In the end, a software will need to be compiled and executed by the machine, thus the output will be a computer-friendly code. Why do we have so many paradigms?
The answer is,
Data. A software will have a set inputs and will need do either change the
state of something, or give back a result, or both!
These programming paradigms makes it easy to manipulate data in some particular way. For instance, Logic programming languages makes it very easy to write a software that has as input a bunch of beliefs and need to validate a particular hypothesis.
The same thing can be done in procedural programming, but modeling the program would take a lot more effort, time and probably wont be optimized as much.
II. The Problems
1. Data Modeling
A lot of programming languages call themselves
general purpose instead of
domain specific (aka DSL) languages. And by general purpose we generally mean they allow the user to
model any kind of data. The word
model here is very important. When we model the data, we need a meta-model describing how to represent that data. What does our model allow us to present and what are its limits. The meta-model should allow the data-model to map easily to the
physical schema; that is the hardware model, while allowing the user to represent his data in a logical schema that is human-readable.
Another issue is performance which is usually related to how well does the data-model maps to the
physical schema, and how optimized the language’s compiler/interpreter is.
Tracking down issues and fixing bugs is very related to the language it self. Some languages offers some tools to avoid side effects and reinforce good and safe patterns. This depends on users, some may find it a safe and reliable approach to write maintainable software, others may find it more restrictive.
This is very much related to maintenance. In order to write safely-concurrent code, the language may offer specific syntax to reinforce thread safety such as pure functions, stateless object, synchronized code blocks, etc.
III. Solutions That Created More Problems
1. Procedural Programming
Assembly, which is one of the very first languages is by nature procedural. You write instructions that changes the state of registers, memory blocks, flags, etc. You create functions and then call them upon need. So it is very natural that higher level languages that came after assembly would be procedural as well, such as C and Pascal. Procedural languages allows the program to be divided into a set of modules, were each module solves a particular issue. This offers [..]
2. Object Oriented Programming
The holy book of OOP states:
– Inheritance: An object shall inherit other objects
– Encapsulation: An object shall not access other object’s data, unless via its API.
– Polymorphism: An object shall have different behaviors depending how it is treated (its data type)
Object Oriented Programming required programmers to think differently about data. It actually does not only handles data, but also its methods.
This has created a lot of issues and concerns, here are some thoughts:
– Data should be separated from functions. They do not belong to the same unit (an object, or a class)
– encapsulation hides the object state, thus enforcing
mutability and side effects.
– inheritance is a very bad way of reusing code, and in fact, it does not even enforce code reuse.
– Some say that arbitrary objects communication is very poor, objects should be created as a tree and exchange messages only through parent-child relation-ships.
3. Functional Programming
It took functional programming a while to be accepted within software developers. While object oriented languages can be understood as procedural programming or as an
imperative language in general, functional programming is a subcategory of
declarative programming which comes from different roots.
Functional programming takes a different approach to model both the
data and the
program. Instead of describing the program’s control flow, they specify what the program must accomplish in terms of functions.
Functional programming make it easier to write concurrent application as usually functional languages reinforce immutability and discourage states and side effects. In the very nature of computers, memory/registers states are being changed a thousand times per second. So functional programming may seem a bit weird if not even useless to some programmers.
IV. The truth
In industry, the dominant paradigms are object oriented and procedural. Usually the languages used combine both of these paradigms such as C++ or Python.
These language does not fully implemented Object Oriented and Procedural principles. Instead they implement them at some level to offer the programmer more flexibility on what he needs to write and at the same time the language appear as non ambiguous. For instance, C++ cannot be fully object oriented because it needs to maintain some level of
On the other hand, functional programming languages are rising and many think it is the future of programming.
The truth is, one can’t live without the other. We see a lot of object oriented language attempt to support parts of functional aspects such as
lambda expressions which had been recently adopted in both Java and C++. Alternatively some functional languages adopted now support object oriented programming such as OCaml.
V. Personal Thoughts
Warning: Personal thoughts ahead.
I have coded in various programming languages, most of which are object oriented and procedural. I assume you that according to my professional and personal experiences, Object Oriented does not reinforce CODE REUSE. It’s a myth. Just because you extend a class and implement some of its methods does not mean you have reused some code.
You have to live long enough to see yourself debugging that class, seeing its internal behaviors because at some pointing it has caused you some issues or you have miss-used it and you need to debug it or understand its internals.
In my own opinion, C with templates could have offered better code reuse than most object oriented languages. What reinforces code reuse is mostly generic programming, which mostly exists in OOP through
templates. I believe when a programmer creates a
class, it IS better to leave that nasty code alone.
Don’t worry about implementations they said. It would be fun they said.
Interfaces reinforce code reuse, they more encouraged than classes. Even in Java, it is preferable to implement interfaces rather than extend classes http://www.javaworld.com/article/2073649/core-java/why-extends-is-evil.html.
Something else, encapsulation allows objects to be an independent entity, that’s true. That’s in fact a powerful mechanism and I love it. But hiding the state of an object is pure evil. Unless you enjoy writing non reusable parallel unfriendly code, stay away from state.
I hope that I convinced you that
No language solves all the issues. Pick the right tool for your job.
Think first, code later. But do think about the language first.
If two languages supports the same features (Say Java and Python), you may pick one according to other need (performance, portability)
Learn more than one language per paradigm. Never fear adventure when it comes to programming.