Programming Paradigms
A programming paradigm refers to the pattern which a program code follows. It can be thought of as a style of programming. Some languages will enforce a paradigm onto the programmers using it while others allow you to program in whichever paradigm you wish.
In this article we are going to take a look at a few common programming paradigms;
- Imperative
- Procedural
- Object-OrientedFunctional
- Declarative
There are a few more interesting paradigms like reactive or mathematical but I will limit this article to these five paradigms.
For the Object-Oriented paradigm, I will take a deeper dive in a separate article mainly because of how much it is applied and how daunting it can be to grasp.
Now you might wonder why you should even care about different paradigms.
In programming, we can have different solutions to the same problem to simply say there is not a single way of tackling a problem. We can write code that solves the problem is different approaches and even programming languages and still make it. Paradigms offer us guidelines in which we can structure our code for solving problems, they are merely just that.
Without further ado, let's get into it ๐๐ฝ
Imperative Paradigm
In the imperative paradigm, we write statements that describe the way to solve our problem step-by-step. A statement here simply refers to some action to be carried out. One thing peculiar to imperative paradigm is that every statement changes the program's state.
A typical example of an imperative language is C.
Let's say we want to calculate the area of a circle. We know the area of a circle if given by $\pi \times radius^2$ so to do it step by step;
PI = 3.14
radius = input("Enter the radius : ")
area = PI*radius**2
print(area)
In the code above, we do the following;
- we get the radius of a circle from the user.
- we then compute the area of the circle
- print the area of the circle
Every statement above changes the program's state.
- In the first line, we declare the value of PI.
- Next, we read some value from the user, here the state of the program is tilted towards reading from Standard Input
- We then compute the area of the circle and
- print the area of the circle, the program state is then towards Standard Output
Procedural Paradigm
The procedural paradigm is a subset of the imperative programming paradigm, so it has all of the features of the imperative paradigm.
Here the program instructions are divided into subroutines or procedures and these are just blocks of code to carry out a specific task/computation.
This paradigm encourages modularity i.e dividing your solution into smaller blocks that do one thing and do it well. A procedure may call another procedure in itself. This paradigm encourages reusability.
C language is a typical example of a language following the imperative procedural paradigm.
In C, we will divide each execution unit into separate functions/procedures. We will then have the main function which will be the entry point of our program and it is from there that every other procedure can be called.
Here is some example code to compute the area of a circle (This is not C).;
const PI: number = 3.14;
function readUserInput(): number {
// read user input from keyboard for example
return userInput;
}
function computeArea() {
const radius = readUserInput();
const area = PI * (radius * radius);
print(area);
}
function main() {
computeArea();
}
// more operations...
In the code above, we have defined functions readUserInput()
to read input from the user
as well as a function computeArea()
which should read the radius of the circle from the user as input
and then compute the area.
We then have the main function where we call out computeArea()
function.
Object-Oriented Paradigm (OOP)
This is another form of the imperative paradigm.
In OOP, everything is considered an object. Each object holds some information and methods/procedures to mutate/modify its data.
This paradigm is very popular nowadays.
We will define classes/blueprints that will make the basis for any type of object in our code.
Some good examples of object-oriented languages include Java, Python3, and C++, etc.
You can read more about this paradigm here.
Declarative Paradigm
In this style, the program is written in a way that describes what results are expected from the program without explicitly telling the computer how to carry out the task.
Any style that is non-imperative is said to be declarative.
A typical example of a language following this style is SQL.
SQL allows you to specify what results in you want but the inner workings of the system executing it is none of your business. A database might decide to store data in the form of a hierarchical structure while another might do so as tables. Regardless of the way the database was designed, it will still execute your SQL code even if the way it does it is different.
SELECT count() FROM Africa WHERE area >= 1000000
The SQL code above will look into a table named Africa and count the number of countries having a surface area of 1 million and above.
Functional Paradigm
This is a form of Declarative Paradigm
.
A program is constructed by composing together functions.
Here, functions are capable of being used and do anything;
- Assigned to variables
- Passed as arguments to other functions
- Returned from other functions
- and much more...
With this ability, we will typically say functions are considered first class citizens.
Some examples of functional programming languages include; Lisp, Haskell while other languages like JavaScript, Python and many more support this programming style.
In this style, we have the concept of pure functions
and impure functions
.
Pure functions are simply those that have no side effects i.e cannot modify an external variable, change the program's state or read/write values from/to a user.
Take a look at the computeArea()
function we had from earlier;
// impure function
function computeArea() {
const radius = readUserInput();
const area = PI * (radius * radius);
print(area);
}
We see that it is reading a value from the user and then printing its result. This function is considered impure because it changes the program's state.
A pure function implementation might look like the code below;
// pure function
function computeArea(radius: number): number {
const area = PI * (radius * radius);
return area;
}
Here, the function does not read/write. The radius is passed to the function as an argument and it returns the area of the circle - all this without mutating any external value or changing the program's state.
If any function also modifies the value of an external variable, it is also considered impure. Consider the example below.
let area;
// impure function
function computeArea(radius: number): number {
// changes the value of area which is an external variable to the function
area = PI * (radius * radius);
}
At this point, we have taken a look at some of the programming paradigms that are commonly used in the programming world today.
If you are interested in learning more paradigms, then consider reading this Wikipedia article.
We are going to close this here. I hope you enjoyed reading this as much as I enjoyed writing it.