Seiteneffekte

Aus Programmieren-Wiki
🚧 Diese Seite befindet sich in Bearbeitung 🚧

Undokumentierte Seiteneffekte sollen vermieden werden.

Seiteneffekte bezeichnen dabei alles, was eine Methode abseits der Berechnung des Rückgabetyps tut. Zum Beispiel das Ändern von Attributen oder Ausgaben auf die Kommandozeile. Seiteneffekte sind in Java dabei nichts Ungewöhnliches. Beispielsweise das Inkrementieren ++i beinhaltet einen Seiteneffekt, da zum einen der aktuelle Wert von i zurückgegeben wird und dieser gleichzeitig aber erhöht wird. Ähnlich verhält es sich mit der Methode next() des Iterator-Interface.

Oftmals ist es übersichtlicher und besser Stil-Methoden mit Seiteneffekten den Rückgabetyp void zu geben. Dieses Prinzip wird "Command-Query-Separation" (QCS) genannt und wird auch in der Vorlesung angesprochen. Wird dieses Prinzip nicht eingehalten, so ist zumindest gefordert, dass der Seiteneffekt klar in JavaDoc der Methode dokumentiert ist.

Negativbeispiel

double computeMedian(int[] data) {
    Arrays.sort(data);
    if (data.length % 2 == 0) {
        return ((double) data[data.length / 2] + (double) data[data.length / 2 - 1]) / 2;
    }
    return data[data.length / 2];
}

Diese Methode erweckt den Anschein als würde sie lediglich den Median eines gegebenen Arrays berechnen. Tatsächlich wird von der Methode nicht nur der Median berechnet, sondern auch das Array sortiert. Das liegt daran, dass Objekte in Java bei einem Funktionasaufruf nicht kopiert werden. Wir können das Array stattdessen in der Methode kopieren und haben damit eine Methode frei von Seiteneffekten:

Positivbeispiel

double computeMedian(int[] data) {
    int[] copy = new int[data.length];
    // Efficient Java-API method to copy arrays
    System.arraycopy(data, 0, copy, 0, data.length);
    Arrays.sort(copy);
    if (copy.length % 2 == 0) {
        return ((double) copy[copy.length / 2] + (double) copy[copy.length / 2 - 1]) / 2;
    }
    return copy[copy.length / 2];
}

Ist der Seiteneffekt hingegen erwünscht, so sollte dies explizit gemacht werden:

/**
* Sort and compute the median of a given array.
* 
* @param data The data to calculate the median of. The passed in array-Object will be sorted.
* @return the median of data.
*/
double sortAndcomputeMedian(int[] data) {
    Arrays.sort(data);
    if (data.length % 2 == 0) {
        return ((double) data[data.length / 2] + (double) data[data.length / 2 - 1]) / 2;
    }
    return data[data.length / 2];
}