PHP: Monaden

DDD
Freigeben: 2024-11-02 21:09:30
Original
702 Leute haben es durchsucht

Dieser Beitrag ist stark vom Tech-Talk von Gina Banyard beim „FORUM PHP 2024“ inspiriert:

Monaden mit 3 einfachen Synonymen entmystifizieren

Beginnen wir mit ein paar Synonymen:

  • Behälter
  • Verpackungen
  • Entwurfsmuster

Wenn Sie „PHP-Monaden“ googeln, tauchen schnell andere Konzepte auf, wie funktionale Programmierung, Bindung, Stapel und sogar esoterische Mathematik (z. B. Funktor, Monoide).

Hab keine Angst.

Im Kern ist eine Monade ein Muster, das auf verschiedene Arten implementiert werden kann.

Designmuster

Wenn Sie einige Vorgänge ausführen müssen, können Sie wie gewohnt einfach benutzerdefinierte Objekte und Helfer definieren.

Warum also mit alternativen Konzepten herumexperimentieren?

Meiner Meinung nach ist das immer noch eine gute Frage, da Sie effizient bleiben müssen, aber bei klassischen Ansätzen gibt es häufige Einschränkungen:

  • Die Reihenfolge der Vorgänge ist wichtig
  • WET-Code
  • Ausnahmen

Monaden können optionale (oder noch nicht verfügbare) Werte konsistenter verarbeiten.

Monad vs. klassische Fehlerbehandlung/Ausnahmen

Moderne Projekte enthalten Tools für die statische Analyse, PHP-Ausnahmen werden jedoch nicht typisiert.

Mit anderen Worten: Die Tools können keine Ausnahmen in der Funktionssignatur erkennen und daher nicht feststellen, ob der Code Ausnahmen korrekt behandelt.

Um das zu testen, schreiben Entwicklerteams normalerweise Funktionstests, aber eine Früherkennung mit statischer Analyse wäre zuverlässiger.

Quelle: „Les Exception: le trou dans la raquette du typage“ (fr)

Mit Monads erhalten Sie in allen Fällen ein typisiertes Objekt, beispielsweise einen benutzerdefinierten Enum-Fall (z. B. FileErrors::AccessDenied), sodass der Fehler im System eingegeben wird.

Implementierung der Logger-Monade

Der Aufbau eines robusten Protokollierungssystems kann eine Herausforderung sein. Es ist einfach, Zeichenfolgen und Aufrufe zu duplizieren.

Anstatt alles hart zu codieren, würden Sie wahrscheinlich einen benutzerdefinierten Helfer namens log() definieren und ihn überall in Ihrem Projekt verwenden.

Dies würde darauf abzielen, den Code trocken zu halten, erlaubt jedoch in bestimmten Fällen möglicherweise nicht das Komponieren komplexerer Funktionen.

Der funktionale Ansatz würde nicht darin bestehen, einen solchen globalen Helfer zu verwenden. Stattdessen würde es lieber eine Monade implementieren, um andere Funktionen zu umschließen:

final class LoggerMonad {
    public function __construct(
        public mixed $data,
        public array $logs = [],
    ) {}

    public function bind(callable $fn) {
         $resultLoggerMonad = $fn($this->data);
         return new LoggerMonad(
             $resultLoggerMonad->data,
             [...$this->logs, ...$resultLoggerMonad->logs],
         );
   }
}

function loggify(callable $fn): Closure {
    return function ($value) use ($fn) {
        $name = (new ReflectionFunction($fn))->name;
        $log = [
            'Running '. $name .'('. var_export($value, true) .')'
        ];
        return new LoggerMonad($fn($value), $log);
    };
}
Nach dem Login kopieren
Nach dem Login kopieren

Dann können Sie den Loggify-Wrapper folgendermaßen verwenden:

function add2(int $v): int {
    return $v + 2;
}

function square(int $v): int {
    return $v * $v;
}

function multi3(int $v): int {
    return $v * 3;
}

function logIt($value, callable ...$fns) {
    $logging_fns = array_map(loggify(...), $fns);
    $monad = new LoggerMonad($value);
    foreach ($logging_fns as $fn) {
        $monad = $monad->bind($fn);
    }
    return $monad;
}

print_r(logIt(
   3,
   add2(...),
   square(...),
   multi3(...)
));
Nach dem Login kopieren

Quelle: „Monades simplement“ von Gina Banyard (fr)

Was ist binden?

?? Baby, tu mir nicht weh

Monaden sollen Werte umschließen, die jeden Typs haben können, einschließlich Objekte und Funktionen.

Wie in jedem anderen Wrapping-System finden Sie einen Konstruktor (~ Klasse), der diesen Wert als Eingabe verwendet, und einige Methoden, die je nach dem Muster, das Sie implementieren möchten, ihre eigenen Zwecke haben.

Allerdings verfügen alle Monaden über eine Bind-Funktion. Wie der Name schon sagt, werden hier die Werte (oder Callbacks) übergeben.

Was auch immer in diesen Rückrufen passiert, die Monade wird es umschließen, was eine leistungsstarke Möglichkeit zu sein scheint, Werte zu dekorieren und den Code umzugestalten.

Ist der Code besser lesbar?

Es kommt ganz klar auf die Umsetzung an, und am Anfang kann man leicht den Überblick verlieren.

Dieser alternative Ansatz kann jedoch die Anzahl der if-Blöcke erheblich reduzieren und die Rückgabewerte konsistenter machen:

final class LoggerMonad {
    public function __construct(
        public mixed $data,
        public array $logs = [],
    ) {}

    public function bind(callable $fn) {
         $resultLoggerMonad = $fn($this->data);
         return new LoggerMonad(
             $resultLoggerMonad->data,
             [...$this->logs, ...$resultLoggerMonad->logs],
         );
   }
}

function loggify(callable $fn): Closure {
    return function ($value) use ($fn) {
        $name = (new ReflectionFunction($fn))->name;
        $log = [
            'Running '. $name .'('. var_export($value, true) .')'
        ];
        return new LoggerMonad($fn($value), $log);
    };
}
Nach dem Login kopieren
Nach dem Login kopieren

Quelle: fp4php – Monaden

Vor- und Nachteile

Vorteile

  • ✅ Es gibt verschiedene Monaden für unterschiedliche Zwecke: Vielleicht, Entweder, Logger, Liste, Leser usw.
  • ✅ Monaden ermöglichen das Umschließen von Code mit besseren Typen, was die statische Analyse verbessern kann
  • ✅ PHP stellt dafür keine integrierten Konstrukte zur Verfügung, daher liegt die Implementierung vollständig beim Entwickler

Nachteile

  • ❌ PHP stellt hierfür keine integrierten Strukturen (z. B. Generics) bereit, daher liegt die Implementierung vollständig beim Entwickler
  • ❌ Der Code wird dadurch nicht vereinfacht

Weiter gehen

  • Funktionale Fehlerbehandlung mit Monaden, Monadentransformatoren und Cats MTL
  • Monaden und Verwendung in PHP
  • Funktionale Programmierung in PHP

Einpacken

Hoffentlich wissen Sie jetzt etwas mehr über PHP-Monaden.

Natürlich sollten Sie Ihrem Projekt nicht nur so ausgefallene Designmuster hinzufügen.

Außerdem verfehlt man leicht den Kernpunkt und konzentriert sich auf sehr spezifische Aspekte, wie etwa die Fehlerbehandlung, obwohl es sich um ein völlig neues Paradigma handelt.

Dennoch ist es erfrischend, neue Ansätze zu entdecken. Wir müssen über den Tellerrand hinausdenken.

Das obige ist der detaillierte Inhalt vonPHP: Monaden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!