This article was originally published on blog.vaibhavgharge.com
A lot of people complain that OOP has done very poorly. Well sure but a lot of things have been done poorly but our enemy is not Object Oriented Programming.
The real conversation is not the difference between object-oriented and functional, the difference is Imperative versus Declarative style of programming.
Well as a mainstream programmer, we've been programming an imperative style for a very long time and of course, the world is moving towards more of a declarative style of programming.
So the real question is to program imperatively or should we program declaratively and which one should we choose?
Let's explore,
- How they are different.
- Code example.
- Parting Thoughts.
What is the difference though between these two paradigms?
Imperative style of programming is where you tell what to do but you also have to spend the time and effort telling how to do it. So not just the what but also the how. First do this and next do that.
Let's look at an example
So here I have a little program. I have a list of names but I want to know if our good friend Nemo is on the list.
So how do I find if Nemo is on this list?
- The very first step I'm gonna do, is I'm gonna define a boolean found is equal to false and of course if we found what do I want to output Nemo found.
- Otherwise, what I'm gonna say Nemo not found.
List<String> names = List.of("Gill", "Dorry", "Bruce", "Nemo", "Darla");
boolean found = false;
for (String name : names) {
if (name.equals("Nemo")) {
found = true;
break;
}
}
if (found) {
System.out.println("Nemo Found. :-)");
} else {
System.out.println("Nemo Not Found. :-(");
}
When I run the code it says "Nemo Found. :-)".
This is an example of an imperative style of code as we are not only explicit about what to do but also how to do it.
Now let's take a look at code, that is an example of a declarative style of programming.
Declarative style is where we tell what to do and not how to do it. It is an abstraction on top of imperative systems that opens the whole new world of possibilities to program in asynchronous and event-driven fashion without having to think about how to it works.
List<String> names = List.of("Gill", "Dorry", "Bruce", "Nemo", "Darla");
if (names.contains("Nemo")) {
System.out.println("Nemo Found. :-)");
} else {
System.out.println("Nemo Not Found. :-(");
}
Parting Thoughts
The fact that everything ends up being imperative at some point as it hits the operating system and hardware is important to remember and understand because it helps us with the mental model of what declarative programming is addressing and how it ultimately executes - there is no magic.
Imperative Style is easy to write but it's hard to read.
On the other hand, Declarative Style is easy to read but it's hard to write (to a certain extent due to unfamiliarity).
Should programs be imperative or should they be functional? and I'm gonna say the answer to me is that it's neither one of them and there are times when the code has to be imperative and there are times when the code has to be functional and I think it is very naive to say it's got to be entirely one and not the other.
Hope you find this post useful. Please share your thoughts in the comment section.
Iβd be happy to talk! If you liked this post, please share, comment.π Cheers
Top comments (19)
Declarative is something to strive for, but it is a matter or degree. Even "Declarative" languages can get very imperative in practice if the model is ill-fitted to the problem. You start applying multiple transformations in order to get the desired result. So the main difference between declarative and imperative is how your abstraction fits your problem.
Yes that!: "how well your abstraction fits the problem"
When the fit is bad the declarations will break down if they even work at all.
Fitting abstractions is a fun to pic and a worthwhile one too.
There are several categorizations of programming languages... I outlined it once since I had never seen it explained.
Based on what I read online it goes like this.
(Some languages mix aspects of 2 or more of these groupings.)
1: Imperative Programming
1.A: Procedural Programming
1.A.1: Structured
1.A.2: Object-Oriented (OOP)
1.A.3: Modular
1.A.4: Page Description
2: Declarative Programming
2.A: Query/Database Programming
2.B: Functional Programming
There is no IDEAL language.
You use what your employer, your instructor, or your equipment requires.
If you don't have an employer or an instructor, and are wealthy enough to be idealistic... consider that you are in the minority, and the majority of us have to be pragmatic.
If you don't have an employer or an instructor and are not wealthy... be pragmatic and learn what you can that will get you what you want.
Languages that are Procedural and/or Structured
Fortran
ALGOL
Cobol
BASIC
Pascal
C
Visual Basic 6 and older
Visual FoxPro
Progress 4GL
Languages that are Object-Oriented (OOP)
C++
Java
C#
Python
PHP
Javascript
Ruby
Perl
ObjectPascal
Objective-C
Dart
Swift
Scala
Languages that are Functional
Common Lisp
Clojure
Erlang
Haskell
F#
(And SOME non-Functional languages have Functional characteristics)
Languages for Querying
SQL
Dbase / FoxPro
Progress
Page Description Languages
PostScript
PDF
Many forget that the original OO language Smalltalk (Simula was half backed) borrowed heavily from functional programming. In fact, one could argue it was a functional language.
Smalltalk, even more so that Lisp, had no IF statement and no Loop statements. Everything was implemented using blocks (today known as Lambdas). For example:
In that sense smalltalk was "declarative style" as you call it. (Though not truly declarative like Haskell or SQL)
I think another thing that causes the functional camp to worry about OO is the question of mutability and side effects. One can mitigate that in OO programs by using immutable objects when possible.
However, the attitude among some that are now learning functional programming that they can set aside principles such as code duplication, modularization, and encapsulation just betrays a lack of understanding. Some functional advocates have often pointed out that OO can be implemented in functional and as such should be seen as a subset of the functional style. (Of course, I think they mean that in the sense of having objects and transforming rather than mutating since mutation is frowned upon by purists)
I think the main benefit of functional that we see day to day is that instead of generic for / while loops we have higher level loops like mapcar, reduce, filter, etc.. That makes for a more advanced structures in the program that can help readability and composability.
But the entire design still needs some big architectural principles to hold things together. And that would involve defining and encapsulating data structures and then defining orderly transformations.
On the discussion of not being imperative...
Do you not think one of the biggest strengths of OPP is that it should, on the surface, always be declarative.
Instead of have loops in your code you want to have a NemoFinder class (or a FishFinder depending on your needs) that will look for and give you Nemo back. You don't need to care about how it works until the point you need to implement it, with a loop or with a LINQ style library (which is still a loop written by someone).
If you practice OOP with a separation if concerns do you not find it ends up looking very declarative.
Yeah, I totally agree with that. There has to be separation of concerns along with the reusability and maintainability of the code.
That is why we have so many design patterns for OOP.
Paradigms in programming have been developed and adapted for different use cases so to indicate that object oriented performed poorly is misconstrued. Programming paradigms are more so not specific in design but multiparadigm for real time applications.
Am I wrong to scratch my head a little, imperative as described above is level of abstraction, as languages develop they seem to become more and more abstracted in on to themselves. I can't see the link between this or if I should use base classes or composition or both.
Hey Adam,
As I mentioned in the parting thought section, The fact that everything ends up being imperative at some point is the logic and more accurate way of thinking about programs.
So declarative in some manner acts as an abstraction over the imperative paradigm. As we all know loops, conditionals are the fundamentals of OOP languages. I hope that clarifies.
I'm not sure what you described is declarative. In fact, you explicitly told how to do it. Not in as much detail as the first example, but there us definitely still an explicit sequence of events.
Declarative languages don't just hide a procedure behind a method name. Take SQL for example. You describe what rows you want from the database, and SQL goes about retrieving them. It could be just reading through the whole table and picking out the selected rows, using an index, or something entirely different, and which method it chooses has less to do with the way the code was written than it has with the structure of the database and the characteristics of the data. Not arguing against proper abstraction, but just saying that abstracting out details doesn't make a technique declarative.
You swap from using the word declarative to the word functional. You seem confused.
Especially null and error handling.
I personally prefer the declarative form of coding, I just never knew there was a name for it.