Partie 2 – WordPress et la programmation orientée objet : un exemple concret

Publié: 2021-07-29

Dans notre aperçu de WordPress et de la programmation orientée objet, nous avons passé en revue la théorie de la programmation orientée objet (POO) et à quoi s'attendre lors de son utilisation.

Avant de passer à des exemples de codage plus spécifiques utilisant la POO, dans cet article, nous essaierons d'expliquer comment un scénario du monde réel peut être abordé avec l'état d'esprit différent requis pour la POO et comment cela est analysé à l'aide d'objets et de classes.

Un scénario réel : envoyer un SMS

Il s'agit plutôt d'un scénario de vie « passée », car les SMS sont de moins en moins utilisés de nos jours, mais comme vous le verrez, il y a une raison pour laquelle nous utilisons cela comme exemple !

Supposons que vous ayez un appareil mobile et que vous souhaitiez envoyer un SMS à l'un de vos contacts. En gardant l'exemple aussi simple que possible, la séquence d'actions serait :

  1. Préparez le message
  2. Sélectionnez l'un de vos contacts et ajoutez-le en tant que destinataire
  3. Envoyez le message

Essayons donc de visualiser les étapes que vous suivrez pour envoyer votre message :

Nous avons ajouté des descriptions plus détaillées des actions, mais plus ou moins tout ce que vous faites est de 3 étapes de base. Vous préparez le message dans l'éditeur d'appareil, vous sélectionnez le destinataire parmi vos contacts, puis vous envoyez le message. Et vous avez terminé ! Votre message est maintenant envoyé.

Maintenant, si nous devions représenter en code une application qui envoie un message SMS, nous devrions analyser quelle route est préférable de suivre ; l'approche procédurale ou OOP.

L'application avec une approche procédurale

Si vous êtes un développeur de plugins WordPress, vous êtes probablement familiarisé avec la programmation procédurale .

Comme nous l'avons décrit précédemment, la programmation procédurale est un type de programmation impérative, où nos programmes consistent en une ou plusieurs procédures. Ainsi, en tant que développeur, vous décomposez votre plugin en un ensemble de variables qui contiennent vos données et de fonctions qui fonctionnent sur les données.

Dans notre exemple ci-dessus avec le message SMS, vous effectueriez une série d'actions qui conduiraient au résultat souhaité. Comme vous l'avez peut-être déjà deviné, vous auriez, par exemple, une variable qui contient le contenu textuel du message, une fonction avec un paramètre $contact qui renvoie le numéro de téléphone et enfin, une fonction qui envoie le message. Dans le code, cela ressemblerait à ceci :

 function get_phone_number( $contact ) { // Code that finds the contact's number in the list of contacts return $phone_number; } function send_sms( $contact, $message ) { $phone_number = get_phone_number( $contact ); // Code that sends the message to this number print "Message Sent!"; }

Et vous l'utiliseriez comme ceci :

 $text = "Hello John"; function send_message( "John Doe", $text );

Ainsi, vous effectuerez une série de tâches qui vous mèneront au résultat souhaité.

Dans cet exemple très simple bien sûr, qui a des exigences limitées et très spécifiques, il n'y a aucune raison d'envisager d'utiliser la POO. La programmation procédurale est plus que suffisante pour atteindre votre objectif. Mais, si vous pensez à certains scénarios sur la façon dont cette application pourrait se développer à l'avenir, vous pourriez vous rendre compte qu'à long terme, vous pourriez avoir des problèmes en termes d'évolutivité. Nous allons essayer d'expliquer pourquoi ci-dessous.

Élargir l'application avec une approche procédurale

Disons que vous souhaitez améliorer cette application et offrir la possibilité d'envoyer également d'autres types de messages, comme un e-mail par exemple. La fonction qui délivre le message serait différente dans chaque cas.

Lorsque vous envoyez un e-mail, vous avez besoin de l'adresse e-mail du contact, pas du numéro de téléphone. En dehors de cela, nous devrons ajouter un paramètre dans la fonction finale send_message() qui correspondra au type de technologie que nous utilisons ; e-mail ou SMS.

Le code correspondant pourrait ressembler à ceci :

 function get_phone_number( $contact ) { // Code that finds the contact's number return $phone_number; } function get_email_address( $contact ) { // Code that finds the contact's email address return $email_address; } function send_sms( $contact, $message ) { $phone_number = get_phone_number( $contact ); // Code that sends the message to this number print "SMS Sent!"; } function send_email( $contact, $message ) { $email_address = get_email_address( $contact ); // Code that sends the email to this number print "Email Sent!"; } function send_message( $contact, $message, $technology ) { if ( $technology == "SMS") { send_sms( $phone_number, $message ); } else if ( $technology == "Email") { send_email( $email_address, $message ); } }

Donc, ce n'est pas comme si cela ne pouvait pas être mis en œuvre avec une approche procédurale. Mais si vous êtes un développeur expérimenté, vous avez probablement déjà compris comment cela pourrait devenir désordonné à l'avenir.

Les inconvénients d'une approche procédurale

Et si nous avions plusieurs types de messages ? Les instructions if deviendraient agaçantes. Et, plus important encore, que se passerait-il si vous aviez des fonctions qui utilisent la fonction send_message() ? Dans ce cas, vous devrez également ajouter le paramètre $technology dans toutes ces fonctions.

Au fur et à mesure que votre code grandit, les fonctions seront partout, ce qui signifie que vous commencerez à copier/coller des morceaux de code (jamais souhaitable), et apporter une petite modification à une fonction pourrait casser plusieurs autres fonctions. Nous y avons tous été. Vous voudriez éviter cela et être en mesure d'ajouter facilement des fonctionnalités à votre code sans trop interférer dans la structure.

Hébergez votre site web avec Pressidium

GARANTIE DE REMBOURSEMENT DE 60 JOURS

VOIR NOS FORFAITS

La programmation orientée objet (ou POO) est un paradigme de programmation qui tente de résoudre ce problème en nous permettant de structurer notre plugin en petits morceaux de code réutilisables, appelés classes . Comme nous l'avons décrit dans notre article Présentation de la POO, une classe est essentiellement un modèle que nous utilisons pour créer des instances individuelles de la classe, appelées objects .

Un objet contient des données et du code. Nous avons toujours des variables qui peuvent stocker des informations, appelées properties . Et les procédures qui opèrent sur les données, appelées méthodes .

L'application avec une approche POO

Analysons maintenant le même scénario que ci-dessus avec une approche POO.

Tout d'abord, nous définirons quels objets nous avons ici, quelles caractéristiques chacun a et quelles actions ils effectuent. Les caractéristiques sont ce que seront plus tard nos propriétés et les actions seront nos fonctions ou méthodes comme on les appelle en POO.

Réfléchissons à ce que nous avons dans le premier scénario d'envoi d'un SMS de la manière la plus simple possible. Il existe un appareil doté d'une interface que nous utilisons pour envoyer le message SMS. On a le contenu du message, on choisit un contact comme destinataire et enfin le message.

 <?php /** * Plugin Name: Send Message */ interface MessagingCapable { public function send_message( $contact, $message ); } class Phone implements MessagingCapable { public function send_message( $contact, $message ) { print "You sent" . $message ; } } function say_hi( MessagingCapable $device, $contact, $message ) { $device->send_message( $contact, $message ); }

Nous déclarons la classe Phone qui implémente l'interface MessagingCapable . Nous devons donc implémenter toutes les méthodes qui y sont déclarées. La fonction say_hi() requiert 3 paramètres :

  1. Un appareil qui prend en charge la messagerie
  2. Un contact
  3. Le message

Afin d'envoyer réellement un message, nous utilisons cette fonction comme ceci :

 $phone = new Phone(); say_hi( $phone, "John Doe", "Hello John" );

Nous créons essentiellement un objet en instanciant la classe Phone et en transmettant le contenu du contact et du message. Cela produirait:

 You sent "Hello John"

Nous avons démontré ce scénario simple d'envoi d'un message texte en utilisant des classes. Dans la section suivante, nous verrons comment nous pouvons étendre les capacités de l'application en suivant l'approche OOP et lors de la mise à l'échelle, nous examinerons où les fonctionnalités OOP jouent leur rôle ainsi que les avantages de l'utilisation de cette technique.

Extension de l'application avec l'approche OOP

Ajoutons également la possibilité d'envoyer des e-mails, comme nous l'avons fait auparavant de manière procédurale.

Quel que soit l'appareil, nous voudrions idéalement utiliser la fonction say_hi() de la même manière. Jetez un oeil au code ci-dessous:

 <?php /** * Plugin Name: Send Message */ interface MessagingCapable { public function send_message( $contact, $message ); } class Phone implements MessagingCapable { public function send_message( $contact, $message ) { print ('You sent a "' . $message . '" SMS to ' . $contact ); } } class Computer implements MessagingCapable { public function send_message( $contact, $message ) { print ('You sent a "' . $message . '" email to ' . $contact ); } } function say_hi( MessagingCapable $device, $contact, $message ) { $device->send_message( $contact, $message ); }

Lorsque nous utilisons ce morceau de code, nous prenons l'appareil mobile pour envoyer un SMS et l'ordinateur pour envoyer un e-mail. Nous ferions soit :

 say_hi ( new Phone(), "John Doe", "Hello John" );

ou:

 say_hi ( new Computer(), "John Doe", "Hello John" );

qui produirait You sent a "Hello John" SMS to John Doe et You sent a "Hello John" email to John Doe conséquence.

Ici, nous commençons déjà à détecter certaines fonctionnalités OOP. Nous avons introduit des interfaces en utilisant l'interface MessagingCapable .

Une interface déclare un ensemble de méthodes qui doivent être implémentées par la classe sans définir comment ces méthodes sont implémentées. Toutes les méthodes déclarées dans une interface doivent être publiques.

PHP ne prend pas en charge l'héritage multiple, ce qui signifie qu'une classe ne peut pas hériter des propriétés/méthodes de plusieurs classes parentes.

Bien qu'il ne puisse étendre qu'une seule classe, il peut implémenter plusieurs interfaces.

L'utilisation d'un téléphone pour envoyer un message sera différente de l'utilisation d'un ordinateur. Les instances de différentes classes agissent différemment lorsqu'on leur demande d'effectuer la même action (c'est-à-dire send_message() ). Ceci est un exemple de polymorphisme. Si nous créons ultérieurement un nouvel appareil, nous n'aurons pas besoin de modifier notre code pour l'adapter, tant qu'ils partagent tous la même interface.

Nous voudrions également souligner ici que nous voyons déjà la différence de lisibilité également. La façon dont nous utilisons finalement ce script en codant simplement :

 say_hi( new Computer(), "John", "Hi" );

C'est totalement simple pour tout développeur qui travaille sur le projet. Et bien sûr, plus le plugin est complexe, plus il devient évident à quel point cela est utile, surtout lorsque vous travaillez en équipe.

Pour essayer de mieux expliquer à quel point il est facile d'étendre votre plugin dans la programmation orientée objet, essayons d'ajouter quelques fonctionnalités supplémentaires.

Ajouter plus de fonctionnalités

Si nous voulons ajouter la possibilité de naviguer sur Internet, nous ajouterons simplement une interface supplémentaire pour tout appareil qui pourrait répondre à cette capacité, comme un ordinateur par exemple.

 interface InternetBrowsingCapable { public function visit_website( $url ); }

L'implémentation de cette interface sera codée comme ceci :

 class Computer implements MessagingCapable, InternetBrowsingCapable { public function send_message( $contact, $message ) { print ('You sent a "' . $message . '" email to ' . $contact ); } public function visit_website( $url ) { print ('You visited "' . $url ); } }

Ainsi, dans la classe Computer actuelle, nous venons d'ajouter l'interface supplémentaire à implémenter, puisqu'un ordinateur peut envoyer un message et naviguer sur Internet, et la visit_website( $url ) .

REMARQUE : Bien sûr, puisque la visite d'une URL n'a aucun rapport avec la fonction say_hi() , nous allons également introduire une nouvelle fonction, quelque chose comme :

 function visit_url( InternetBrowsingCapable $device, $url ) { $device->visit_website( $url ); }

Et c'est tout! Pour tout appareil pouvant visiter une URL, nous pouvons utiliser cette fonction comme nous l'avons fait avec un ordinateur. Vous ne craignez pas de casser le reste des fonctionnalités. Cela montre l'évolutivité disponible lors de l'utilisation de la POO par rapport à la programmation procédurale.

Ajoutons un smartphone juste pour démontrer quelques fonctionnalités supplémentaires. Voici le code complet, avec l'ajout de la classe smartphone pour que vous puissiez avoir une meilleure idée de ce qui se passe :

 <?php /* * Plugin Name: Communication Plugin */ interface MessagingCapable { public function send_message( $contact, $message ); } interface InternetBrowsingCapable { public function visit_website( $url ); } class Phone implements MessagingCapable { public function send_message( $contact, $message ) { print 'You sent a "' . $message . '" SMS to ' . $contact; } } class Computer implements MessagingCapable, InternetBrowsingCapable { public function send_message( $contact, $message ) { print 'You sent a "' . $message . '" email to ' . $contact; } public function visit_website( $url ) { print 'You visited "' . $url; } } class Smartphone extends Phone implements InternetBrowsingCapable { public function visit_website( $url ) { print 'You visited "' . $url; } public function send_message( $contact, $message ) { parent::send_message( $contact, $message ); print ' from your smartphone'; } } function say_hi( MessagingCapable $device, $contact, $message ) { $device->send_message( $contact, $message ); } function visit_url( InternetBrowsingCapable $device, $url ) { $device->visit_website( $url ); }

La classe Smartphone étend la classe parent Phone et implémente l'interface InternetBrowsingCapable . Cela signifie qu'il peut envoyer un message et visiter une URL. Ici, nous détectons la fonctionnalité Héritage. En d'autres termes, nous avons une hiérarchie de classes, une classe mère (Téléphone) et une sous-classe (Smartphone).

Ainsi, un objet Smartphone hérite de toutes les propriétés et comportements de la classe parent Phone. De cette façon, à l'intérieur de la classe enfant, nous pouvons ajouter une méthode ou remplacer une méthode de la classe parent, comme nous l'avons fait avec le send_message() dans la classe Smartphone. Nous avons fait cela pour changer la sortie. Nous pourrions totalement ignorer cette méthode et utiliser le send_message() de la classe parente telle quelle.

Vous pouvez essayer le code vous-même en le collant dans le bloc de code de cet excellent outil en ligne PHP. Sous le code, essayez l'une de ces lignes de code et voyez les différents résultats.

 say_hi ( new Phone(), "John Doe", "Hello John" ); say_hi ( new Computer(), "John Doe", "Hello John" ); say_hi ( new Smartphone(), "John Doe", "Hello John" ); visit_url ( new Smartphone(), "https://www.pressidium.com" ); visit_url ( new Computer(), "https://www.pressidium.com" );

Pour une compréhension encore meilleure de l'ensemble du concept, jetez un œil au diagramme de classes du code ci-dessus.

Comme illustré ci-dessus, lors de la conception des relations entre les classes, nous n'incluons pas les éléments communs dans la classe enfant. De plus, n'oubliez pas de prêter attention au guide de gauche pour identifier les relations et la visibilité de leurs propriétés et méthodes.

Si vous souhaitez également voir la fonctionnalité d'encapsulation en action, essayez d'inclure une classe Contact dans l'un des exemples de scripts ci-dessus que nous avons fournis. La classe ressemblerait à ceci :

 class Contact { private $name; private $phone_number; private $email_address; public function __construct( $name, $phone_number, $email_address ) { $this->name = $name; $this->phone_number = $phone_number; $this->email_address = $email_address; } public function get_name() { return $this->name; } public function get_phone_number() { return $this->phone_number; } public function get_email_address() { return $this->email_address; } }

La méthode __construct() , de par sa conception, est appelée automatiquement lors de la création d'un objet. Désormais, lorsque nous instancions la classe Contact, son constructeur est appelé et définit les valeurs de ses propriétés privées. Ensuite, nous utilisons nos "getters" qui sont les méthodes publiques get_name() , get_phone_number() et get_email_address() pour récupérer ces valeurs.

L'encapsulation regroupe les données avec les méthodes qui fonctionnent sur les données tout en limitant l'accès direct en empêchant l'exposition des détails de mise en œuvre cachés.

Conclusion

J'espère que cet article vous a aidé à comprendre la programmation orientée objet de manière plus pratique. La POO aide vraiment à faciliter l'extension de l'application à l'avenir si nécessaire en étant claire et réutilisable.

De plus, un plugin qui utilise la POO sera plus rapide et plus facile à exécuter. En effet, les méthodes communes à tous les objets d'une classe ne consomment de la mémoire qu'une seule fois, lors de leur déclaration.

La sécurité est également améliorée grâce à l'encapsulation. En programmation procédurale, par contre, toutes les données sont globales, ce qui signifie que l'accès est disponible de n'importe où.

Grâce à ce qui précède, la maintenance du code, la productivité, l'évolutivité et le dépannage deviennent également beaucoup plus faciles pour vous et votre équipe.

Dans les prochains articles de cette série, nous verrons ce style de programmation en action en l'appliquant à un plugin WordPress. Plus précisément, nous allons créer une copie du plugin Limit Login Attempts version 1.7.1 créé par Johan Eenfeldt mais converti avec une approche orientée objet autant que possible.

Au cours de ce processus, nous décomposerons le flux du plugin et définirons les exigences. À l'avenir, nous essaierons nos premières réflexions sur la conception du plugin et, dans l'étape de mise en œuvre, nous écrirons le code. Au cours du processus de mise en œuvre, nous ferons des allers-retours et remanierons, si nécessaire, afin d'obtenir les résultats souhaités.

Cependant, nous n'entrerons pas dans les détails de toutes les parties du code. Au lieu de cela, nous aimerions nous concentrer sur le partage de la façon dont les plugins sont construits de manière orientée objet. Nous sommes convaincus qu'une fois que vous aurez fini de lire cette série d'articles, vous pourrez très bien créer votre propre plugin OOP.

Cliquez ici pour lire la partie 3 de notre série sur la programmation orientée objet

Voir également

  • WordPress et la programmation orientée objet - Un aperçu