paint-brush
Coder sur une interface : tout ce que vous devez savoirpar@oussamamater
482 lectures
482 lectures

Coder sur une interface : tout ce que vous devez savoir

par Oussama Mater7m2024/06/18
Read on Terminal Reader

Trop long; Pour lire

"Coder vers une interface" n'a jamais eu de sens pour moi. Je me suis interrogé sur la nécessité de créer une interface puis de la mettre en œuvre. Comment puis-je déterminer quand et où utiliser ces interfaces ? Si vous vivez cela, sachez que nous sommes tous passés par là. Laissez-nous vous aider à comprendre pourquoi vous devez « coder pour interfacer ».
featured image - Coder sur une interface : tout ce que vous devez savoir
Oussama Mater HackerNoon profile picture

À mesure que vous abordez la programmation de manière plus sérieuse, vous rencontrez inévitablement l'expression « Coder vers une interface », que ce soit dans des vidéos, des livres ou des articles. Et cela n'a jamais eu de sens pour moi. Je me suis interrogé sur la nécessité de créer une interface puis de la mettre en œuvre. Comment puis-je déterminer quand et où utiliser ces interfaces ?


Chaque fois que je regardais un tutoriel ou lisais un article, ils m'expliquaient ce qu'est une interface, "C'est une classe sans implémentation", et je me disais "Ehmm, merci 😏". Je veux dire, je le savais déjà ; ce que je voulais vraiment savoir, c'était pourquoi et quand l'utiliser.


Je me souviens d'un jour, j'ai interrogé la communauté Discord, et l'un des seniors a simplement dit : « Ne vous inquiétez pas, cela finira par cliquer pour vous », et c'est arrivé, cela a pris du temps, mais c'est arrivé. Si vous vivez cela, sachez que nous sommes tous passés par là ; nous allons vous aider à comprendre pourquoi vous devez coder sur une interface .

Écrivons du code

Puisque l’IA prend le dessus et que tout le monde s’en fout, nous ne voulons pas être en retard à la fête. Nous souhaitons l'ajouter à notre site Web, un petit chatbot qui répond aux questions sur notre produit le fera.


J'utiliserai PHP pour mon exemple ; n'hésitez pas à utiliser n'importe quelle langue avec laquelle vous êtes à l'aise. Ce qui compte, c'est le concept.


Notre chatbot peut être aussi simple que ceci :

 <?php class ChatBot { public function ask(string $question): string { $client = new OpenAi(); $response = $client->ask($question); return $response; } }

Il existe une seule méthode ask() , qui utilise le SDK OpenAI pour se connecter à leur API, poser une question, puis renvoyer simplement la réponse.


Nous pouvons maintenant commencer à utiliser notre chatbot

 $bot = new ChatBot(); $response = $bot->ask('How much is product X'); // The product costs $200.


Jusqu'à présent, la mise en œuvre semble bonne, elle fonctionne comme prévu et le projet est déployé et utilisé. Mais nous ne pouvons nier que notre chatbot est fortement dépendant de l’API Open AI ; Je suis sûr que vous êtes d'accord.


Considérons maintenant un scénario dans lequel les prix de l’Open AI doublent et continuent d’augmenter. Quelles sont nos options ? Soit nous acceptons simplement notre sort, soit nous recherchons une autre API. La première option est simple, nous continuons simplement à les payer, et la deuxième n’est pas aussi simple qu’il y paraît. Le nouveau fournisseur aura probablement sa propre API et son propre SDK ; nous devrons faire des mises à jour de toutes les classes, tests et composants associés initialement conçus pour Open AI, cela représente beaucoup de travail.


Cela suscite également des inquiétudes ; Que se passe-t-il si la nouvelle API ne répond pas à nos attentes en termes de précision ou si les temps d'arrêt augmentent ? Et si nous voulions simplement expérimenter simultanément avec différents fournisseurs ? Par exemple, fournir à nos clients abonnés le client OpenAI tout en utilisant une API plus simple pour les invités ? Vous voyez à quel point cela peut être complexe, et vous savez pourquoi ? Parce que notre code était mal conçu.


Nous n'avions pas de vision; nous venons de choisir une API et en étions entièrement dépendants et de sa mise en œuvre. Or, le principe du « Code to interface » nous aurait épargné tout cela. Comment? Voyons.


Commençons par créer une interface :

 <?php interface AIProvider { public function ask(string $question): string; }


Nous avons notre interface, ou comme j'aime l'appeler, un contrat. Implémentons-le ou codons-le.

 <?php class OpenAi implements AIProvider { public function ask(string $question): string { $openAiSdk = new OpenAiSDK(); $response = $openAiSdk->ask($question); return "Open AI says: " . $response; } } class RandomAi implements AIProvider { public function ask(string $question): string { $randomAiSdk = new RandomAiSDK(); $response = $randomAiSdk->send($question); return "Random AI replies: " . $response->getResponse(); } }


En réalité, OpenAiSDK et RandomAiSDK seront injectés via le constructeur. De cette façon, nous déléguons la logique d'instanciation complexe à un conteneur DI , un concept connu sous le nom d' inversion de contrôle . En effet, chaque fournisseur nécessite généralement certaines configurations.


Nous disposons désormais de deux fournisseurs que nous pouvons utiliser pour répondre aux questions. Quelle que soit leur mise en œuvre, nous sommes convaincus que lorsqu’on leur pose une question, ils se connecteront à leur API et y répondront. Ils doivent adhérer au contrat AIProvider .


Maintenant, dans notre ChatBot , nous pouvons faire ce qui suit

 class ChatBot { private AIProvider $client; // A dependency can be injected via the constructor public function __construct(AIProvider $client) { $this->client = $client; } // It can also be set via a setter method public function setClient(AIProvider $client): void { $this->client = $client; } public function ask(string $question): string { return $this->client->ask($question); } }


Notez bien que l'exemple vise à démontrer les multiples façons d'injecter une dépendance, dans ce cas, un AIProvider . Vous n'êtes pas obligé d'utiliser à la fois des constructeurs et des setters.


Vous pouvez voir que nous avons apporté quelques modifications ; nous ne dépendons plus d'OpenAI et vous n'y trouverez aucune référence. Au lieu de cela, nous dépendons du contrat/de l’interface. Et, d’une manière ou d’une autre, nous pouvons nous identifier à cet exemple dans la vraie vie ; nous avons tous été un ChatBot au moins une fois.


Imaginez acheter un système de panneaux solaires. L'entreprise promet d'envoyer des techniciens pour l'installer, vous assurant que quel que soit l'employé qu'elle envoie, le travail sera fait et vous finirez par installer vos panneaux. Donc, peu importe qu'ils envoient Josh ou George. Ils peuvent être différents, l’un étant meilleur que l’autre, mais les deux sont engagés pour installer les panneaux.


Ils ne diront pas, vous savez, je répare votre téléviseur à la place, ils sont obligés par l'entreprise de faire le travail spécifié. RandomAi et OpenAi agissent en tant qu'employés d' AIProvider ; vous posez une question et ils vous fourniront une réponse. Tout comme vous ne vous souciez pas de savoir qui installe les panneaux, le ChatBot ne devrait pas du tout se soucier de qui fait le travail. Il a juste besoin de savoir que toute implémentation fournie le fera.


Désormais, vous pouvez librement utiliser l’un ou l’autre.

 $bot = new ChatBot(); // For subscribed users $bot = new ChatBot(new OpenAi()); $response = $bot->ask('How much is Product X'); // Open AI says: 200$ // For guests $bot->setClient(new RandomAi()); $response = $bot->ask('How much is Product X'); // Random AI replies: 200$

Désormais, vous avez la possibilité de modifier l’intégralité du fournisseur d’API et votre code se comportera toujours de la même manière. Vous n'avez rien à changer car vous avez codé sur une interface , donc aucune des préoccupations que nous avons soulevées plus tôt ne sera un problème.

Il y a toujours des bonus

Dans notre exemple, en codant sur une interface, nous avons également respecté trois des principes SOLID , sans même le savoir, permettez-moi de développer.


Je n'entrerai pas dans les détails ; chacun des principes peut faire l'objet d'un long article. Ceci est juste une brève explication pour montrer ce que nous avons gagné en codant sur une interface.

Principe ouvert-fermé

Le premier principe que nous avons respecté est le principe ouvert-fermé, qui stipule que le code doit être ouvert à l'extension et fermé à la modification. Aussi difficile que cela puisse paraître, vous y êtes parvenu. Pensez-y, le ChatBot est maintenant fermé pour modification ; nous ne toucherons plus au code. C'était notre objectif depuis le début.


Mais il est ouvert à une extension ; si nous devions ajouter un 3ème, un 4ème, voire un 5ème fournisseur, rien ne nous arrêterait. Nous pouvons implémenter l'interface et notre classe peut l'utiliser immédiatement, aucune modification n'est requise.

Remplacement Liskov

Je ne vais pas vous ennuyer avec sa définition, mais en gros, elle indique que vous pouvez remplacer les classes par TOUTES leurs sous-classes et vice versa. Techniquement, tous nos fournisseurs d'IA are-a AIProvider et leurs implémentations peuvent être échangées les unes contre les autres, sans affecter l'exactitude de ChatBot , ce dernier ne sait même pas quel fournisseur il utilise 😂, alors oui, nous avons respecté Mme Liskov .

Inversion de dépendance

Je dois admettre que celui-ci pourrait avoir son propre article. Mais pour faire simple, le principe stipule qu’il faut s’appuyer sur des abstractions plutôt que sur des éléments concrets, ce qui est exactement ce que nous faisons. Nous dépendons d’un fournisseur, pas d’un fournisseur spécifique comme Open AI.


N'oubliez pas que tout cela est dû au fait que nous avons codé sur une interface.

Cela finira par cliquer pour vous

Chaque fois que vous mettez à jour une classe que vous savez que vous ne devriez pas mettre à jour et que votre code devient piraté avec les instructions if, vous avez besoin d'une interface. Demandez-vous toujours : ce cours a-t-il vraiment besoin de savoir comment ? Vais-je toujours utiliser ce fournisseur de services ? Ou un pilote de base de données ? Sinon, vous savez quoi faire.


Cela étant dit, laissez-lui un peu de temps, il finira par cliquer pour vous .