Mehrere Rückgabewerte einer Funktion

In der Softwareentwicklung arbeite ich sehr gerne mit Funktionen, um den Quellcode in kleinere, leicht verständliche Einheiten aufzuteilen. Idealerweise sind sie so allgemein, dass sie an mehreren Stellen im Code verwendet werden können. In der Regel geben diese Funktionen einen einzelnen Wert zurück. In manchen Fällen ist jedoch erforderlich, mehrere Werte zurückgeben zu können, vor allem dann, wenn die Daten in einem engen fachlichen Zusammenhang stehen – beispielsweise ein bestimmtes Produkt, seine abgesetzte Menge und der damit generierte Umsatz.

Dafür stehen uns in VBA (in allen anderen Programmiersprachen natürlich auch) mehrere Lösungsmöglichkeiten zur Verfügung, die ich hier kurz vorstellen möchte.

Rückgabe als Array

Arrays sind absoluter Meilenstein in der Sotftwareentwicklung und erlauben uns, mehrere gleichartige Werte bequem zu verwalten. Für unser Beispiel könnte man theoretisch auf die Idee kommen, in der Funktion ein Array mit drei Elementen anzulegen und als erstes Element den Produktnamen, im zweiten Element die abgesetzte Menge und im dritten den Umsatz zu übergeben.

In der Vergangenheit habe ich selbst solche Arraykonstrukte als Funktionsrückgabewerte genutzt. Handelt es sich um ein Programm, welches relativ selten erweitert wird, dann funktioniert dieses Konstrukt auch gut. Mittlerweile würde ich allerdings davon eher abraten. Denn wenn man so eine Funktion später an anderen Stellen aufrufen oder auch anderen Programmen als API bereitstellen möchte, muss man als Aufrufer ganz genau wissen, an welcher Arrayposition welcher Wert übergeben wird. Dies ist nicht intuitiv anhand der Methodensignatur ersichtlich, sondern es ist immer ein Blick in die konkrete Implementierung, bzw. in die hoffentlich vorhandene Funktionsdokumentation nötig.

Aufteilung der Funktion in mehrere Funktionen

Berücksichtigt man bei der Softwareentwicklung das Single-Responsibility-Prinzip, dann darf es eigentlich keine Funktion geben, die gleichzeitig mehrere Werte zurückgibt. Denn in diesem Fall würde es heißen, dass die Funktion mehrere Aufgaben erledigt, was dem Prinzip widerspricht.

Abhilfe würde in diesem Fall die Aufteilung der Funktion in separate Funktionen schaffen, zum Beispiel in getProdukt(), getMenge() und getUmsatz().

Das Wörtchen „eigentlich“ habe ich am Anfang des Kapitels nicht umsonst hervorgehoben. In der Softwareentwicklung geht es oft um die Abwägung und um Spagat zwischen der Performance, Wiederverwendbarkeit und Pragmatismus.

In diesem konkreten Beispiel mit drei unterschiedlichen zurückzugebenenden Werten ist die Sache einigermaßen händelbar. Bei beispielsweise 6 unterschiedlichen Werten könnte es dann wiederum anders aussehen. Zum einen ist es natürlich umständlicher, weil 6 Funktionen entwickelt, gewartet und aufgerufen werden müssen. Zum anderen könnte Performance zum Thema werden, wenn für die Ermittlung von jedem Wert ein erneuter Zugriff auf die Datenquelle nötig wäre

Rückgabe mit eigenen VBA-Datentypen

Meine favorisierte (pragmatischste) Lösung für diesen Anwendungsfall lautet – ich kreiere einen eigenen VBA-Datentypen, der auf die Bedürfnisse der jeweiligen Funktion ausgerichtet ist. Eigene Datentypen haben gewisse Ähnlichkeit mit Klassen, beschreiben jedoch ausschließlich die Datenhaltung.

Public Type typProdukt
    bezeichnung As String
    anzahl      As Long
    summe       As Double
End Type

Der so angelegte Datentyp wird dann als Rückgabewert der Funktion hinterlegt. Der große Vorteil dieser Lösung gegenüber dem Array ist, dass man die Attribute namentlich ansprechen kann. Darüber hinaus besteht auch keine Notwendigkeit, die Attribute als Variant zu deklarieren – man verwendet hier einfach die passenden Datentypen.

Public Function getProdukt() As typProdukt

    'hier erfolgt die Datenermittlung
    '...
    Dim produkt As typProdukt
    
    produkt.summe = 120
    produkt.bezeichnung = "TestProdukt"
    produkt.anzahl = 12
    
    getProdukt = produkt

End Function

Nach dem Aufruf der Funktion lassen sich die Daten bequem über deren Namen ansprechen.

Public Sub aufruf()
    With getProdukt()
        MsgBox .bezeichnung & " wurde " & .anzahl & "-fach verkauft und erlöste " & .summe & " €."
    End With
End Sub

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.