3.1 Programming Paradigms
Programming paradigms provide fundamental styles for implementing software. In the
following, a short overview of the individual programming paradigms utilized in this work is
given. Extensive comparisons are available in the literature [77][78].
- Imperative programming focuses on executing a sequence of instructions,
operating on a state. Imperative programming is the primary utilized programming
style in scientific implementations, due to its simplicity and intuitive approach. This
paradigm is supported by all major languages relevant to CSE, such as Fortran,
C, and C++.
- Object-oriented programming aims for modularity by wrapping functionality
into reusable classes, offering defined interfaces for external utilization [79].
Polymorphism is implemented via so-called virtual class hierarchies, allowing to
specialize implementations according to run-time information. The object-oriented
approach is the most widely taught paradigm at universities, especially with
mainstream languages like Java and C++. The paradigm has also some basic
support by C and Fortran, although the features are not as extensive as with
typical object-oriented languages, such as C++.
- Functional programming uses mathematical functions for
formulating algorithms and programs by simultaneously avoiding states of objects
and mutable data [80]. Functional programming supports so-called lambda
expressions, based on the lambda calculus [81]. Pure functional programming
languages are available, such as Haskell [82]. Since the new C++ standard
2011, C++ natively supports lambda functions, thus enabling functional style
programming. However, previous C++ generations required external libraries to
enable functional-style programming, such as Boost Lambda [83] and Boost
Phoenix [84].
- Generic programming fosters code reuse by lifting algorithms or data structures
from concrete implementations to their most general form [85][86][87]. For
instance, in C++ generic programming approaches polymorphism from a different
angle than the object-oriented paradigm. Where the latter relies on run-time
decisions - introducing additional execution overhead - the first uses compile-time
dispatches, omitting run-time dispatch costs. C++ supports generic programming,
due to its type system and template mechanism. Also, C++’s standard template
library makes extensive use of this paradigm, as the algorithms, such as copy, are
separated from the datastructures, like vector, allowing to use an algorithm with
different datastructures and vice versa.
- Meta programming enables programs to generate or manipulate themselves
or other programs [88][89]. Meta programming techniques are considered to
be rather exotic, and are typically not taught in engineering curricula. Template
meta programming, as supported by C++, is a type of meta-programming,
where the template system is used to generate source code at compile-time.
Consequently, compilation times are increased significantly, impeding the
development process due to the potentially increased idle time. In C++, template
meta programming is used to implement the generic programming paradigm.
Although meta programming in general promises significant reduction in run-time
costs, it requires advanced programming skills to develop, debug, and maintain
implementations. Closely connected to this issue is the term leaky abstraction,
referring to the fact that intentionally hidden implementation details are exposed
to the developers in case of errors, further complicating debugging. This exposure
is triggered by the compile-time nature of template meta programming.