Guide de développement

Note

Bien que le framework soit relativement récent, veuillez noter que certaines des premières classes d’Ubiquity ne suivent pas entièrement ce guide et n’ont pas été modifiées pour des raisons de rétrocompatibilité.
Néanmoins, tous les nouveaux codes doivent suivre ce guide.

Choix de conception

Sollicitation et utilisation de services

Injection de dépendances

Évitez d’utiliser l’injection de dépendances pour toutes les parties du framework, en interne.
L’injection de dépendances est un mécanisme gourmand en ressources :

  • Elle nécessite d’identifier l’élément à instancier ;

  • Puis de procéder à sont instanciation :

  • Pour enfin assigner le résultat à une variable.

Obtenir des services d’un conteneur

Evitez également les accès publics aux services enregistrés dans un conteneur de services.
Ce type d’accès implique la manipulation d’objets dont le type de retour est inconnu, et peu facile à manipuler pour le développeur.

Par exemple, il est difficile de manipuler le retour non typé de $this->serviceContainer->get('translator'), comme le permettent certains frameworks, et de savoir quelles méthodes appeler dessus.

Lorsque cela est possible, et lorsque cela ne réduit pas trop la flexibilité, l’utilisation de classes statiques est conseillée :

Pour un développeur, la classe TranslatorManager est accessible depuis un l’ensemble du projet sans aucune instanciation d’objet.
Elle expose son interface publique et permet la complétion de code :

  • Le translator n’a pas besoin d’être injecté pour être utilisé ;

  • Il n’a pas besoin d’être récupéré depuis un conteneur de services.

L’utilisation de classes statiques crée inévitablement une forte dépendance et affecte la flexibilité.
Mais pour revenir à l’exemple du Traducteur, il n’y a aucune raison de le modifier s’il est satisfaisant. |brl Il n’est pas souhaitable de vouloir à tout prix apporter de la flexibilité quand elle n’est pas nécessaire, pour qu’en conséquence, l’utilisateur constate ensuite que son application est un peu lente.

Optimisation

L’exécution de chaque ligne de code peut avoir des répercussions importantes sur les performances.
Comparez et évaluez les solutions de mise en œuvre, en particulier si le code est sollicité à plusieurs reprises :

Qualité du code

Ubiquity utilise Scrutinizer-CI pour l’évaluation de la qualité du code.

  • Pour les classes et les méthodes :

    • Les évaluations A ou B sont satisfaisantes

    • C est acceptable, mais à éviter autant que possible

    • Les notes plus basses sont à prohiber

Complexité du code

  • Les méthodes complexes doivent être divisées en plusieurs, pour faciliter la maintenance et permettre la réutilisation ;

  • Pour les classes complexes, effectuer une refactorisation de type extract-class ou extract-subclass en utilisant les traits.

Duplications de code

Évitez absolument la duplication du code, sauf si la duplication est minime et est justifiée par les performances.

Bugs

Essayez de résoudre tous les bugs signalés au fur et à mesure, sans les laisser s’accumuler.

Tests

Toute correction de bug qui n’inclut pas un test prouvant l’existence du bug corrigé, peut être suspecte.
De même pour les nouvelles fonctionnalités dont on ne peut prouver qu’elles fonctionnent réellement.

Il est également important de maintenir un taux de couverture du code par les tests acceptable, qui peut baisser si une nouvelle fonctionnalité n’est pas testée.

Documentation du code

Le code actuel n’est pas encore entièrement documenté, n’hésitez pas à contribuer afin de combler cette lacune.

Standards de code

Les standards de code Ubiquity sont basés sur les standards PSR-1 , PSR-2 et PSR-4 il est donc préférable de les connaître.
Les quelques exceptions aux standards sont normalement reportées dans ce guide.

Conventions de nommage

  • Utiliser camelCase pour les variables php, les membres, les fonctions et noms de méthodes, les arguments (e.g. $modelsCacheDirectory, isStarted()) ;

  • Chaque classe php doit avoir un namespace (voir PSR-4) et utiliser la convention UpperCamelCase pour son nommage (e.g. CacheManager) ;

  • Préfixer toutes les classes abstraites avec Abstract, à l’exception des classes PHPUnit BaseTests :

  • Suffixer les interfaces avec Interface ;

  • Suffixer les traits avec Trait ;

  • Suffixer les exceptions avec Exception ;

  • Suffixer les classes principales de type manager avec Manager (e.g. CacheManager, TranslatorManager) ;

  • Préfixer les classes utilitaires avec un U (e.g. UString, URequest) ;

  • Utiliser UpperCamelCase pour le nommage des fichiers PHP (e.g. CacheManager.php) ;

  • Utiliser les majuscules pour les constantes (e.g. const SESSION_NAME=”Ubiquity”).

Indentation, tabulations, accolades

  • Utiliser des tabulations, et non des espaces ; (! PSR-2)

  • Utiliser les accolades sans passage à la ligne suivante ; (! PSR-2)

  • Utilisez des accolades pour indiquer le corps de la structure de contrôle, quel que soit le nombre d’instructions qu’elle contient ;

Classes

  • Définir une classe par fichier ;

  • Déclarer l’héritage de la classe et toutes les interfaces implémentées sur la même ligne que le nom de la classe ;

  • Déclarer les membres de données avant les méthodes ;

  • Déclarer les méthodes privées en premier, puis celles qui sont protégées pour finir par les méthodes publiques :

  • Déclarer tous les arguments sur la même ligne que le nom de la méthode/fonction, quel que soit le nombre d’arguments ;

  • Utiliser des parenthèses lors de l’instanciation d’une classe, même si le constructeur ne prend aucun argument ;

  • Ajouter le statement use pour chaque classe qui ne fait pas partie de l’espace de noms global ;

Opérateurs

  • Utiliser la comparaison identique ou égale lorsque vous le jugez nécessaire ;

Exemple

<?php
namespace Ubiquity\namespace;

use Ubiquity\othernamespace\Foo;

/**
 * Class description.
 * Ubiquity\namespace$Example
 * This class is part of Ubiquity
 *
 * @author authorName <authorMail>
 * @version 1.0.0
 * @since Ubiquity x.x.x
 */
class Example {
        /**
         * @var int
         *
         */
        private $theInt = 1;

        /**
         * Does something from **a** and **b**
         *
         * @param int $a The a
         * @param int $b The b
         */
        function foo($a, $b) {
                switch ($a) {
                        case 0 :
                                $Other->doFoo ();
                                break;
                        default :
                                $Other->doBaz ();
                }
        }

        /**
         * Adds some values
         *
         * @param param V $v The v object
         */
        function bar($v) {
                for($i = 0; $i < 10; $i ++) {
                        $v->add ( $i );
                }
        }
}

Important

Vous pouvez importer ces fichiers de standardisation intégrant ces règles dans votre IDE :

Si votre IDE favori ne figure pas dans la liste, vous pouvez soumettre le fichier de normalisation associé en créant une nouvelle PR.