~bohwaz/blog/

Avec de vrais morceaux de 2.0 !

De l'explosion des classes en PHP

Autant j'aime beaucoup les namespaces, la séparation claire des fonctions et autres sucreries en PHP, autant j'ai l'impression qu'on est maintenant dans un excès inverse. Avant on avait des gros fichiers monolithiques remplis de fonctions sans rapport les unes avec les autres c'était crade. Mais maintenant on a un énorme bordel de fichiers et classes qui ne servent à rien et ne font que détruire les perfs du serveur.

Évidemment ça ne se voit pas trop sur un serveur qui ne sert qu'une seule application car le code et les fichiers restent en RAM, mais quand on est en mutualisé avec des milliers d'applis sur le même dédié, ça se ressent bien. D'abord car charger un fichier depuis le disque à un coût, et ensuite parce qu'une classe en PHP occupe pas mal d'espace mémoire, même si elle est vide (cf. notamment la conférence de Julien Pauli).

Prenons quelques exemples. En premier picoFeed de Frédéric Guillot, qui lui sert notamment pour miniflux, que j'apprécie beaucoup (même si c'est pas encore ça à mon avis). C'est un parseur de flux RSS/Atom qui se veut "simple" et "rapide" qui fait tout un tas de choses genre récupération du contenu des articles pour les flux qui ne fournissent rien, la possibilité de générer des flux, des filtres de contenu, etc. Mais ça reste un exemple quand même. Cette librairie (une fois supprimées les règles de récupération de contenu) fait 47 fichiers, dont 16 qui font moins de 200 octets. Prenons un exemple, de 125 octets, Parser/Rss92.php:

namespace PicoFeed\Parser;

/**
 * RSS 0.92 Parser.
 *
 * @author  Frederic Guillot
 */
class Rss92 extends Rss20
{
}

Et toutes ces classes sont comme ça, elles ne servent à rien à part avoir un nom différent. Pourquoi ne pas faire un if/else ou switch case pour gérer ces cas plutôt que de créer des classes vides ? C'est moche.

Et ce n'est qu'une seule lib qui ne sert qu'à faire du RSS/Atom. Imaginez une appli complète avec des dizaines de libs de la même manière. Oh évidemment on ne charge pas tous les fichiers de toutes les libs (et donc toutes les classes) à chaque requête mais bon niveau perfs ça se ressent quand même.

Je suis aussi particulièrement admiratif quand je vois une lib (ou appli etc.) avec des dizaines ou centaines de classes pour gérer des exceptions (record : 450 !). Chaque classe ne faisant qu'étendre une autre classe d'exceptions. picoFeed est un peu victime de ça, même si vu la taille de la lib ça reste correct. On va dire que je me répète à force mais : à quoi ça sert d'avoir une classe pour chaque type d'exception imaginable ? Vous avez oublié que le second paramètre du constructeur d'une exception c'est $code ? Et à quoi ça sert $code ? Et bien à passer un code d'erreur !

Ainsi dans picoFeed on a ClientException (qui étend Exception), et des classes qui l'étendent : InvalidUrlException, InvalidCertificateException, MaxRedirectException, MaxSizeException, et TimeoutException.

Pourquoi ne pas avoir une seule classe/exception et un code d'erreur différent pour chaque situation ? Ces exceptions ne servent à rien, 99% des utilisateurs de la lib ne vont pas les récupérer individuellement. De même que ça n'aurait aucun sens que MySQL rejette une classe d'exception différente à chaque erreur différente, qui irait vraiment utiliser MySQLException_ER_CANT_CREATE_TABLE par exemple ? Quasiment personne, et c'est pour ça que ça a du sens d'utiliser le code d'erreur.

Je pourrais parler aussi de UA-Parser, une lib qui permet de parser l'User-Agent du navigateur. Bon je sais que c'est devenu compliqué de parser ce bordel d'UA avec le temps, mais quand même, 27 classes pour ça ? 130 Ko de code, et ça ne comprend même pas le fichier avec les regexs utilisées pour reconnaître l'user-agent !

Bref il y aurait de quoi simplifier ici, et tendre vers plus de légèreté et cesser un peu cette expansion lyrique qui n'a pas grande utilité, vous ne pensez pas ?

PS : pour ceux/celles qui demandent une alternative à picoFeed je ne peux que conseiller ma propre solution (modestie oblige ;-) ), FeedParser, issu du Framework KD2 (qui n'est pas un vrai framework structurant mais un ensemble de libs pratiques, légères et utiles, utilisables indépendamment les unes des autres). La stratégie de parsing est complètement différente : FeedParser n'utilise pas DOMDocument ou SimpleXML pour parser un document car les sites génèrent souvent du XML invalide. De ce fait FeedParser fait du parsing/lexing directement sur le flux, même s'il est invalide. Et ça marche ! Dans mes tests j'ai 100% de succès (aucun flux n'est illisible) sur plus de 20.000 flux, dont 15% de flux invalides. Et évidemment une seule classe, 17 Ko de code, contre pas loin de 400 Ko pour picoFeed par exemple.

Écrire un commentaire
(facultatif)
(facultatif)
(obligatoire)
                          
  ___ __ _ _   _ ___  ___ 
 / __/ _` | | | / __|/ _ \
| (_| (_| | |_| \__ \  __/
 \___\__,_|\__,_|___/\___|
                          
(obligatoire)

Les adresses internet seront converties automatiquement.
Tags autorisés : <blockquote> <cite> <pre> <code> <var> <strong> <em> <del> <ins> <kbd> <samp> <abbr>

pierre

Quelques questions :

- est-ce à dire que vous êtes un adepte du "The MicroPHP Manifesto" [http://microphp.org/] ?
- est-ce à dire que vous n'êtes pas pour les Framework Symphony / Zend ? ni pour les micro Framework ?
- avez-vous un exemple d'une application (plus d'une classe avec des dépendances) qui pour vous est un "modèle" de bon développement ?

Sinon, je partage aussi votre point de vue, mais je me cherche toujours ..

Cordialement

BohwaZ

Hello, je n'ai rien personnellement contre les frameworks, mais je les trouve trop lourds en général, trop de code et de trucs à gérer. Et en général si tu veux juste un module du framework tu dois te taper toute la logique du framework, genre le modèle, la hiérarchie des répertoires, la gestion des erreurs (alors que bon on les exceptions en PHP, mais chaque framework semble réinventer ça à sa sauce), etc.

Si je devais en utiliser un ce serait sûrement Zend qui est plutôt bien fait niveau modularité, et probablement le meilleur sur ce plan-là. De plus il est bien codé, complet, et chaque module est bien foutu et cohérent (en général).

Je ne connaissais pas Micro PHP manifesto mais oui pas loin de ça. Il faut dire que la bibliothèque standard de PHP est très très bien fournie. Là où il faudrait installer des centaines de modules tiers en JS ou des dizaines en Ruby/Python, en PHP en général tu n'a rien à faire, le principal est là. Je l'utilise aussi en embarqué car avec un petit binaire on a accès à des tonnes de fonctionnalités, avec d'excellentes performances. PHP a cette force là, et s'il est toujours le seul présent chez tous les hébergeurs c'est qu'il y a une raison et notamment que la bibliothèque standard est très bien fournie et que l'admin sys n'a pas besoin d'installer des modules tiers à la confiance douteuse.

Sinon moi j'ai développé mon propre framework qui est plus un ensemble de classes utilitaires développées et peaufinées au fil des ans, chacune étant indépendante des autres, on peut donc n'en prendre qu'une seule sans trop se poser de questions. Cf. http://dev.kd2.org/kd2fw/

J'essaye donc de réunir et faire un peu de rangement dans les quelques classes développées avec le temps et les mettre au même endroit, mais ce n'est pas vraiment un framework au sens "vrai" du terme.

Par contre je ne suis pas d'accord avec l'auteur de MicroPHP manifesto qui génère son HTML avec du javascript, c'est un gros souci pour moi les sites comme ça, car le JS n'est pas activé sur mes terminaux (mobiles, tablettes, ordis) pour des raisons de performance et de sécu (sauf liste blanche). Et ce n'est pas faire des sites web accessibles s'ils ne sont pas accessibles à des terminaux qui ont quelques années. Je connais encore des gens qui surfent avec Firefox 1.0 ou IE 4.0. Je me fout que mon site marche parfaitement sur leurs écrans mais je veux que quand ils viennent chercher une info ils la trouvent et donc le texte soit lisible. Quand je vais sur mon mobile chercher les horaires d'ouverture d'un magasin (information simple pourtant) je constate que le site ne marche pas parce qu'il y a un bug dans leur javascript qui fait 750 Ko je me dis qu'on marche sur la tête et que ces gens-là ne font pas du web mais de la branlette technologique.