Comment garantir un code PHP flexible et réutilisable avec Insphpect – SitePoint

Online Coding Courses for Kids

Inspecter est un outil que j’ai écrit dans le cadre de mon projet de doctorat. Il analyse le code à la recherche de techniques de programmation orientée objet qui entravent la réutilisation et la flexibilité du code.

Pourquoi?

Permettez-moi de commencer par deux observations banales:

  1. Les exigences commerciales évoluent avec le temps.
  2. Les programmeurs ne sont pas clairvoyants.

Lancement de nouveaux produits, réglementations de verrouillage d’urgence, expansion sur de nouveaux marchés, facteurs économiques, lois de protection des données mises à jour: il existe de nombreuses causes potentielles de mise à jour des logiciels d’entreprise.

De ces deux observations, nous pouvons déduire que les programmeurs savent que le code qu’ils écrivent va changer, mais pas ce que ces changements seront ou quand ils se produiront.

Écrire du code de manière à ce qu’il puisse être facilement adapté est une compétence qui prend des années à maîtriser.

Vous connaissez probablement déjà les pratiques de programmation qui reviennent et vous hantent. Les programmeurs débutants se rendent rapidement compte que les variables globales sont plus problématiques qu’elles ne le valent, et le motif Singleton, jadis incroyablement populaire, est un gros mot depuis dix ans.

La façon dont vous codez votre application a un impact important sur sa facilité d’adaptation pour répondre aux nouvelles exigences. Au fil de votre carrière, vous apprenez des techniques qui facilitent l’adaptation du code. Une fois que vous avez compris les principes de base de la programmation orientée objet, vous vous demandez comment vous vous en êtes sorti!

Si vous demandez à dix développeurs de produire des logiciels, avec les mêmes exigences, vous obtiendrez dix solutions différentes. Certaines de ces solutions seront inévitablement meilleures que d’autres.

Considérons un navire dans une bouteille et un modèle réduit de bateau en Lego. Les deux sont des modèles réduits de navires, mais changer les voiles sur le navire dans une bouteille est très difficile, et la réutilisation des pièces est presque impossible. Cependant, avec un navire Lego, vous pouvez facilement échanger les voiles ou utiliser les mêmes composants pour construire une maquette de fusée, une maison ou une voiture.

Certaines techniques de programmation conduisent à expédier en bouteille approche et rendre votre code difficile à changer et à adapter.

Inspecter

Inspecter est un outil qui analyse votre code pour les pratiques de programmation qui conduisent à ce type de vaisseau dans une conception de bouteille.

Il note votre code en fonction de sa flexibilité et met en évidence les domaines dans lesquels la flexibilité peut être améliorée.

Que recherche Insphpect?

Actuellement, Insphpect recherche les éléments suivants:

  • couplage serré
  • configuration codée en dur
  • singletons
  • injection de setter
  • en utilisant le new mot-clé dans un constructeur
  • localisateurs de services
  • héritage
  • méthodes statiques
  • état global
  • fichiers qui ont plus d’un rôle (par exemple, définir une classe et exécuter du code)

S’il détecte quelque chose qu’il identifie comme inflexible, il met en évidence le code, explique pourquoi il a mis en évidence le problème, puis note tout votre projet et vos classes individuelles sur une note de 0 à 100 (100 étant aucun problème détecté). À titre de preuve de concept, pour certaines détections, il est capable de générer automatiquement un fichier de correctif qui réécrit le code pour supprimer complètement l’inflexibilité.

Jetez un œil à un exemple de rapport ici.

Insphpect est actuellement en phase de test, et cela aiderait vraiment le progrès de ma recherche si vous pouvez le vérifier et remplir le sondage dans la section «Donnez votre avis» du site.

Contexte

Mais ces mauvaises pratiques sont-elles vraiment mauvaises?

Ce fut l’une des parties les plus difficiles de la recherche de base, et vous pouvez lire comment cela a été fait en détail sur le Site Web Insphpect.

Cependant, cela peut être résumé comme suit:

  • Les opinions de chaque mauvaise pratique ont été recueillies auprès de 100 auteurs par pratique.
  • L’opinion de l’auteur sur cette pratique a été notée sur une échelle de 1 à 5.
  • La rigueur méthodologique de l’auteur a été notée sur une échelle de 1 à 7 sur la base du score Jadad utilisé pour les essais cliniques.

Celles-ci ont ensuite été tracées comme le graphique ci-dessous:

Résultats du motif singleton

Chaque ligne horizontale représente un article, et la barre gauche (orange) pour chaque article est la recommandation allant de 5 – Évitez cette pratique à tout prix (Extrême gauche) – à 1 – Privilégiez cette pratique aux alternatives.

La barre de droite (bleue) pour chaque article est le score de style Jadad mesurant la rigueur analytique. Un score de sept signifie que l’article décrit la pratique, fournit des exemples de code, discute des approches alternatives, fournit des exemples de code comparables, discute des avantages / inconvénients de chaque approche et fait une recommandation de l’approche à utiliser.

Dans le cas du singleton ci-dessus, les auteurs qui comparent le singleton à des approches alternatives, discutent des avantages / inconvénients, etc., sont beaucoup plus susceptibles de suggérer d’utiliser des approches alternatives.

Procédure pas à pas

Actuellement, Insphpect permet de télécharger du code via une URL de référentiel Git ou un fichier ZIP.

Donc, pour ne pas signaler les failles dans le travail des autres, jetons un œil à l’un de mes propres projets pour voir ce qu’il identifie.

Nous utiliserons https://github.com/Level-2/Transphporm comme exemple de projet.

Ceci est un assez bon exemple, car il a un score très élevé sur un autre outil de qualité de code Scrutinisateur.

Tout d’abord, entrez l’URL git https://github.com/Level-2/Transphporm dans la zone de texte en haut de la page d’accueil et appuyez sur “Go”. Cela prendra quelques secondes à quelques minutes, selon la taille du projet, et générera un rapport qui ressemble à ceci:

Rapport Transphporm

Une fois que vous êtes sur la page du rapport, vous verrez un résumé en haut avec une note globale sur 100, 100 étant très bon et 0 étant très mauvais.

Sous le résumé, vous verrez une liste de toutes les classes du projet, chacune avec sa propre note.

Ne vous inquiétez pas si votre code n’obtient pas un score parfait. Il est peu probable que ce soit le cas. N’oubliez pas, Insphpect est un outil qui identifie la flexibilité de votre code. Il y a des parties de votre code (comme le point d’entrée) où la flexibilité n’est pas garantie.

Pour Transphporm, il a mis en évidence des problèmes dans sept classes.

Jetons un œil à certains d’entre eux. Faites défiler jusqu’à TransphpormParserCssToXpath et cliquez sur le lien. Vous verrez un score pour cette classe particulière et une liste des problèmes qui ont été identifiés.

Dans ce cas, il a identifié une variable statique et une méthode statique. En cliquant sur l’une des lignes rouges, vous découvrirez pourquoi la ligne a été signalée.

Par exemple, un clic sur la ligne 12 expliquera pourquoi les variables statiques sont moins flexibles que les variables d’instance.

Rapport de classe unique

Bien qu’il existe une explication plus approfondie des problèmes causés par les propriétés statiques sur le rapport, pour un rappel rapide, les variables statiques ont une valeur qui est partagée entre toutes les instances de la classe.

C’est intrinsèquement moins flexible qu’une variable d’instance, car l’utilisation d’une variable d’instance permet à chaque instance d’avoir une valeur différente.

Par exemple, tenez compte des éléments suivants:

class User {
    public static $db;
    public $id;
    public $name;
    public $email;

    public function save() {
        $stmt = self::$db->prepare('REPLACE INTO user (id, name, email) VALUES (:id, :name, :email)');

        $stmt->execute([
            'id' => $this->id,
            'name' => $this->name.
            'email' => $this->email
        ]);
    }
}

Car $db est statique, chaque instance de cette classe partage la même chose $db l’instance et les enregistrements seront toujours insérés dans la même base de données.

Bien que cela semble raisonnable, permettez-moi de vous donner un exemple concret.

Dans le monde réel

Un de nos clients était une agence de recrutement. Environ deux ans après avoir développé leur site, ils ont repris une autre petite entreprise. Ils voulaient conserver le site Web et l’image de marque de la deuxième entreprise, car il était assez bien connu dans le créneau dans lequel ils se trouvaient.

Notre client nous a demandé ce qui suit:

Sur le site de la deuxième entreprise, pouvez-vous ajouter une case à cocher lors de l’ajout d’un travail qui ajoute également le travail à notre base de données afin que les personnes qui consultent notre site puissent également voir le travail et vice versa.

Une demande assez simple. Exécutez une requête d’insertion dans deux bases de données différentes.

Mais comme le site Web utilisait une instance de base de données globale statique, cela a été inutilement difficile!

Les développeurs de ce site ont écrit le code confiant qu’une seule connexion à la base de données serait jamais nécessaire. Ils avaient tord.

N’oubliez pas que vous n’êtes pas clairvoyant et qu’il est impossible d’anticiper quelle flexibilité pourrait être nécessaire à l’avenir.

La solution

Comme suggéré par Insphpect, la solution consiste à utiliser des variables d’instance:

class User {
    private $db;
    public $id;
    public $name;
    public $email;

    public function __construct(PDO $db) {
        $this->db = $db;
    }

    public function save() {
        $stmt = self::$db->prepare('REPLACE INTO user (id, name, email) VALUES (:id, :name, :email)');

        $stmt->execute([
            'id' => $this->id,
            'name' => $this->name.
            'email' => $this->email
        ]);
    }
}

Maintenant un User l’instance peut être utilisée avec différentes instances de base de données:

new User($database1);
new User($database2);

Pour TransphpormParserCssToXpath nous pourrions faire de même, supprimer la variable statique et envisager d’en faire une variable d’instance plutôt qu’une variable statique.

Utilisation de new dans constructeur

Jetons un œil à l’une des autres classes: TransphpormBuilder.

Rapport de classe de générateur

Cela a un score de zéro, ce qui est plutôt mauvais. En examinant le rapport en détail, Insphpect a relevé le même problème à trois reprises: en utilisant new mot-clé dans un constructeur.

L’entraîneur de programmation Google Misko Hevery fait un excellent travail pour expliquer pourquoi il s’agit d’une mauvaise pratique de programmation, mais voici un exemple simple de la sortie d’Insphpect:

class Car {
    private $engine;

    public function __construct() {
        $this->engine = new PetrolEngine();
    }
}

Ici, chaque fois qu’une instance de Car est créé, une instance de PetrolEngine est créé. Cela le rend très rigide, car il n’y a aucun moyen de construire un Car avec un type de moteur différent. Chaque voiture modélisée dans ce système doit avoir un PetrolEngine.

Au lieu de cela, nous pouvons utiliser l’injection de dépendance:

class Car {
    private $engine;

    public function __construct($engine) {
        $this->engine = $engine;
    }
}

Différentes voitures peuvent être créées avec une instance de PetrolEngine, DieselEngine, ElectricEngine, JetEngine ou tout autre type de moteur existant dans le projet.

Pour corriger cette erreur dans le TransphpormBuilder, toutes les variables qui ont actuellement des noms de classe codés en dur doivent utiliser des arguments de constructeur à la place.

Il y a d’autres problèmes identifiés par Insphpect, mais vous pouvez l’essayer par vous-même et voir comment se déroule votre projet.

Dans les coulisses

Vous vous demandez peut-être comment les scores sont calculés et pourquoi cette classe a obtenu un zéro. À l’heure actuelle, les pondérations sont susceptibles de changer une fois que d’autres projets ont été analysés et que davantage de commentaires ont été fournis.

Les scores sont conçus pour être indicatifs pour comparer un projet / classe à un autre.

La note globale du projet n’est qu’une moyenne de toutes les classes du projet. Cela a été implémenté car un projet avec deux problèmes dans 1000 classes est beaucoup mieux dans l’ensemble qu’un projet avec deux problèmes dans deux classes.

Chaque mauvaise pratique est pondérée en fonction du fait qu’elle entrave la flexibilité pour l’ensemble de la classe ou entrave uniquement la flexibilité pour une méthode.

Conclusion

Insphpect peut être utilisé pour identifier les zones de votre code qui rendent les modifications futures plus difficiles qu’elles ne pourraient l’être, et il propose des suggestions sur la façon d’écrire le code de manière plus flexible. N’oubliez pas que vous n’êtes pas clairvoyant et que vous n’avez aucun moyen de savoir comment votre code va devoir changer!

Inspecter est actuellement un travail en cours, et plus il y aura de personnes qui l’utiliseront (et rempliront l’enquête) mieux ce sera.

Quel a été le score de votre projet ou de votre bibliothèque préférée? Assurez-vous de remplir le sondage, car il fournira des données précieuses pour mon projet de doctorat et aidera l’outil à s’améliorer!

Close Menu