Das Abhängigkeitsmanagement ist aus den folgenden zwei Gründen ein großes Problem in OOP:
- Die enge Kopplung von Daten und Code.
- Allgegenwärtige Verwendung von Nebenwirkungen.
Die meisten OO-Programmierer halten die enge Kopplung von Daten und Code für absolut vorteilhaft, doch dies ist mit Kosten verbunden. Das Verwalten des Datenflusses durch die Ebenen ist ein unvermeidlicher Bestandteil der Programmierung in jedem Paradigma. Das Koppeln Ihrer Daten und Ihres Codes fügt das zusätzliche Problem hinzu, dass Sie einen Weg finden müssen, um das Objekt an diesen Punkt zu bringen , wenn Sie eine Funktion an einem bestimmten Punkt verwenden möchten .
Die Verwendung von Nebenwirkungen führt zu ähnlichen Schwierigkeiten. Wenn Sie für einige Funktionen einen Nebeneffekt verwenden, aber die Implementierung austauschen möchten, haben Sie so ziemlich keine andere Wahl, als diese Abhängigkeit einzuschleusen.
Betrachten Sie als Beispiel ein Spammerprogramm, das Webseiten nach E-Mail-Adressen durchsucht und diese dann per E-Mail versendet. Wenn Sie eine DI-Denkweise haben, denken Sie gerade darüber nach, welche Dienste Sie hinter Schnittstellen einkapseln und welche Dienste wo eingebunden werden. Ich lasse dieses Design als Übung für den Leser. Wenn Sie eine FP-Denkweise haben, denken Sie gerade an die Ein- und Ausgänge für die unterste Funktionsebene, wie z.
- Geben Sie eine Webseitenadresse ein und geben Sie den Text dieser Seite aus.
- Geben Sie den Text einer Seite ein, und geben Sie eine Liste der Links von dieser Seite aus.
- Geben Sie den Text einer Seite ein und geben Sie eine Liste der E-Mail-Adressen auf dieser Seite aus.
- Geben Sie eine Liste von E-Mail-Adressen ein, und geben Sie eine Liste von E-Mail-Adressen mit entfernten Duplikaten aus.
- Geben Sie eine E-Mail-Adresse ein und geben Sie eine Spam-E-Mail für diese Adresse aus.
- Geben Sie eine Spam-E-Mail ein und geben Sie die SMTP-Befehle aus, um diese E-Mail zu senden.
Wenn Sie in Ein- und Ausgängen denken, gibt es keine Funktionsabhängigkeiten, sondern nur Datenabhängigkeiten. Das macht sie so einfach zum Unit-Test. Ihre nächste Schicht sorgt dafür, dass die Ausgabe einer Funktion in die Eingabe der nächsten eingespeist wird, und kann die verschiedenen Implementierungen bei Bedarf problemlos austauschen.
In einem sehr realen Sinne veranlasst Sie die funktionale Programmierung natürlich dazu, Ihre Funktionsabhängigkeiten immer umzukehren, und deshalb müssen Sie normalerweise keine besonderen Maßnahmen ergreifen, um dies nachträglich zu tun. Wenn Sie dies tun, erleichtern Tools wie Funktionen höherer Ordnung, Verschlüsse und Teilanwendungen das Ausführen mit weniger Boilerplate.
Beachten Sie, dass nicht die Abhängigkeiten selbst problematisch sind. Es sind Abhängigkeiten, die in die falsche Richtung weisen. Die nächste Ebene kann eine Funktion haben wie:
processText = spamToSMTP . emailAddressToSpam . removeEmailDups . textToEmailAddresses
Es ist vollkommen in Ordnung, dass diese Ebene Abhängigkeiten hat, die wie folgt fest codiert sind, da ihr einziger Zweck darin besteht, die Funktionen der unteren Ebene zusammenzukleben. Das Austauschen einer Implementierung ist so einfach wie das Erstellen einer anderen Komposition:
processTextFancy = spamToSMTP . emailAddressToFancySpam . removeEmailDups . textToEmailAddresses
Möglich wird diese leichte Rekomposition durch fehlende Nebenwirkungen. Die Funktionen der unteren Schicht sind völlig unabhängig voneinander. Die nächsthöhere Ebene kann processText
anhand einiger Benutzerkonfigurationen auswählen, welche tatsächlich verwendet wird:
actuallyUsedProcessText = if (config == "Fancy") then processTextFancy else processText
Auch dies ist kein Problem, da alle Abhängigkeiten in eine Richtung weisen. Wir müssen einige Abhängigkeiten nicht invertieren, damit sie alle in die gleiche Richtung weisen, da uns reine Funktionen bereits dazu gezwungen haben.
Beachten Sie, dass Sie dies viel gekoppelter gestalten können, indem config
Sie zur untersten Ebene durchgehen , anstatt sie oben zu markieren. FP hindert Sie nicht daran, aber es macht Sie viel ärgerlicher, wenn Sie es versuchen.