Hier ist ein Beispiel dafür, wie Sie dies aus funktionaler Sicht angehen und wie Sie potenzielle Fallstricke vermeiden können. Ich arbeite in Haskell, von dem ich annehme, dass Sie es nicht wissen, also werde ich es im weiteren Verlauf ausführlich erklären.
data Application = Applied ApplicationDetails |
InReview ApplicationDetails |
Approved ApplicationDetails |
Declined ApplicationDetails
Dies definiert einen Datentyp, der sich in einem von vier Zuständen befinden kann, die Ihren Anwendungsstatus entsprechen. ApplicationDetails
wird als vorhandener Typ angenommen, der die detaillierten Informationen enthält.
newtype UpdatableApplication = UpdatableApplication Application
Ein Typalias, der explizit von und nach konvertiert werden muss Application
. Dies bedeutet, dass, wenn wir die folgende Funktion definieren, die eine akzeptiert und auspackt UpdatableApplication
und etwas Nützliches damit macht,
updateApplication :: UpdatableApplication -> ApplicationDetails -> Application
updateApplication (UpdatableApplication app) details = ...
Dann müssen wir die Anwendung explizit in eine aktualisierbare Anwendung konvertieren, bevor wir sie verwenden können. Dies geschieht mit folgender Funktion:
findUpdatableApplication :: Application -> Maybe UpdatableApplication
findUpdatableApplication app@(Applied _) = Just (UpdatableApplication app)
findUpdatableApplication _ = Nothing
Hier machen wir drei interessante Dinge:
- Wir überprüfen den Status der Anwendung (mithilfe des Mustervergleichs, der für diese Art von Code sehr praktisch ist) und
- Wenn es aktualisiert werden kann, verpacken wir es in eine
UpdatableApplication
(die nur eine Anmerkung zum Kompilierungstyp der hinzugefügten Typänderung enthält, da Haskell über eine spezielle Funktion verfügt, um diese Art von Tricks auf Typebene auszuführen, die zur Laufzeit nichts kostet). , und
- Wir geben das Ergebnis in einem "Vielleicht" zurück (ähnlich wie
Option
in C # oder Optional
in Java - es ist ein Objekt, das ein Ergebnis umschließt, das möglicherweise fehlt).
Um dies tatsächlich zusammenzustellen, müssen wir diese Funktion aufrufen und, wenn das Ergebnis erfolgreich ist, an die Aktualisierungsfunktion weiterleiten ...
case findUpdatableApplication application of
Just updatableApplication -> do
storeApplicationInDatabase (updateApplication updatableApplication)
showConfirmationPage
Nothing -> do
showErrorPage
Da die updateApplication
Funktion das umschlossene Objekt benötigt, können wir nicht vergessen, die Voraussetzungen zu überprüfen. Und da die Vorbedingungsprüfungsfunktion das umschlossene Objekt in einem Maybe
Objekt zurückgibt, können wir nicht vergessen, das Ergebnis zu überprüfen und entsprechend zu reagieren, wenn es fehlschlägt.
Nun ... Sie könnten dies in einer objektorientierten Sprache tun. Aber es ist weniger bequem:
- Keine der OO-Sprachen, die ich ausprobiert habe, verfügt über eine einfache Syntax zum Erstellen eines typsicheren Wrapper-Typs.
- Es ist auch weniger effizient, da sie zumindest für die meisten Sprachen den Wrapper-Typ nicht entfernen können, da er zur Laufzeit vorhanden und erkennbar sein muss (Haskell hat keine Laufzeit-Typprüfung, alle Typprüfungen sind es zur Kompilierungszeit durchgeführt).
- Während einige OO-Sprachen Typen haben, die denen entsprechen, haben
Maybe
sie normalerweise keine so bequeme Möglichkeit, die Daten zu extrahieren und gleichzeitig den Pfad zu wählen. Auch hier ist der Mustervergleich sehr nützlich.