Procedural Programming vs Object-Oriented Programming

Published on 2015-02-28. Modified on 2023-10-26.

What are the facts about procedural programming versus object-oriented programming?

The discussion about procedural programming versus object-oriented programming, in the sense of which is "best", is mostly dominant in communities of programming languages that supports both programming paradigms. And the Internet is filled with blog posts, forum posts, YouTube tutorials, guides and documents about the procedural programming vs object-oriented programming "issue".

The fact is that these discussions makes very little sense.

Programming is about solving problems and you can solve any programming problem in any programming paradigm. In some programming languages you can even combine both paradigms. However, not all paradigms solve specific problems equally efficient. Therefore a discussion about one paradigm vs another doesn't make sense until you first define the problem you are trying to solve. Once you have defined your problem with some very clear parameters you can understand which paradigm is best suited to solve your problem.

Discussions that aren't centered around very specific problems are nothing more than theoretical babble and mudslinging.

In order to really understand a specific programming paradigm it is always a good idea to look at how it first evolved. What was the reason for its development? What problems existed with other programming paradigms that needed a new way of thinking? Was it a real world problem or simply an academic problem? And how has it since evolved?

So let's take a look at some history.

Non-structered programming

Before the advent of object-oriented programming, around the end of the fifties, much software was developed using programming languages that emphasized unstructured programming (or non-structured programming), sometimes also referred to as first-generation and second-generation languages. Unstructured programming is the historical earliest programming paradigm.

There are both high-level and low-level programming languages that use non-structured programming. These include early versions of BASIC, COBOL, MUMPS, JOSS, FOCAL, TELCOMP, machine-level code, early assembler systems (those without procedural meta operators) and some scripting languages.

A program in a non-structured language usually consists of sequentially ordered commands, or statements, usually one in each line. The lines are usually numbered or may have labels which allows the flow of execution to jump to any line in the program (like with the unpopular GOTO statement).

This is a simple example in BASIC.

10 INPUT "What is your name: "; N$
20 INPUT "How old are you: "; A$
30 PRINT "Hello "; N$
40 IF A$ > 80 THEN GOTO 60
50 PRINT "You are still young!"
60 PRINT "You are getting old!"
70 END

Non-structured programming is not suitable for the development of large programs and it does not allow re-usability of code. You cannot avoid breaking the rule of DRY. Non-structured programming became famous for creating spaghetti code and as a result "structured programming" was invented.

Structured programming

Then in the sixties structured programming emerged - mainly due to the famous letter by Edsger W. Dijkstra Go To statements considered harmful.

Structured programming is a programming paradigm that improves the clarity, quality, and development of software by making use of subroutines, block structures and loops. This is contrast to using simple jumps such as the GOTO statement.

Structured programming, in contrast to non-structured programming, tries to improve the clarity, quality, and development time by making more extensive use of control flow constructs such as loops and conditions with if, then, else, endif statements, and iterations of blocks with for, while, do..until statements.

Blocks are also used to group statements together.

This is a simple example of a conditional statement in C:

if (age < 80) {
    printf("You are still young!\n");
} else {
    printf("You are getting old!\n");
}

Procedural programming

Procedual programming takes structured programming one step further by adding functions. Functions are also called "procedures" based on the concept of a "procedure call".

Sometimes people call procedural programming "structured procedural programming" because they want to emphasize that "procedures", i.e. functions, was added to the structured way of programming.

With functions it becomes possible to organize code into unique blocks that can be reused and it becomes much easier to avoid the problems of DRY. This makes the overall organization of code much better.

This is a very simple example of the usage of a function in PHP:

function add_integers(int $a, int $b): int
{
    return $a + $b;
}

echo add_integers(3, 5);

In procedural programming all functions are available to any part of a program as global functions. In small programs this isn't a problem, but as the size of a program grows, a small change to one function can affect many other functions if they are depending on that particular function. This can particularly be a problem when huge teams of people work together on the same code base. A minor change to one function would result in a cascade of errors in lots of other functions that depended on the original function.

Object-oriented programming

Object-oriented programming takes procedural programming a couple of steps further. A new technique evolved which allowed data to be divided into separated scopes called "objects". Only specific functions belonging to the same scope could access the same data.

In the beginning objects where not called objects, they where just viewed upon as separate scopes. Later when dependencies were reduced and connections between functions and variables inside these scopes where viewed upon as isolated segments, the result gave birth to the concepts of "objects" and "object-oriented programming".

Later, I believe it was mainly due to the development of Java, certain terms, jargon and buzz-words arose and a function was no longer called a function when it resided inside a separate scope, instead it was called "a method". Variables was also no longer called variables, but was termed "attributes" when they resided inside a separate scope.

An object is in essence simply a collection of functions and variables now referred to as "methods and attributes".

The way methods and attributes are kept isolated inside a separate scope is mostly by the usage of what is called "a class". A class, once it is instantiated, is called an object. It is important to note that not all programming languages that support the object-oriented paradigm has some called classes.

An object is in essence simply a collection of functions and variables now referred to as "methods and attributes".

Encapsulation is the process of putting data, such as variables, constant, arrays, lists, and other types of data, and functions into a single unit. Encapsulation means to "encase" or "enclose" something, and it is achieved in, for example, Java, C++, and PHP by the class concept. By putting related data and functions into a single unit, we can better organize our code into separate blocks with related features and functionality.

Abstraction is the process of hiding and securing data from other functions. In Java, C++, and PHP, classes are used to encapsulate and keywords such as private and public determine exactly how the scope of classes and methods work, they hide or expose the attributes and methods of the class. Abstraction focuses on just the relevant data of an object and hides all the details which may or may not be for generic or specialized behavior. It hides the background details and emphasizes on the essential points to reduce complexity and increase efficiency.

Inheritance is the process of obtaining the attributes and methods from one class to another class. With inheritance you avoid DRY as you can avoid duplicating code across multiple classes and functions. Instead classes can inherit functions of other classes and even expand their functionality. Inheritance is a way to reuse code and allow independent extension of the software via public classes and interfaces. The relationships of objects give rise to a hierarchy. Inheritance was invented in 1967 for the programming language Simula 67.

Polymorphism is the ability in programming to present the same interface for different functionality. Poly means "many" and "morph" means change or form. It's the ability to have multiple functions with the same name, yet with different functionality or implementation. With polymorphism we can have 3 different functions all called printOut, depending on the context one function could output HTML, another JSON, and the last XML.

Conclusion

All-in-all we can say that object-oriented programming is about organizing code. It is an extension of procedural programming, and it is about avoiding a global scope and about sharing resources between classes and functions. You extend functions by "borrowing" their blueprints without actually affecting the original code. And you override functions without affecting the original code. And you isolate scope by putting methods (functions) and attributes (variables) into classes.

So object-oriented programming relies on these four characteristics: Encapsulation, abstraction, inheritance, and polymorphism. How these different ideas are implemented vary from programming language to programming language.

A funny thing to think about is that many object-oriented programming language compilers and interpreters are developed in a pure procedural programming language. PHP for example is developed in C. All the object-oriented features of PHP developed in a pure procedural implementation. In other words, you are using a pure procedural programming language to develop an object-oriented programming language.

Now, when you feel compelled to ask which programming paradigm is the best, procedural vs object-oriented, you should know that the question makes no sense.

Recommended resources