Dieser Beitrag ist stark vom Tech-Talk von Gina Banyard beim „FORUM PHP 2024“ inspiriert:
Beginnen wir mit ein paar Synonymen:
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.
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:
Monaden können optionale (oder noch nicht verfügbare) Werte konsistenter verarbeiten.
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.
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); }; }
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(...) ));
Quelle: „Monades simplement“ von Gina Banyard (fr)
?? 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.
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); }; }
Quelle: fp4php – Monaden
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!