We begin our Object-Oriented Programming Course with this first introduction where we will see what it is, where it comes from, and what its purpose is.
Object-Oriented Programming (OOP) is a programming paradigm that is based on the concept of “objects”, which are entities that encapsulate data and behaviors, and the relationships between them.
Object-Oriented Programming aims to achieve:
- Modularity: Allows dividing a system into independent components that can be developed, tested, and maintained separately.
- Reusability: Facilitates code reuse through inheritance and class composition.
- Flexibility: Allows adapting the software to changes in requirements or the execution environment more easily.
- Scalability: Allows scaling the software by adding new objects and classes as needed, without affecting the existing structure.
Without too much fear, we can say that it is the programming paradigm that has had the most influence in the last 50 years.
But before we start talking about classes, inheritance, and interfaces like crazy, let’s start by seeing where it comes from and why it is so important.
Basic programming knowledge is assumed. If that’s not the case, I recommend you take a look at our Introduction to Programming Course
Where does object-oriented programming come from?
Let’s go back 50 years. At that time, computing was in its infancy 🐣, and neither the tools nor the needs regarding programs were what they are today.
So to speak, “everything was yet to be done.” But what was already clear back then was that it was convenient to group data into containers (data structures).
For example, if you had a person, it was logical to have
Person {
string Name;
string Surname;
DateTime BirthDate;
}
This grouping was convenient, so we could work with a Person as a whole. Otherwise, you ran the risk of accidentally mixing up the data of one person with another.
Furthermore, these groupings could be composed. That is, one of your groupings could contain other groupings inside. For example, imagine you wanted to make a program that draws geometric shapes.
Point2D {
int x;
int y;
}
Shape {
Point2D Position; // composition with Point2D
int Rotation;
int Width;
int Height;
}
Where Shape uses Point2D as its position. So far, so good. We have our data containers (very nice and very practical).
Now you could use your shape to create Squares, Rectangles, Equilateral Triangles, and Circles. You simply used your Shape container and filled in the data as needed.
The problem is coming
The problem arises when, in addition to data, you want to add behavior.
Imagine we want to add a function that calculates the area. It makes sense for a shape to know how to calculate its area because it is something intrinsic and internal to the shape (it doesn’t depend on anyone else).
At that time, the natural tendency to solve this was to use Function References as members of your grouping. For example,
Shape {
Point2D Position;
int Rotation;
int Width;
int Height;
int GetArea(); // we have added a reference to a function
}
But of course, a Rectangle, a Circle, and an Equilateral Triangle do not calculate their Area with the same function.
Well, no problem, I’ll create shapes. As I create them, I’ll change the function (directly in memory!) to the one I need according to the shape.
And you’ve messed up…
3000 lines and 217 files later, when you called a function you had no idea which function you were calling, because it had been changed 14 times throughout the program.
Imagine the problem of having to make a payment platform and not being 100% sure how each part works! (you would probably end up getting fired or sued or both)
Object-oriented programming
Doing it this way, the situation had gotten really messy. No one could make good programs like that, it wasn’t sustainable. So some very smart people started thinking.
They thought a lot. They visualized 12-dimensional universes. They modeled the world. They laid the foundations for a new programming paradigm.

They weren’t just trying to solve a problem. They were trying to invent a methodology that would allow for a systematic approach to solving any programming problem (which is no small feat).
After a lot of thinking they said, we’ve got it 💡! What we need are four pillars:
- Abstraction (through objects)
- Encapsulation
- Inheritance
- Polymorphism
And they were very pleased with themselves. We will see these four pillars in due time, what they are, and what function each of them served.
But the important thing today is to emphasize that they are not “magic laws” nor absolute truths. It’s what they needed to fix the mess they had created.
Object-oriented programming today
A lot of time has passed since the foundations of object-oriented programming were established. Many things have changed in this time.
Currently, even the number of detractors of object-oriented programming is increasing. Questioning whether it is a paradigm that remains relevant today or has become outdated. Well, several things are happening here.
On one hand, current needs are not the same as when those very smart people sat down to think. Programming is now much more complex and covers needs that weren’t even glimpsed back then.
On the other hand, object-oriented programming has also changed. In fact, it has become more complex and more rigid. Even, in the words of some of its creators, it has evolved and deviated from its original purpose.
That doesn’t mean object-oriented programming is bad or outdated. On the contrary, we said that it is a paradigm that arises naturally, as you make increasingly complex programs.
What is necessary is to understand the foundations and the purpose of each of them. It’s not a problem with the paradigm, but with its use. You need to know how to apply it and adapt it to modern times.
That’s what we will dedicate ourselves to in this course, where we will see all these things. Where each of them comes from. And the practices that make sense to apply today, and those that are best to avoid.
