PHP, caca et programmation orientée objet (POO)
December 14, 2023

Aujourd'hui, j'aimerais aborder cet article sur un ton plus léger. Je voudrais vous raconter comment j'ai découvert la programmation orientée objet, comment je l'ai comprise et comment tout cela m'a amené à concevoir un projet assez... original !
Introduction
J'ai commencé l'apprentissage de la programmation avec java fin 2012. J'ai d'abord appris la programmation impérative et j'apprenais avec pas mal d'aisance. Puis j'ai migré sur la programmation orienté objet et là, cela s'est beaucoup moins bien passé. Avec le recul je pense que cela est dû à plusieurs facteurs. D'abord les travaux à réaliser étaient moins créatifs car ils s'agissait beaucoup d'écriture de setteurs de getteurs : du code bien redondant à coup de copier coller. De plus, j'ai été confronté à ce que j'appelle le problème du comment vs pourquoi. C'est à dire que les cours étaient bien plus orientés sur ce que la POO apportait sans pour autant justifier ses choix de design. Je savais comment ça marchait, mais pas pourquoi ça marchait comme ça.
Cela a duré jusqu'en 2015 où, pendant que je suivais des moocs de programmation, je suis tombé sur un langage assez exotique vis à vis de ce que je connaissais jusque là : Pharo. Contrairement à Java où Php, Pharo est un langage de programmation objet pur et les instructions impératives des deux autres langages, comme les conditions et les boucles, sont alors des appels de méthode. Autre changement assez conséquent : les classes elle-même sont des objets.
Malgré sa syntaxe assez particulière et le fait que je n'ai toujours pas produit de code pharo à ce jour, ça a été une révélation qui m'a grandement aidé à comprendre l'orienté objet.
Pour un peu de culture, voici un exemple de code pharo, tiré du livre pharo par l'exemple.
initialize
| sampleCell width height n |
super initialize.
n := self cellsPerSide.
sampleCell := LOCell new.
width := sampleCell width.
height := sampleCell height.
self bounds: (5@5 extent: ((width*n) @(height*n)) + (2 * self borderWidth)).
cells := Matrix new: n tabulate: [ :i :j | self newCellAt: i at: j ]Et Php dans tout ça ?
C'est peu de temps après que je me suis penché sur le langage Php, et l'onboarding n'a pas été des plus fameux ! Je pourrais critiquer pas mal de points mais je me concentrerais sur un seul, ce n'était pas l'orienté objet que j'avais appris à aimer. Cela a été la source de pas mal de frustrations, au point qu'il m'est venu l'envie d'y palier en lançant un projet assez loufoque : recréer l'OOP de Php. N'étant pas sûr de la possibilité d'une telle démarche, je décide de le renomer Php's Object Oriented Project, ou POOP pour les intimes.
Les premier essais ne sont pas fameux et font usage de code assez discutable. C'est assez logique, si je veux retrouver cette POO que j'aime il me faut refaire la classes, l'héritage, l'accès à self et à super... tout ça n'est pas chose aisée. Pour vous montrer un exmeple, voici un bout de code du premier jet avec une fonction _self qui renvoie l'objet qui l'appelle :
function _self(){
$objet = debug_backtrace();
return $objet[2]["object"];
}Mon code complet est disponible ici, et on peut trouver d'autres excentricités de code. Pour cette raison, le projet sera mis de côté, faute d'être une solution pratique à utiliser. Puis, quelques années plus tard je l'ai repris.
IO, Javascript et prototypage
Si j'aime l'idée que les classes soient des objets, je dois avouer que cela implique pas mal de complexité. En Pharo chaque classe créée ajoute la création d'une metaclasse dont la classe est instance, avec un arbre d'héritage de metaclasses en parallèle de celui des classes. Il y a aussi Ruby, qui propose une alternative moins lourde mais tout de même tordue à mon sens. Toute classe est instance de la classe Class, qui est instance d'elle-même, et hérite indirectement de la class Object qui du coup est aussi instance de la classe Class. De quoi donner le tourni...
Au bout d'un moment et à force de réflexions m'est venue une question : si je veux manipuler des objets qui sont instances de classes elles-même objets, ne serait-il pas préférable de mettre les deux concepts de classes et d'instances au même niveau pour ne manipuler que des objets ? C'est ainsi que je me suis intéressé au concept de prototype.
En m'inspirant des langages de programmtion IO et Javascript (avec un peu de Python), j'ai trouvé moyen de faire une bibliothèque Php permettant de faire de la POO sans avoir à écrire de classe. Une seule classe est nécessaire et est déjà fournie. Le fonctionnement est le suivant :
<?php
// On crée une instance en clonant l'objet statique object de la bibliothèque
include "src/lib.php";
$Range = Instance::object()->clone();
// On définit les propriété de notre objet range
$Range->max = 10;
$Range->min = 0;
// Pour la définition d'une méthode, comme en python le premier paramètre est l'instance et est obligatoire
// Il est passé implicitement à la méthode, qu'on utilise comme ceci => $Range->include(42)
$Range->include = function($self, $value)
{
return ($self->max > $value) && ($self->min <= $value);
};
// On peut créer une méthode make pour produire des ranges à volonté
$Range->make = function($self, $min, $max)
{
$new = $self->clone();
$new->min = $min;
$new->max = $max;
return $new;
};
// A l'usage
$newRange = $Range->make(0, 10);
$newRange->include(42);Le repo du projet est trouvable à cette adresse.
Conclusion
En conclusion je dirais que j'ai beaucoup exploré le concept d'orienté objet durant cette aventure. C'est un paradigme léger qui permet de nombreuses interprétations, ce qui peut lui être reproché, mais j'y vois aussi une force. Au final je n'utilise pas Poop dans mon code Php et je suis assez dubitatif quant à ses performances, mais je suis content de ce que j'ai pu apprendre en chemin.
Epilogue et Lemonade
En plus de cela, j'ai fini par ajouter cette forme d'orienté objet dans un langage de programmation que je développe, baptisé Lemonade. Son nom vient de la grande lignée des langages générant du Javascript (Coffescript, Caffeine, Earl grey...). Bien qu'il me reste encore beaucoup de travail, lemonade a pour but d'être un langage de programmation statiquement typé, orienté objet et fonctionnel, mais très peu impératif. Ce qui j'espère lui permettra de sortir du lot :)
Merci d'avoir lu et à une prochaine !