Programming paradigms nowadays
Writing a program like a recipe is not the only form of programming.
In fact, in the early days of computing, different forms of high-level programming were investigated and resulted in implementations. Imperative programming is the most popular because it is intuitive, facilitates to write algorithms, and is easily translated into machine language, but computing power increasing over time allows to make compilers for languages that are a better expression of the human thought.
High-level programming has not been always granted. Some challenged its usefulness. The inventor of the computer itself Von Neumann, when he was presented with Fortran, had this amazing reaction :
Why would you want more than machine language?
Here is the answer: the goal is to program as you think instead of thinking like a processor. And the practical advantage is to reduce the number of instructions to execute an operation .
But the evolution of language allows us to go further, and we have with objects the statements to translate a problem into a program more easily, or facilitate the representation of a real world activity into a formal language that can be processed by a computer.
Nevertheless, whatever the form takes a program, its code will always be compiled into machine language that is imperative. All paradigms therefore bring us to imperative code, and so their main goal is to transfer a part of the work from the programmer to the compiler. The higher the level of a language is, the greater the compiler must be sophisticated. One loses necessarily performance, to the benefit of productivity.
This is making a hierarchized code, to build blocks of instructions which are independent of any other block of instructions.
It was initiated by Niklaus Wirth in response to goto statements in Basic which tends to produce "spaghetti" code. It was implemented for the first time in 1968 in Algol W. This has not prevented goto to proliferate on personal computers in the eighties. They knew only Basic, the easiest language to implement.
The Pascal language was created to implement structured programming and make it mandatory. Even if it was since replaced by other languages, the principle of structured programming remained acquired and became the norm.
Imperative and procedural
The imperative mode is the same as applying a recipe, which is why it has emerged and is the most widely used: a succession of simple or iterative operations that modify the state of the ingredients up to arrive at the final state that you are looking for. Instructions change the states of the program through that of variables and objects. Imperative programming is also procedural, procedures being a succession of steps.
A distinction is made sometimes between the two paradigms, but they are inseparable and complementary. We cannot differentiate the sequence of commands of the imperative code and the sequences of instructions in the procedural code.
It describes the elements of a processing to perform without so far describe the order of instructions to accomplish this processing. It has therefore neither conditions nor controls structures.
It suits perfectly the description of interfaces, that are associated with events such as that of a keyboard or a mouse.
SQL is declarative just like HTML, XML and many derived dialects, including RSS. Regular expressions too and have a form adapted to searches and transformations of text. Models of system with a mathematical form belong to it, and logic programming too.
But reactive programming is the only variant that can suit any type of processing.
It is a form of declarative programming. It reverses the direction of processing, putting the result and defining it like a set of assertions. The validation of the results by the interpreter, in evaluating the assertions it implies, has the effect of completing the processing.
OOP was invented for simulation. It represents real-world objects as classes, and a class has attributes, its own variable, that represent the properties of the real object, and methods, its own functions. Objects of programs are obtained by declaring instances of a class. So the class represents all objects with same attributes and methods.
The concepts of OOP were set in the late 50s (ie 20 years before the onset of Basic and C). The first OO language was Simula 67 (a language for simulation). It had classes, instances and objects, inheritance, virtual methods (redefinable in inherited classes).
The Smalltalk language implemented a few years later by Alan Kay was purely OO. It was he who coined the term "Object Oriented Programming". He puts emphasis on the concept of messages, seeing the progress of the program as an exchange of messages between objects.
This is a concept that takes a renewed interest in 2014 with WebSocket, which are discussed further in the client-server architecture.
Some current programmers in high-level languages do not see the benefit of object-oriented programming or other such improvements in their field, system programming. See the article on the C language. Maybe current OO languages are not suitable for high-level system programming?
Inheritance or composition
This is a sub-paradigm of object orientation. The principle of inheritance is to define a class as derived from another with new attributes and methods. The principle of composition is to define traits or mixins, with attributes and methods, with their definition (unlike interfaces), which can be combined with those of any object.
If C++ was based solely on inheritance, and is the only one offering multiple inheritance, but then composition was added throught "traits". The Go language opted for composition only.
Composition could be considered superior to simple inheritance, as it allows to define classes of abstract objects and combine them to implement and allow uses of multiple contexts for the same program. A module is replaced by another module, with the same API, thus the same interface but different operations. Multiple inheritance is equivalent but a source of confusion.
This programming approach was described in 1973. It has not been implemented as a language but rather as extensions to other languages. It is similar to object orientation with the difference that all actors operate in concurrency, not sequentially. Messages are sent and received between actors asynchronously. The management of messages is separated from that of objects : each message contains a source and a destination and the runtime take them and forwards them to their target.
Most languages provide an extension to handle events (sometimes called wrongly "reactive extensions").
AOP aims to facilitate code reuse by separating the types of uses, called here concerns. To do this we declare classes and functions that can interact with different processes. This is not intended to be used in a simple program, but rather in a system designed to manage a global activity. Every aspect modifies the operations of the system. We can replace an aspect by another to adapt the system to a particular problem while maintaining the same database and same classes and functions.
This principle was developed by Palo Alto since 1994. Java has an extension oriented aspect, AspectJ which dates from 2001.
A functional language describes the processing as an evaluation of functions, where each one depends only on its parameters. A function does not have access to global variables, it can not currently see side effects.
This type of operation is old and dates of Lisp (1958), Erlang (1986), Haskell (1990). It has never been popular until the arrival of Scala (2001) which combines functional programming with other paradigms such as objects .
In reactive programming, when you write :
a = b + c
This does not mean, as is the case of imperative programming that the sum of the values of b and c are calculated, and that the result is assigned to the variable a. This means that the value of a corresponds to the sum of the values of b and c throughout the entire life of the program. So when b or c will be subsequently modified, a will be automatically changed. It is the responsibility of the runtime to update the variables with all the dependencies.
An implementation was made by INRIA in 1988 in Reactive-C, a C preprocessor which translates the code in imperative code. There are extensions for different languages, but if it is not possible to describe a system in terms of interactions, they relate rather to events programming.
Functional reactive programming
It aims to combine PR with PF and this makes the latter less strict, allowing functions to not depend only on their parameters.
A functional program is described in the form of relationships, as does reactive programming, we makes it reactive in introducing external states in functions.
Functions can then refer to global variables, but not as in imperative mode, functions are recalculated when the value of these variables change.
Roles or DCI
Programming by roles is the idea of Trygve Reenskaug that has developed this concept for decades and thinks it culminated in BabyUML. That wants to focus on the interaction between objects rather than on the results that every object can produce. (Ref) .
Besides the description of classes is described the communication between objects with a set of methods.
The difference with the AOP is that it does not modify the objects to suit the context, they are adapted to a context by adding a role, thus an interface. One would think that combining interfaces, as implemented by Go, could be used to this purpose, but the author is more ambitious and wants a clean, independent interface program is developed to describe the system as a set of interactions.
This paradigm is also called Data Context Interaction by the author.
The client-server architecture for programming on the Web may be used to local software with the offline mode, but also with the use of web technologies on a local machine. It becomes a new way of designing programs. Eg with Node.js as backend and HTML to describe the interface, a program can operate by exchanging messages between the interface and the backend, or between modules via a server on the backend. Example are Advanced Explorer (on this site) and the Light Table editor. This architecture makes the latter superior to other editors, as it can modify a program while it is running.
One can imagine to implement this architecture in a programming language in which the exchange of message is the basis of its operation.
By Denis Sureau, January 29 janvier 2014.