Generic programming

from Wikipedia, the free encyclopedia

Generic programming is a technique for developing reusable software libraries . Functions are designed as generally as possible so that they can be used for different data types and data structures .

Some programming languages ​​are implemented using the concept of generic types or templates - this is how dynamic programming languages , in which the type of a variable can change at runtime, are generic due to their generalized polymorphism . Languages ​​that offer such mechanisms are also said to allow generics .

It is essential in generic programming that the algorithms are not written for a specific data type , but only make certain demands on the types. The principle is also called parametric polymorphism .

A prime example is the C ++ standard library of the C ++ programming language , in which the algorithms are separated as much as possible from the data structures with which they work.

Comparison of different techniques

The maximum function is an example

,

the given for two values , of the same type the larger value returns.

The prerequisite is that and are comparable with each other, i.e. the expression is defined and describes an order .

Rewriting the algorithms for each data type

In classic programming languages ​​such as C , you could program a function for each data type that produces the same result in the corresponding type.

The following functions determine the larger of the two numbers a and b , but once as an integer and once as a float :

int maxInt(int a, int b) {
    if (a < b)
        return b;
    
    return a;
}
float maxFloat(float a, float b) {
    if (a < b)
        return b;
    
    return a;
}

It is noticeable that the code is always the same, only the types differ.

Generic programming

Here the type is determined by the preprocessor.

#define Item int

The target data type in a separate file.

static Item maximum;

The storage mechanism is also located in the same file.

static void save(void* tmp) {
    maximum = *((Item*) tmp);
}

Of course, there's a special method of comparing the type here.

int compare(void* aa, void* bb) {
    if (*((Item*) aa) < *((Item*) bb))
        return -1;

    return 0;
}

The generic algorithm for rendering the maximum.

void max(void *aa, void *bb, void save(void*)) {
    if (compare(aa, bb))
        save (bb);
    else
        save (aa);
}

The function max is thus completely generic. You notice that the save and compare functions use a specific data type, but these are encapsulated later, since they do not belong to the grammar of the algorithm.

Use of object-oriented means

The object-oriented approach does not work satisfactorily in the context of static typing. Although classes can be extended by "other" data types with interfaces or multiple derivation , so that the behavior of the generic programming can be partially reproduced using polymorphism, the complete independence of different types (or classes) is not implemented because it can these techniques are not strictly object-oriented techniques either.

If you define a class (for example in C ++) Vergleichbaresand derive the classes and from it for a physical simulation, for example (says that both lengths and dimensions are something comparable), you can write: LaengeMasse

Vergleichbares& max(Vergleichbares& a, Vergleichbares& b) {
    if (a < b)
        return b;
    
    return a;
 }

but there are still two problems:

  • First of all, that the result type is only "comparable"; you have to tell the compiler explicitly when calling that the maximum of two lengths is again one length (if you want to use its length properties, which is likely), but above all,
  • that this function makes it possible to “determine” the maximum of a length and a mass, although this operation has no physical sense.

Templates

Generic programming, for example implemented in C ++ using templates , now combines the flexibility of the macro with type safety and the other properties of the function. The generic implementation of max in C ++ is

template<typename T>
T max(T a, T b) {
    if (a < b)
        return b;
    
    return a;
}

The function defined in this way max()can now be used for all types with a comparison operator .

Another advantage is that you don't have to say explicitly when defining that a type is comparable (for example by deriving from a corresponding class), you just have to ensure that it has the necessary properties (in this case an operator < with correct semantics ). In this way, types can also be used with the function that were designed in ignorance of the function (for example, the built-in types of the programming language).

An algorithm should always require as little of the type as possible. The STL algorithms do not work directly on the containers, but with iterators . In this way, they are largely independent of the precise properties of the special container and can in some cases even work directly on input and output flows.

Generic programming in various programming languages

  • As already mentioned, generic programming in C ++ is supported by templates.
  • Generic types existed in Ada long before templates were introduced in C ++.
  • There are also generic data types in ABAP .
  • In Java there are generic types from version 1.5.
  • In the .NET languages C # and VB .NET (as of .NET 2.0) there is the generic types ( generics ).
  • Generic classes exist in the Eiffel programming language .
  • The functional programming language ML (and descendants such as OCaml ) and Haskell allow generic programming. Type polymorphism is the conceptual basis there. You can even generate modules. Generic modules ("parametric modules") are referred to here as functors. You can pass functors modules as parameters and get a new module as the result.
  • In programming languages ​​such as Python , which manage data types dynamically and also support operators, practically any method can be used in the sense of generic programming.
  • Finally, you can also use the macros in C for generic programming, although they were not originally introduced for this purpose.

Software engineering

A generic model can be adapted to the specific circumstances of a concrete situation; z. B. a generic process model such as waterfall or spiral model for a specific project . This process is also called tailoring in the field of software engineering .

If the generic model changes, you can easily adapt its characteristics if the path from the model to the characteristic is described in detail and you only have to follow the changed elements. In the case of non-generic models, this is also referred to as overfitting .

See also