


PHP Master | Le motif d'objet nulle - le polymorphisme dans les modèles de domaine
Points de base
- Le motif d'objet vide est un motif de conception qui utilise le polymorphisme pour réduire le code conditionnel, ce qui rend le code plus concis et plus facile à entretenir. Il fournit un objet non fonctionnel qui peut remplacer l'objet réel, éliminant ainsi le besoin de vérifications de valeur nulle.
- Le mode objet vide peut être utilisé en conjonction avec d'autres modes de conception, tels que le mode d'usine créant et renvoyant des objets vides, ou le mode politique modifiant le comportement d'un objet à l'exécution.
- L'inconvénient potentiel du motif d'objet vide est qu'il peut conduire à la création d'objets inutiles et augmenter l'utilisation de la mémoire. Il peut également rendre le code plus compliqué car des classes et des interfaces supplémentaires sont nécessaires.
- L'implémentation du modèle d'objet vide nécessite la création d'une classe d'objets vide qui implémente la même interface que l'objet réel. Cet objet vide fournit une implémentation par défaut pour toutes les méthodes de l'interface, ce qui lui permet de remplacer l'objet réel. Cela rend le code plus robuste et moins sujet aux erreurs.
Bien qu'il ne se conforme pas pleinement aux spécifications, on peut dire que l'orthogonalité est l'essence d'un système logiciel basé sur le principe de "bonne conception", dans laquelle les modules sont découplés les uns des autres, ce qui rend le système moins sujet à des problèmes rigides et fragiles. Bien sûr, il est plus facile de parler des avantages des systèmes orthogonaux que de gérer réellement les systèmes de production; ce processus est généralement une poursuite de l'utopie. Même ainsi, il n'est en aucun cas un concept utopique pour atteindre des composants très découplés dans un système. Divers concepts de programmation tels que le polymorphisme permettent la conception de programmes flexibles, dont les pièces peuvent être commutées au moment de l'exécution, et leurs dépendances peuvent être exprimées sous des formes abstraites plutôt que des implémentations concrètes. Je dirais que l'ancienne devise de la «programmation axée sur l'interface» a été largement adoptée au fil du temps, que nous implémentions une infrastructure ou une logique d'application. Cependant, lorsque vous entrez dans le domaine des modèles de domaine, la situation est très différente. Franchement, c'est un scénario prévisible. Après tout, pourquoi un réseau d'objets interdépendants (qui ont des données et des comportements devraient-ils être limitées par des règles métier bien définies) être polymorphes? Cela n'a pas beaucoup de sens en soi. Cependant, il y a quelques exceptions à cette règle, qui peuvent éventuellement s'appliquer à cette situation. La première exception est l'utilisation d'un proxy virtuel, qui est effectivement la même interface que l'objet de domaine réel implémente. Une autre exception est le soi-disant «cas nul», qui est un cas spécial où une opération peut finir par attribuer ou renvoyer des valeurs nuls au lieu de remplir une entité bien remplie. Dans les approches traditionnelles non polymorphes, l'utilisateur du modèle doit vérifier ces valeurs nulles "nuisibles" et gérer gracieusement la condition, entraînant une explosion d'instructions conditionnelles tout au long du code. Heureusement, cette situation apparemment déroutante est facilement résolu en créant simplement une implémentation multi-branchage de l'objet de domaine qui implémentera la même interface que l'objet en question, sauf que sa méthode ne fait rien, donc le client sera le code est libéré de Vérifiez à plusieurs reprises les valeurs nulles laides lors de l'exécution d'une opération. Sans surprise, cette approche est un modèle de conception appelé objets vides qui apportent les avantages du polymorphisme à l'extrême. Dans cet article, je vais démontrer les avantages de ce modèle dans plusieurs cas et vous montrer comment ils sont étroitement attachés aux méthodes polymorphes.
Traiter les conditions non polymorphes
Comme on pourrait s'y attendre, il existe plusieurs façons d'essayer lors de la montre les avantages des modèles d'objets vides. Une approche particulièrement simple que j'ai trouvée consiste à implémenter un mappeur de données qui peut finir par renvoyer des valeurs nulles d'un chercheur à usage général. Supposons que nous ayons créé avec succès un modèle de domaine squelette qui se compose d'une seule entité utilisateur. L'interface et sa classe sont les suivantes:
<?php namespace Model; interface UserInterface { public function setId($id); public function getId(); public function setName($name); public function getName(); public function setEmail($email); public function getEmail(); }
<?php namespace Model; class User implements UserInterface { private $id; private $name; private $email; public function __construct($name, $email) { $this->setName($name); $this->setEmail($email); } public function setId($id) { if ($this->id !== null) { throw new BadMethodCallException( "The ID for this user has been set already."); } if (!is_int($id) || $id throw new InvalidArgumentException( "The ID for this user is invalid."); } $this->id = $id; return $this; } public function getId() { return $this->id; } public function setName($name) { if (strlen($name) 30) { throw new InvalidArgumentException( "The user name is invalid."); } $this->name = $name; return $this; } public function getName() { return $this->name; } public function setEmail($email) { if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { throw new InvalidArgumentException( "The user email is invalid."); } $this->email = $email; return $this; } public function getEmail() { return $this->email; } }
La classe utilisateur est une structure réactive qui implémente certains mutateurs / accessoires pour définir certaines données et comportements utilisateur. Avec cette classe de domaine construite, nous pouvons maintenant aller plus loin et définir un mappeur de données de base qui isole notre modèle de domaine et notre couche d'accès aux données les uns des autres.
<?php namespace ModelMapper; use LibraryDatabaseDatabaseAdapterInterface, ModelUser; class UserMapper implements UserMapperInterface { private $adapter; public function __construct(DatabaseAdapterInterface $adapter) { $this->adapter = $adapter; } public function fetchById($id) { $this->adapter->select("users", array("id" => $id)); if (!$row = $this->adapter->fetch()) { return null; } return $this->createUser($row); } private function createUser(array $row) { $user = new User($row["name"], $row["email"]); $user->setId($row["id"]); return $user; } }
La première chose qui devrait apparaître est que la méthode FetchById () du mappeur est une coquine dans le bloc, car elle renvoie efficacement NULL lorsqu'aucun utilisateur dans la base de données correspond à l'ID donné. Pour des raisons évidentes, cette condition maladroite fait que le code client doit travailler dur pour vérifier la valeur nulle à chaque fois qu'il appelle le chercheur du mappeur.
<?php use LibraryLoaderAutoloader, LibraryDatabasePdoAdapter, ModelMapperUserMapper; require_once __DIR__ . "/Library/Loader/Autoloader.php"; $autoloader = new Autoloader; $autoloader->register(); $adapter = new PdoAdapter("mysql:dbname=test", "myusername", "mypassword"); $userMapper = new UserMapper($adapter); $user = $userMapper->fetchById(1); if ($user !== null) { echo $user->getName() . " " . $user->getEmail(); }
À première vue, il n'y aura pas de problème, vérifiez-le simplement en un seul endroit. Mais si la même ligne apparaît dans plusieurs contrôleurs de pages ou couches de service, allez-vous tomber sur un mur de briques? Avant de vous en rendre compte, le null apparemment innocent rendu par le mappeur produira beaucoup de conditions répétitives, ce qui est un mauvais présage de mauvaise conception.
Supprimer les instructions de condition du code client
Cependant, il n'est pas nécessaire de s'inquiéter, car c'est exactement le cas où le modèle d'objet vide montre pourquoi le polymorphisme est une aubaine. Si nous voulons nous débarrasser de ces instructions conditionnelles ennuyeuses une fois pour toutes, nous pouvons implémenter la version polymorphe de la classe utilisateur précédente.
<?php namespace Model; class NullUser implements UserInterface { public function setId($id) { } public function getId() { } public function setName($name) { } public function getName() { } public function setEmail($email) { } public function getEmail() { } }
Si vous vous attendez à ce qu'une classe d'entité complète emballe toutes sortes de décorations, vous êtes probablement très déçu. La version "NULL" de l'entité est conforme à l'interface correspondante, mais la méthode est un wrapper vide et il n'y a pas d'implémentation réelle. Bien que l'existence de la classe Nulluser ne nous apporte évidemment rien qui mérite des éloges, c'est une structure concise qui nous permet de jeter toutes les déclarations conditionnelles précédentes dans la poubelle. Vous voulez voir comment il est mis en œuvre? Tout d'abord, nous devons faire du pré-travail et reconstruire le mappeur de données afin que son chercheur renvoie un objet utilisateur vide au lieu d'une valeur vide.
<?php namespace ModelMapper; use LibraryDatabaseDatabaseAdapterInterface, ModelUser, ModelNullUser; class UserMapper implements UserMapperInterface { private $adapter; public function __construct(DatabaseAdapterInterface $adapter) { $this->adapter = $adapter; } public function fetchById($id) { $this->adapter->select("users", array("id" => $id)); return $this->createUser($this->adapter->fetch()); } private function createUser($row) { if (!$row) { return new NullUser; } $user = new User($row["name"], $row["email"]); $user->setId($row["id"]); return $user; } }La méthode CreateUser () du Mapper masque une minuscule condition car elle est désormais responsable de la création d'un utilisateur vide lorsque l'ID transmis au Finder ne renvoie pas un utilisateur valide. Même ainsi, ce coût nuancé économise non seulement le travail du code client faisant de nombreuses vérifications répétées, mais le transforme également en un consommateur lâche qui ne se plaindra pas lorsqu'il doit faire face aux utilisateurs vides.
<?php namespace Model; interface UserInterface { public function setId($id); public function getId(); public function setName($name); public function getName(); public function setEmail($email); public function getEmail(); }
Le principal inconvénient de cette approche polymorphe est que toute application qui l'utilise deviendra trop lâche car elle ne se bloque jamais lorsqu'elle traite des entités non valides. Dans le pire des cas, l'interface utilisateur ne montrera que des lignes vierges, mais rien de vraiment bruyant nous rend dégoûtés. Cela est particulièrement évident lors de la numérisation de l'implémentation actuelle de la classe nulsser précoce. Même s'il est possible, sans parler de celui recommandé, il peut également encapsuler la logique dans des objets vides tout en gardant son polymorphisme inchangé. Je peux même dire que les objets vides sont parfaits pour encapsuler des données et des comportements par défaut qui ne devraient être exposés au code client que dans quelques cas spéciaux. Si vous êtes assez ambitieux et que vous souhaitez essayer ce concept avec un simple objet utilisateur vide, la classe Nulluser actuelle peut être refactorisée comme suit:
<?php namespace Model; class User implements UserInterface { private $id; private $name; private $email; public function __construct($name, $email) { $this->setName($name); $this->setEmail($email); } public function setId($id) { if ($this->id !== null) { throw new BadMethodCallException( "The ID for this user has been set already."); } if (!is_int($id) || $id throw new InvalidArgumentException( "The ID for this user is invalid."); } $this->id = $id; return $this; } public function getId() { return $this->id; } public function setName($name) { if (strlen($name) 30) { throw new InvalidArgumentException( "The user name is invalid."); } $this->name = $name; return $this; } public function getName() { return $this->name; } public function setEmail($email) { if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { throw new InvalidArgumentException( "The user email is invalid."); } $this->email = $email; return $this; } public function getEmail() { return $this->email; } }
La version améliorée de Nulluser est légèrement plus expressive que son prédécesseur silencieux, car son Getter fournit quelques implémentations de base pour renvoyer certains messages par défaut lors de la demande d'un utilisateur non valide. Bien que Trivial, ce changement a un impact positif sur la façon dont le code client gère les utilisateurs vides, car les utilisateurs savent au moins que certains problèmes surviennent lorsqu'ils essaient d'extraire les utilisateurs inexistants du stockage. Il s'agit d'une bonne percée, non seulement montrant comment implémenter des objets vides qui ne sont pas du tout vides, mais aussi à quel point il est facile de déplacer la logique à l'intérieur d'objets pertinents en fonction de besoins spécifiques.
Conclusion
Certains pourraient dire que la mise en œuvre d'objets vides est gênante, en particulier en PHP, où les concepts de base de la POO (comme le polymorphisme) sont considérablement sous-estimés. Ils ont raison dans une certaine mesure. Néanmoins, l'adoption progressive des principes de programmation et des modèles de conception dignes de confiance, ainsi que le niveau de maturité que le modèle d'objet linguistique a atteint, est d'aller de l'avant et de commencer à utiliser certains des «produits de luxe» qui étaient considérés comme des notions complexes et irréalistes Il n'y a pas longtemps, fournit toutes les bases nécessaires. Le modèle d'objet NULL entre dans cette catégorie, mais son implémentation est si simple et élégante qu'il est difficile de ne pas le trouver attrayant lors de l'effacement des vérifications nulles en double dans le code client. images de Fotolia
(En raison des limitations de l'espace, la partie FAQ du texte d'origine est omise ici.)
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undress AI Tool
Images de déshabillage gratuites

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

La clé pour rédiger des commentaires PHP est de clarifier l'objectif et les spécifications. Les commentaires devraient expliquer "pourquoi" plutôt que "ce qui a été fait", en évitant la redondance ou trop de simplicité. 1. Utilisez un format unifié, tel que DocBlock (/ * /) pour les descriptions de classe et de méthode afin d'améliorer la lisibilité et la compatibilité des outils; 2. Soulignez les raisons de la logique, telles que pourquoi les sauts JS doivent être sortis manuellement; 3. Ajoutez une description d'une vue d'ensemble avant le code complexe, décrivez le processus dans les étapes et aidez à comprendre l'idée globale; 4. Utilisez TODO et FIXME Rationalement pour marquer des éléments et des problèmes de tâches pour faciliter le suivi et la collaboration ultérieurs. De bonnes annotations peuvent réduire les coûts de communication et améliorer l'efficacité de la maintenance du code.

Il existe trois méthodes courantes pour le code de commentaire PHP: 1. Utiliser // ou # pour bloquer une ligne de code, et il est recommandé d'utiliser //; 2. Utiliser /.../ pour envelopper des blocs de code avec plusieurs lignes, qui ne peuvent pas être imbriquées mais peuvent être croisées; 3. Compétences combinées Commentaires tels que l'utilisation / if () {} / pour contrôler les blocs logiques, ou pour améliorer l'efficacité avec les touches de raccourci de l'éditeur, vous devez prêter attention aux symboles de fermeture et éviter les nidification lorsque vous les utilisez.

Toinstallphpquickly, usexAmpPonWindowsorHomebrewonMacos.1.onwindows, downloadAndInstallxAmppp, selectComponents, startapache et placefilesInhtdocs.2.

Toléarnphpeffective, startBySettingUpAlocalServerERironmentUsingToolsLILYXAMPPANDACODEDITERLIGHILLEVSCODE.1) INSTRUSITIONXAMPFORAPACHE, MYSQL, ANDPHP.2) USACODEDEDITORFORSYNTAXSUPPORT.3)

L'entrée vocale de l'utilisateur est capturée et envoyée au backend PHP via l'API MediaRecorder du JavaScript frontal; 2. PHP enregistre l'audio en tant que fichier temporaire et appelle STTAPI (tel que Google ou Baidu Voice Recognition) pour le convertir en texte; 3. PHP envoie le texte à un service d'IA (comme Openaigpt) pour obtenir une réponse intelligente; 4. PHP appelle ensuite TTSAPI (comme Baidu ou Google Voice Synthesis) pour convertir la réponse en fichier vocal; 5. PHP diffuse le fichier vocal vers l'avant pour jouer, terminant l'interaction. L'ensemble du processus est dominé par PHP pour assurer une connexion transparente entre toutes les liens.

Pour réaliser la correction d'erreur de texte et l'optimisation de la syntaxe avec l'IA, vous devez suivre les étapes suivantes: 1. Sélectionnez un modèle ou une API d'IA appropriée, tels que Baidu, Tencent API ou bibliothèque NLP open source; 2. Appelez l'API via Curl ou Guzzle de PHP et traitez les résultats de retour; 3. Afficher les informations de correction d'erreur dans l'application et permettre aux utilisateurs de choisir d'adopter l'adoption; 4. Utilisez PHP-L et PHP_CODESNIFFER pour la détection de syntaxe et l'optimisation du code; 5. Collectez en continu les commentaires et mettez à jour le modèle ou les règles pour améliorer l'effet. Lorsque vous choisissez AIAPI, concentrez-vous sur l'évaluation de la précision, de la vitesse de réponse, du prix et du support pour PHP. L'optimisation du code doit suivre les spécifications du PSR, utiliser le cache raisonnablement, éviter les requêtes circulaires, revoir le code régulièrement et utiliser x

La méthode principale de création de fonctions de partage social dans PHP est de générer dynamiquement des liens de partage qui répondent aux exigences de chaque plate-forme. 1. Obtenez d'abord la page actuelle ou les informations d'URL et d'article spécifiées; 2. Utilisez UrLencode pour coder les paramètres; 3. Épisser et générer des liens de partage en fonction des protocoles de chaque plate-forme; 4. Afficher les liens sur l'avant pour que les utilisateurs puissent cliquer et partager; 5. Générez dynamiquement des balises OG sur la page pour optimiser l'affichage du contenu du partage; 6. Assurez-vous d'échapper à la saisie des utilisateurs pour empêcher les attaques XSS. Cette méthode ne nécessite pas d'authentification complexe, a de faibles coûts de maintenance et convient à la plupart des besoins de partage de contenu.

1. La maximisation de la valeur commerciale du système de commentaires nécessite de combiner la livraison précise de la publicité native, les services à valeur ajoutée par l'utilisateur (tels que le téléchargement d'images, les commentaires de recharge), d'influencer le mécanisme d'incitation basé sur la qualité des commentaires et la conformité de la monétisation anonyme des données de données; 2. La stratégie d'audit doit adopter une combinaison de mécanismes de filtrage des mots clés dynamiques pré-audit et de signalement des utilisateurs, complétés par une note de qualité des commentaires pour réaliser une exposition hiérarchique de contenu; 3. Anti-brosses nécessite la construction d'une défense multicouche: la vérification sans capteur RecaptChav3, le robot de reconnaissance de champ de miel, IP et la limite de fréquence d'horodatage empêchent l'arrosage, et la reconnaissance du modèle de contenu marque les commentaires suspects et itéra en continu pour traiter les attaques.
