
OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.
Alan Kay, the father of OOP
Poem: Objects everywhere
My adapter needs a service To adapt to any purpose, And that service kinda functions As a helper at the junction Between builders; the conception Is to model raised exceptions, Causing tension, also leaving me in dread โ My mind's crowded with code objects in my head. ๐ตโ๐ซ ๐
Object-oriented programming (OOP) is talked about so much in the software development space. It's a tried-and-true method of creating applications, and many developers swear by it. But what is OOP?
According to Alan Kay, the inventor of OOP, the whole idea was based on biology. Kay (who majored in biology in college) likened objects to biological cells; each cell has its own "data" (DNA) and "logic", and they communicate via chemical "messages". No single cell is in charge of the whole body; the complexity changes from their interactions.
I agree completely with Alan Kay in theory; I only disagree in application. Alan Kay (and a lot of developers) believe that this can be accomplished with a programming language (like his language, Smalltalk). I believe that it's all a mindset and programming languages are only tools we can use to implement OOP.
I'm not saying the programming language does not matter; I'm just saying that the language is not responsible for making your code object-oriented โ the developer is.
In other words, there is no silver bullet in software1, but there's misplaced effort.
Misplaced effort
The abuse of OOP reminds me of the abuse of declarative programming languages by developers who are used to imperative programming languages.
I used to work as a software engineer in in-flight entertainment, and our language of choice for the UI was QML. QML is a declarative language, which means you have to describe what you want to achieve as opposed to listing the step-by-step instructions on how to achieve it.
However, what I noticed with amateur QML developers2 is that they would use the language imperatively as opposed to declaratively.
For example, let's say we wanted to animate a side panel in and out of the UI using QML. We could write it declaratively like this:
import QtQuick
Item {
width: 400
height: 400
Rectangle {
id: sidePanel
width: 200
height: parent.height
color: "#2c3e50"
state: "hidden" // DECLARATIVE: Start by being "hidden"
states: [
State {
name: "visible"
PropertyChanges {
target: sidePanel
x: 0
}
},
State {
name: "hidden"
PropertyChanges {
target: sidePanel
x: -sidePanel.width
}
}
]
// DECLARATIVE: Transition from "hidden" to "visible" (and vice versa) is handled automagically
transitions: Transition {
from: "hidden"
to: "visible"
reversible: true
NumberAnimation {
property: "x"
duration: 500
easing.type: Easing.OutQuint
}
}
}
MouseArea {
anchors.fill: parent
onClicked: sidePanel.state = (sidePanel.state === "visible" ? "hidden" : "visible");
}
}
Notice since the code is set up declaratively, animating the side panel is a matter of switching its state from "hidden" to "visible". The intent is very obvious.
However, we could go against the QML "declarative" philosophy and write it imperatively, like this:
import QtQuick
Rectangle {
id: badPanel
width: 200
height: 400
x: -200
color: "red"
PropertyAnimation {
id: slideIn
target: badPanel
property: "x"
to: 0
duration: 500
}
PropertyAnimation {
id: slideOut
target: badPanel
property: "x"
to: -200
duration: 500
}
MouseArea {
anchors.fill: parent
onClicked: {
// IMPERATIVE: Manually checking values and firing commands
if (badPanel.x < 0) {
slideIn.start();
} else {
// Now you have to write a second animation for sliding out!
slideOut.start();
}
}
}
}
Here, the developer has to explicitly check values and start the animations.
Both snippets of code work, but only one embodies the principles of declarative programming.
As I've illustrated, QML, a declarative language, can still be written in an imperative way. The language does not prevent it completely โ it only makes it awkward and more difficult to do incorrectly (i.e. the imperative way)3.
OOP is great...
I use OOP (a lot ๐) because it works:
- It keeps my code maintainable. It's nice to reason each class/module etc. as an "object" that is independent of all other objects. Then I get to route messages between them like a patchbay.
- In my experience, OOP works better for software that is developed for people that don't know how to code (i.e. the masses). This is because we all intuitively think in objects, and mapping human problems to objects (i.e. modelling the domain) becomes easier. In that way, OOP democratized computer programs.
- OOP helps me to reason about architecture better, for both my own code and others.
- There is no other way to make large GUI applications. Well, at least for now.4
...but OOP is not always the answer
Just because I use OOP, it doesn't mean I shun other paradigms. There are times that I write code procedurally and there are times that I write code using functional programming principles. Use the right philosophy for the right task. It's perfectly legal to mix and match to your taste.
Experienced game developers seem to hate OOP, and I get it. In game programming, performance and speed is very important, so I can understand people taking a more data-oriented approach (also known as Data-Oriented Design or DOD). This is sometimes more efficient, because the programmer writes code with knowledge of the low-level architecture and workings of the computer, and therefore could optimize better. However, a lot of software development doesn't require this. In those cases, OOP may suffice.
The bottom line
OOP is not a programming language; it's a mindset.
We should use programming languages to teach the principles of OOP (and other paradigms) as opposed to relying on them to govern us. The more we understand the philosophy (by reading about it and writing code), the more effectively we can apply it in our favor and most importantly, correctly.
-
In the software world, we have this weird idea that we can shield the developer from all issues he/she can encounter. An example of this is frontend developers' obsession with static types. But no matter what we do, we can't shield other developers from all problems; the developer must assume the responsibility bestowed upon him/her. Don't leave it to a machine. This also leads to developers relying on frameworks to make their code "clean". Frameworks don't have that power, developers do. Okay, rant over, for now ๐!ย โฉ
-
I was one at one point ๐. I was experienced in Java and C++, but those languages are imperative so the philosophy is different.ย โฉ
-
It may be worth saying that being bad at declarative programming doesn't mean you're a bad developer; it just mean you don't understand the paradigm.ย โฉ
-
Oh there is? Go ahead, I'll wait ๐คจ...ย โฉ