Séparation UI/Rules : la RÈGLE D’OR de la programmation.
Comme beaucoup, mes premières expériences de code back end se sont faites avec PHP. Je me souviens encore très bien de mes premières pages web avec ce langage, c’était pendant une journée d’été, les oiseaux chantaient, j’avais une faim terrible…
Mais je me souviens surtout que PHP avait presque instantanément changé la manière dont je voyais notre métier. Jamais de ma vie la programmation ne m’avait paru aussi simple et fluide, les frappes sur mon clavier étaient aussi douces que les pressions d’un pianiste alors qu’il est en train de jouer la mélodie de Nocturne Op.9 No.2 en Do mineur de Chopin. J’étais tombé amoureux, et il est quasiment instantanément devenu mon langage préféré.
Mais en continuant mon apprentissage, je me suis rendu compte que ma relation avec PHP devenait plus toxique qu’autre chose, et c’est en jetant un coup d’œil à mes premiers programmes que j’ai vraiment compris ce qu’il n’allait pas. PHP vous pousse à faire du code sale.
<body>
<?php $c = 0; $l = 0; ?>
<table border="1">
<?php for($l = 1; $l<=10; $l++) { ?>
<tr>
<?php for($c=1; $c<=10; $c++)
{ if($l==1 || $c==1) { ?>
<td bgcolor=#C0C0C0>
<?php } else { ?>
<td>
<?php } echo $c * $l; ?>
</td>
<?php } ?>
</tr>
<?php } ?>
</table>
</body>
J’en avais déjà parlé dans une de mes vidéos (vous la trouverez ici : https://www.youtube.com/watch?v=cpWZ3l8wwj8), mais PHP a été pensé comme étant un langage raccourci, pour faire les choses vite-fait bien-fait. Alors c’est sympa de pouvoir travailler rapidement, mais en retour, vous tirez un trait sur des bonnes pratiques de la programmation. Et celle qui en prend le plus pour son grade, c’est la séparation entre l’interface graphique et les règles de logique métier, ce que j’appellerais la séparation UI/Rules.
En général, quand on programme, on a tendance à réfléchir en fonctionnalités, et le fait de récupérer une information d’une base de données et de l’afficher sur l’interface utilisateur, c’est quelque chose qui va de paire et que l’on met dans le même panier.
La séparation UI/Rules, ce n’est pas quelque chose auquel on pense immédiatement (en PHP ou dans n’importe quel autre langage d’ailleurs), et bien souvent, ce sont les framework qui viennent nous le rappeler à coups de pied aux fesses. Par nous-même, on a tendance à aller droit au but et à coder de la manière la plus simple et directe possible. Et c’est pour ça que j’adorais PHP à mes débuts, puisqu’il me permettait de coder super rapidement et facilement, sans rentrer dans des architectures “compliquées”.
Erreur fatale.
Bien sûr, c’est quelque chose qui est justifié quand vous travaillez sur une petite page web ou un petit projet qui va vous prendre quelques heures grand maximum. Là, vous pouvez (éventuellement) vous permettre se coder un peu salement.
Mais sur un vrai projet qui va vous prendre semaines, mois, voir années de travail, c’est quelque chose à éviter absolument !
Déjà, la raison évidente, c’est que sans séparation UI/Rules, votre code va très vite devenir super confus, et il va être difficile de le maintenir, de le debugger, de rajouter des fonctionnalités (comme des bouts d’interface), ou même de discerner ce qui relève réellement de la logique de l’application ou non. Bref, du code à l’italienne.
Et les ennuis ne s’arrêtent pas là. Lorsque vous travaillez en équipe, c’est le bordel assuré : les développeurs front end et back end se mélangent les pinceaux et ne savent jamais qui fait quoi, et quelque chose d’aussi simple que d’implémenter le travail d’un designer va devenir le parcours du combattant.
Et je ne vous parle même pas de ce qu’il risque de se passer si votre équipe décide de refondre le design de l’application. C’est simple : vous prenez le code, poubelle, et vous recommencez tout. Pas top, hein ?
C’est pour ça que quand vous programmez quoique ce soit, application web ou de bureau, vous devez toujours faire ce que j’appelle de la séparation UI/Rules : séparer au maximum vos éléments graphiques ainsi que les interactions avec ceux-ci, de la logique métier de l’application.
Ce que j’appelle logique métier, ce sont les fonctionnalités qui vont constituer le cœur de votre programme. Par exemple, une calculatrice, son but premier, ce n’est pas d’afficher des nombres (UI), mais de faire des calculs (Rules).
Cette séparation, c’est une règle d’or du développement qui va énormément améliorer la qualité de votre code, sa maintenabilité (et donc sa pérennité), mais aussi votre travail d’équipe, puisque chacun pourra être dans sa zone de confort et utiliser ses compétences à fond.
Pour reprendre les points précédents :
- Il sera très facile d’identifier d’où vienne les erreurs et de les corriger.
- Vous pourrez ajouter ou modifier la logique et l’interface sans embêter personne.
- Vous n’aurez même pas besoin de vous préoccuper de la logique pour implémenter le travail d’un designer.
- Les développeurs front end et back end pourront travailler chacun dans leur coin sans se marcher sur les pieds.
- Vous pourrez changer d’interface comme de chemise, et même recycler vos règles dans une autre application sans aucun problème. Super utile quand vous voulez faire une version mobile de votre application par exemple.
Sur le papier, ça en jette ! Mais en pratique ce n’est pas toujours facile à implémenter. Si vous utilisez un framework MVC type Symfony (PHP), Sails.js ou ASP.NET MVC, forcément, c’est simple comme bonjour, vu que se sont littéralement des solutions toutes faites présentées sur un plateau d’argent.
Mais si vous utilisez du pur PHP, du C++ avec Qt ou des Winforms, il va falloir se creuser les méninges un petit peu plus, mais ça reste possible ! Et je vais justement vous donner quelques pistes de réflexion pour vous aider.
Modèle - Vue - Contrôleur
Le fameux design pattern MVC. Indémodable, et ce n’est pas pour rien puisque c’est un des plus simples et efficaces. Je ne vais passer que rapidement dessus, déjà parce qu’il est extrêmement connu, et parce qu’il y a tellement de subtilités que cela mériterait d’y consacrer un article complet.
Mais le principe de base, c’est que l’on va venir diviser notre code en 3 parties :
- Le modèle : ça va correspondre à des classes métiers de votre application, qui vont généralement représenter des choses concrètes de notre monde. Par exemple, pour une application de gestion de stocks, on pourrait imaginer des classes Article, Entrepot, Commande… Le modèle est intimement lié à la base de données de l’application, mais je ne vais pas rentrer dans les détails.
- La vue : un fichier contenant l’interface graphique toute cuite, sur laquelle il ne vous reste plus qu’à y coller vos données. C’est une sorte de texte à trous de la programmation en fait. Il y a plein de manières différente de faire des vues (HTML, pile d’appels, templates…) mais une fois de plus, je ne vais pas m’y attarder.
- Le contrôleur : exploite les données du modèle et effectue des traitements pour retourner un résultat. On peut séparer les contrôleurs en deux types distincts.
- Les règles : les fameux traitements qui vont constituer le cœur de votre application. Il s’agit de simples fonctions reposant sur une base paramètres ➔ traitements ➔ résultat.
- Les contrôleurs graphiques : ils vont servir à récupérer les données et effectuer les traitements nécessaires pour pouvoir initialiser l’interface graphique à l’aide de la vue. La boucle est bouclée.
Généralement, on implémente le pattern MVC à l’aide d’un framework conçu pour ça, mais contrairement à ce que beaucoup pensent, le principe du MVC est assez simple pour être utilisé avec n’importe quelle technologie. Dans mon bonus, j’explique comment vous pouvez l’implémenter assez facilement en PHP pur, sans aucun framework.
Règle - Vue - Événement
Là où le paterne MVC est plus dédié à l’initialisation de l’interface, donc toute la partie back end, je parlerais plus de paterne RVE (un terme que j'ai inventé) pour ce qui concerne les traitements en temps réel.
Mais le principe est sensiblement le même et consiste encore une fois à diviser le code en 3 parties :
- Les règles : ce sont toutes les règles et classes métiers de votre application. Le nom n’a rien de confus, car ce sont exactement les mêmes que l’on retrouve chez MVC : les modèles et les contrôleurs-règles.
- La vue : c’est quasiment la même chose qu’en MVC, sauf que là où une vue MVC va être pensée pour ne recevoir des éléments uniquement l’initialisation, la vue RVE va être pensée pour être modifiée en temps réel. Par exemple : une Razor Page sera une vue MVC, alors qu’une Blazor Page sera une vue RVE.
- Les événements : les actions qui vont se déclencher quand l’utilisateur va interagir avec la page.
Une chose que je vois souvent, c’est que les gens ont tendance à faire la séparation UI/Rules dans leur back end via MVC, mais pas pour le code front end, et il n’est pas rare de voir des règles métiers inclues dans des événements JavaScript, ce qui est tout aussi préjudiciable.
En effet, les événements sont sensés jouer exactement le même rôle que les contrôleurs graphiques MVC, ils récupèrent les données venant des règles et mettent à jour l’interface graphique en conséquent, c’est la même chose.
Étant donné que MVC se fait en back end, on est assez libre sur les technologies utilisées, ce qui n’est pas le cas du RVE qui se fait essentiellement en front end
Du coup, il y a plusieurs écoles pour implémenter le paterne RVE :
- Implémenter les règles et classes métiers en front end. C’est la méthode la plus simple, mais très peu sécurisée, car l’utilisateur final y a potentiellement accès. Et en plus de ça, vous ne regroupez pas toutes vos règles ensemble ce qui est un peu dommage.
- Uniformiser les technologies front end et back end. C’est très pratique, mais ça ne marche pas avec tous les langages.
- Utiliser des API REST.
API REST
Les API REST, c’est le cheat code de la séparation UI/Rules. Elles vont vous permettre de pouvoir déconnecter complètement vos règles de votre front end pour les rapatrier sur votre serveur, et pouvoir uniformiser vos technologies pour toutes les règles.
Le principe d’une API REST, c’est que vous allez créer une méthode qui va être consultable par une requête HTTP, et qui va permettre de retourner un résultat simple à exploiter dans une réponse HTTP. Les plus malins d’entre vous auront déjà remarqué que les contrôleurs graphiques ne sont ni plus ni moins que des API REST qui retournent un résultat en HTML.
public List<Product> GetAllProducts()
{
Product[] products = new Product[]
{
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
};
return products;
}
Pour ce qui est de la logique métier, on préférera faire des API REST qui retourneront des données sous format XML, JSON, ou même du simple texte, pour pouvoir les manipuler facilement dans nos événements.
Chose importante, c’est que les API REST vont souvent être appelées avec des requêtes HTTP asynchrones, afin de ne pas dégrader l’expérience utilisateur si jamais il y a du lag. Ça rend la syntaxe des appels un peu plus compliqué, mais la plupart des langages gèrent ça très bien. Voici un exemple de requête asynchrone avec JavaScript et JQuery.
$.ajax({
url: "helloworld.txt",
success: function(result){
$("#hello-div").append(result);
}
});
Un autre avantage extrêmement intéressant des API REST, c’est que vos règles deviennent 100% indépendantes de votre interface. Ainsi, vous pourrez utiliser vos règles depuis n’importe où : une version mobile, d’autres applications, voir même rendre vos API disponibles au public afin que d’autres développeurs puissent les exploiter, comme c’est le cas avec l’API de Twitter.
Avec ça, je pense que vous aurez déjà une très bonne séparation UI/Rules. Il doit y avoir d’autres moyens d’optimiser la séparation encore plus, mais si j’avais dû aller dans les détails, j’aurais écrit un livre plutôt qu’un article. Pour le moment, voici un schéma final qui résume tout.
Sachez simplement que plus la séparation UI/Rules va être rigoureuse, plus les bénéfices seront importants.
Maintenant, une question subsiste : comment implémenter cette méthodologie dans n’importe quel programme ? Comme je l’ai dit, pour certains ça va être évident, et pour d’autres, il va falloir se creuser un peu la tête. Mais retenez une chose : Les méthodes énoncées ci-dessus sont implémentable avec toutes les technologies, même sans framework. Dans mon bonus, j’implémente cette méthodologie avec du pur PHP, sans aucune aide.
La méthode pour y arriver va dépendre de vos langages & frameworks, mais voici ce que vous pouvez faire dans l’ordre :
- Faites un plan de la fonctionnalité que vous allez implémenter afin d’avoir une idée de ce à quoi va ressembler le code.
- Analysez ce code, divisez-le en différentes parties et rangez ces parties dans les cases suivantes :
- S’il s’agit d’une classe représentant quelque chose de concret, c’est un modèle.
- S’il s’agit d’un comportement lié au cœur de votre application, c’est une règle métier.
- S’il s’agit d’une méthode dédiée à l’initialisation des données sur l’interface, c’est un contrôleur, qui va en général faire appel à des modèles et des règles.
- S’il s’agit d’un bout de code qui va aller modifier des morceaux d’interface, et recevoir les actions de l’utilisateur, c’est un événement, qui va lui aussi faire appel à des règles, voir des modèles.
- S’il s’agit de code qui va permettre de construire une interface utilisateur, peu importe la manière (HTML, pile d’appel, template…), c’est une vue.
- Construire un système qui va permettre à ces différentes parties de communiquer sans se mélanger. Ca peut-être via des API REST, une uniformisation des technologies… Pour le coup, ça va dépendre de beaucoup de facteurs liés à l’architecture et la pile de votre projet, à vous de faire le bon choix.
- Codez le tout.
Et voilà, mission accomplie.
Ça fait un moment que je vois des développeurs ne jurer que par leur framework, et se retrouver complètement déboussolé quand ils n’avaient pas une solution toute faite pour implémenter MVC automatiquement. Je vous rassure mes amis, la séparation UI/Rules est possible en toutes circonstances à partir du moment où vous maîtrisez les bases, ce qui ne devrait désormais plus être un problème pour vous ;)
Mais l’épidémie n’est pas endiguée, et encore aujourd’hui, des développeurs inconscients placent leur code PHP au milieu de leur code HTML, et leurs règles métiers top secrètes dans leur script.js. Donc rendez leur service et partagez cet article afin de leur faire prendre conscience de leurs pratiques malsaines, et les faire level-up en matière de génie logiciel.
Et si vous voulez m’entendre parler plus en détails des points que j’ai énoncé, qui méritent largement des articles à eux tout seuls (MVC, RVE et API REST) faites-le moi savoir dans les commentaires, et suivez mon blog afin de découvrir plus de bonnes pratiques toutes plus succulentes les unes que les autres.
Accéder au bonus : La séparation UI/Rules en PHP pur.
Afin d'éviter les spams, messages haineux ou insultants envers les autres commentateurs, tous les commentaires sont soumis à modération.