Everything is an abstraction in the programming world. Every language, library, and framework attempts to introduce some features that allow programmers to do their job better.
The rule of thumb is that every abstraction comes with a tradeoff, hence every programming language simplifies some things but restricts others. There are many different languages designed to make specific things more manageable, and every one of them has some limitations related to its design.
Programmers may use their favorite features and, thanks to them, implement amazing things. Still, they have to abide by a specific syntax, compiler restrictions, interpreter requirements, and the general logic of the language of their choice. That is why, we should learn those features and understand what we gain and what we lose whenever we utilize a specific approach.
The imperative paradigm
A programming paradigm is a set of features that describe the rules of the implementation and the execution process. Some languages may adhere to one or many sets of features, thus implementing one or many different paradigms.
Probably the most important one is called imperative programming. The name is closely related to giving commands, so when we look at the first computers and their programmers, it becomes obvious why it is so famous.
From the very early days of computing machines, the idea was relatively simple. Programmers had to instruct the machine to do certain things in a specific order to get the result they needed. For instance, most of the instructions were more or less similar to instructions like reading data from memory, applying logical or arithmetic operations, and saving the data back to memory.
Throughout the years, commands became more and more sophisticated, but the general imperative idea of expressing them in an exact order and modifying the state remained with us to this day.
The history of imperative variants
As many things in the programming world do, this one also starts with an assembler. An assembler is a language implementing the imperative paradigm, and its instructions correspond to processor commands that calculate the result by modifying the state in the correct order. Thanks to the standardized syntax, programmers could easily instruct their computers to read specific data, manage multi-step calculations, and write the results to the desired place. The concept stayed the same, but the complexity was reduced tremendously.
The next step that may seem quite familiar to any coder is procedural programming. Its crucial feature is combining commands into procedures that could be called at any point to calculate specific things. A programmer still writes explicit instructions but now may use procedures as an addition to the original concept. That extra abstraction brought the imperative programming to the next level, allowing engineers to express the same logic more concisely.
Languages like Pascal or C are good examples of this approach. Next to implementing a more specific procedural paradigm, they introduce a more humane syntax than those we know from assemblers.
The last significant member of the imperative family is object-oriented programming. This paradigm requires the division of logic into objects that interact with each other. Each piece may define its internal state and set of methods to make communication possible. The logic inside is still imperative, but programmers are bound to object-based architecture. The purpose was to model the problem in correspondence to real-life thinking and thus simplify its logic comprehension.
The best example of pure OOP language is Smalltalk, but various multi-paradigm languages like C++ or Java, also widely implement this paradigm.
Imperative programming is the idea of giving explicit instructions to calculate and modify data until a meaningful result is achieved. It is ubiquitous in the history of programming languages because of its close relation to the very core of machine operations. Thanks to a higher-level syntax and additional features, we may utilize more specific paradigms specifically designed to handle particular problems that arise before programmers around the world.
Understanding different approaches helps to achieve a complete comprehension of the language design and its usage. Of course, imperative programming is only a part of the whole picture, so we will discuss other vital paradigms in the future. Stay tuned!