Un bon framework

Avertissement : je suis l’architecte et l’auteur principal du framework de développement d’applications web et mobiles de Yoocan ; assez logiquement, les idées développées dans cet article correspondent aux principes architecturaux mis en oeuvre dans celui-ci.

Définition

En dehors des cas simples – en termes d’architecture – il est rare de démarrer le développement d’une application de zéro ; en général, on s’appuie sur une structure, un cadre prédéfini, qu’en informatique on nomme d’un mot anglais, framework, qui se traduit par cadre de travail. Des termes français comme « structure logicielle » ou « cadriciel » existent, mais sont peu usités. Un framework est un objet composite visant à simplifier et accélérer le travail de développement : il impose un plan d’architecture général appuyé sur un ensemble de patterns – ou patrons logiciels – et de bibliothèques standards.

L’utilisation d’un framework apporte de nombreux gains :

  • le partage de tâches communes et fastidieuses à développer à chaque nouvelle application : analyse des paramètres d’entrée, contrôles graphiques prêts à l’emploi, etc.
  • des garanties en termes de sécurité, en empêchant le développeur de faire des erreurs communes : injection SQL, cross-site scripting, buffer overflow, etc.
  • des garanties en termes de conformité de fonctionnalités standards vis-à-vis de règles métier, juridiques, techniques : respect des règles comptables, de lois physiques, etc.

La contrepartie réside dans le cadre imposé, et son degré de rigidité, ce qui limitera votre liberté d’agir ; j’y reviendrai.

Un framework peut être plus ou moins spécialisé :

  • le .NET framework ou la plateforme Java permettent de créer pratiquement tout type d’application, du petit utilitaire en ligne de commande au mastodonte distribué, à l’exception des logiciels très proches du métal comme les pilotes matériel
  • CodeIgniter ou Symfony, tous deux basés sur PHP, sont des frameworks adaptés au développement de tous types de site internet
  • DirectShow est un framework pour réaliser des applications Windows multimédias
  • WordPress peut être considéré comme un framework spécialisé dans un type de site internet, les blogs

Le point commun entre tous ces outils est leur capacité à vous emmener de l’α à l’ω du développement de votre application, ce qui différencie les frameworks des bibliothèques ou des patrons logiciels.

L’art du cadrage

Le terme anglais framework a un grand défaut et une grande qualité. D’un côté, il décrit assez mal l’idée d’accompagner les développeurs dans le développement et l’aide apportée, mais de l’autre, il appuie sur un point qui me semble central pour le choix : la notion de cadre, qui induit certaines rigidités.

Les frameworks imposent très souvent des bibliothèques précises pour certaines fonctionnalités génériques (accès aux sources de données, journalisation, etc.) quand vous voudriez utiliser votre pilote de base de données ou votre outil de journalisation préféré.

Il est également assez habituel de démarrer son application avec un jeu de fonctionnalités limité et de choisir un framework très ajusté pour développer au plus vite ; lorsque vient le moment de faire évoluer le logiciel, il arrive très souvent que le framework ne permette pas de développer les nouvelles fonctions, voire pire, qu’il ne puisse pas cohabiter avec des outils tiers. Par exemple, il n’est pas très facile d’intégrer ensemble un blog WordPress et un forum phpBB. Dans un genre plus technique, Facebook avait commencé son développement en PHP, et s’est vite trouvé confronté à de grosses problématiques de performance ; en effet, quand le nombre d’utilisateurs augmente, PHP propose principalement deux façons de distribuer la charge : la mise en cache HTML, impossible de par la nature de Facebook, ou l’augmentation du nombre de serveurs, ce qui aurait induit des coûts délirants. Après avoir hésité à tout redévelopper, Facebook s’en est remis à optimiser la plateforme elle-même, en précompilant les pages PHP avec un outil développé en interne.

Le choix d’un framework est donc un exercice subtil où il s’agit d’équilibrer les gains apportés en rapidité de développement et en fonctionnalités « out of the box » et les limitations de l’outil en termes de configurabilité, d’ouverture et de possibilité d’intervertir ou d’ajouter des composants.

Principaux critères de choix

Pour bien choisir son framework, le plus important est évidemment son adéquation avec le type d’application que vous souhaitez construire ; vous n’utiliserez pas un framework internet PHP pour construire une application Windows classique. En prenant en compte la problématique du cadre décrite ci-dessus, cela peut s’avérer moins trivial qu’il n’y parait ; si vous démarrez un blog, vous vous pencherez très probablement sur WordPress, mais si le but de votre blog est de vendre votre production artisanale, et que la partie blog n’est qu’une manière d’améliorer votre visibilité par le grand public dans votre domaine, que faire ?

Tous les frameworks ont un cœur de fonctionnalités qui a présidé à sa création, déterminé ses choix techniques et fonctionnels fondamentaux ; quand un outil assez ajusté – comme WordPress pour les blogs par exemple – cherche à sortir de ce noyau pour faire un peu du tout – du forum, de l’e-commerce, etc. – c’est souvent une mauvaise idée et il fera presque toujours plus mal ses fonctions annexes qu’un outil spécifique. Je conseille d’éviter le proverbial « qui trop embrasse, mal étreint », et si vous vous appuyez sur un framework spécifique, de limiter son usage à ce qu’il sait nativement très bien faire.

Un autre atout d’un framework souvent cité est sa « communauté », c’est-à-dire l’ensemble de ses développeurs et de ses utilisateurs actifs, et plus précisément, ceux volontaires pour apporter de l’aide technique. Il est vrai qu’une communauté nombreuse est un gage, à un instant t, d’obtenir des réponses rapides à ses questions techniques ; cependant, contrairement à une idée répandue, il n’est pas une assurance de pérennité de l’outil. En effet, on constate généralement que lorsque les développeurs en chef disparaissent, pratiquement quelle que soit la taille de la communauté, les outils tombent dans l’oubli ou sont modifiés de fond en comble par une nouvelle équipe, quand vous avez la chance qu’elle se crée.

Car oui, comme tout en ce bas monde, il arrive que les frameworks meurent. Bien entendu, rien ne vous empêche de continuer à les utiliser, enfin, tant que les plateformes sous-jacentes peuvent les faire tourner, qu’il n’y a pas besoin d’ajouter de fonctionnalités ou de boucher des trous de sécurité, qu’on trouve d’autres orphelins de la communauté pour vous aider… Ce qui m’amène à un autre critère très important pour le choix et qui est assez peu souvent évoqué : s’appuyer sur des standards de l’industrie. Entre un framework avec son propre système de template, son propre langage d’accès aux données, son propre format d’export de données, et un autre qui s’appuie sur le SQL, normalisé par l’ANSI, XSLT, normalisé par le w3c, XML, normalisé par le w3c, on pressent naturellement qu’on trouvera plus facilement de l’aide en dehors de la communauté pour le deuxième que pour le premier.

Enfin, pour revenir sur la rigidité du cadre, avant de s’enfermer dans un choix, il est vital de bien étudier les possibilités que vous laissent le framework d’étendre le cadre ou d’en sortir :

  • l’utilisation de l’inversion de contrôle est généralement un gage de la possibilité de réimplémenter à sa sauce certaines parties du framework
  • dans le cas d’un outil fortement spécialisé, il faut étudier dans quelle mesure il peut s’intégrer dans un écosystème tiers (authentification, autorisation, suivi statistique, charte graphique, etc.), donc de vivre dans un framework plus générique que lui
  • à l’inverse, un outil générique doit être capable d’accueillir en son sein des produits plus spécialisés

Conclusion

Le choix d’un framework est très loin d’être anodin et peut revenir vous hanter pour des années, oscillant entre Charybde – la réécriture complète – et Scylla – maintenir un outil obsolète ou en étendre un mal adapté. De plus, il est très souvent sujet à des guerres de religion dont les informaticiens sont friands – microkernel contre kernel monolithique, Linux contre Microsoft, .NET contre Java, etc., quand ce ne sont pas des béotiens sur les questions techniques qui en imposent un pour des raisons n’ayant rien à voir avec la technologie. Si vous retenez de cet article qu’il faut bien évaluer le cadre imposé, et vous méfier des frameworks vous proposant une énième solution quand des standards techniques internationaux existent, il aura atteint son but.

SharpZipLib, Winzip et Office Open XML

Nous utilisons l’excellente bibliothèque native .NET SharpZipLib pour compresser et décompresser ; elle gère les formats tar, bzip2, gz et tar, fournit des implémentations bas niveau surchargeant Stream et plus haut niveau pour des tâches standards comme décompresser directement un zip dans un répertoire.

Dans le cadre de la mise en oeuvre d’un export xlsx pour notre contrôle tableau, j’ai naturellement utilisé SharpZipLib pour compresser les fichiers – xlsx est en ensemble de fichiers XML zippés. Après quelques erreurs venant du format du fichier XML inclus, qu’Excel me reportait clairement (erreur ligne x colonne y dans le fichier z), Excel continua à me dire qu’il avait du corriger mon fichier mais sans m’indiquer aucune erreur. Ouvert avec winrar, le fichier semblait parfaitement conforme ; pire, comparé à la version PHP, le contenu du zip était au caractère près le même, et pourtant Excel ne disait rien sur le fichier généré par la version PHP.

Je me suis donc naturellement tourné vers l’utilitaire de compression ; après quelques tripatouillages d’options, j’ai trouvé la bonne : UseZip64. SharpZipLib supporte Zip64, qui permet d’avoir des fichiers de plus de 4Go inclus dans le zip. Apparemment, il est connu que cette option est mal supportée par de vieilles versions de Winzip et par l’utilitaire de décompression inclus dans l’explorateur de fichiers de Windows XP ; j’ajoute à la liste au moins Excel, je n’ai pas testé avec Word ou PowerPoint mais j’imagine que ça doit être pareil. Pour que ça fonctionne, j’ai du modifier mon code de la façon suivante :

using(ZipOutputStream zos = new ZipOutpuStream(s)) {
  zos.UseZip64 = UseZip64.Off;
  ...
}

D’après la documentation, la valeur par défaut est Dynamic qui devrait déterminer si ça sert à quelque chose d’activer Zip64 ; dans mon cas, aucun fichier ne dépasse les 100ko, et pourtant il m’a activé Zip64, donc je ne sais pas trop quels sont les critères employés mais j’ai du désactiver complètement Zip64 pour qu’Excel soit content. Si ça peut servir à quelqu’un…

Ce qui n’est pas testé ne fonctionne pas

Lors de mes recherches sur la proposition d’apprendre le code à l’école du Conseil National du Numérique, j’ai retrouvé plusieurs fois l’idée selon laquelle la programmation pouvait être une activité formatrice au sens où elle promouvait un processus de création par essai – erreur où l’erreur n’était pas considérée comme une sanction définitive mais comme une étape naturelle participant à la construction de la solution. Cette idée est également très régulièrement citée comme un des facteurs de la réussite de la Silicon Valley, où un échec n’est pas considéré comme rédhibitoire, mais comme une expérience valorisable comme une autre.

Encore faut-il que les programmeurs s’intéressent au fait que leur programme soit erroné, et d’après mon expérience, c’est souvent là que le bât blesse.

C’est ballot, mais la moindre modification du code doit être testée !

Je vais reprendre un exemple récent arrivé à un de mes développeurs – si il se reconnait, rien de personnel, c’est pour l’exemple – sur une fonction plpgsql ; ça, c’est la première version qui marche (simplifiée à l’extrême bien sûr) :

CREATE OR REPLACE FUNCTION MAFONCTION(V_ID INT, V_MONPARAMETRE BOOLEAN) RETURNS INT AS $$
DECLARE
 V_RESULT INT:=1;
BEGIN
 UPDATE MATABLE SET MAVALEUR=V_MONPARAMETRE WHERE ID=V_ID;
 RETURN V_RESULT;
END;
$$ LANGUAGE plpgsql;

En relisant les spécifications, le développeur s’aperçoit que j’avais demandé que le deuxième paramètre soit optionnel et ait comme valeur par défaut false, et connaissant mal la syntaxe plpgsql, écrit le code suivant – négligeant de le tester, se disant qu’il n’y avait pas de raison que cela ne fonctionne pas :

CREATE OR REPLACE FUNCTION MAFONCTION(V_ID INT, V_MONPARAMETRE BOOLEAN) RETURNS INT AS $$
DECLARE
 V_RESULT INT:=1;
 V_MONPARAMETRE BOOLEAN:=false;
BEGIN
 UPDATE MATABLE SET MAVALEUR=V_MONPARAMETRE WHERE ID=V_ID;
 RETURN V_RESULT;
END;
$$ LANGUAGE plpgsql;

Pas de bol, il se trouve que les paramètres d’une fonction plpgsql peuvent être nommés, mais que ce n’est qu’une sorte de macro ; posgtresql va remplacer toutes les occurrences du nom choisi dans la fonction par le numéro du paramètre précédé d’un $ ; dans notre cas, postgresql ne le fera pas, puisqu’on a défini une variable dans la clause DECLARE qui écrase le paramètre en entrée, et postgresql ne fera ni erreur ni avertissement. Du coup, la valeur de V_MONPARAMETRE sera toujours false, quoi qu’on passe à la fonction. Le développeur est venu une fois fini le reste du travail demandé me dire que tout était terminé ; mes tests d’intégration n’ont bien sûr pas fonctionné, pas plus que mes tests unitaires. Le développeur était pourtant certain d’avoir vu sa fonction marcher, sans doute avant sa dernière modification qu’il considérait comme tellement triviale qu’il n’y avait pas besoin de la tester.

Un exemple historique… et autrement plus coûteux

Le premier vol d’Ariane 5 s’est achevé au bout de quelques dizaines de secondes, détruisant pour 370 millions de dollars de satellites. La source du problème ? Un module de calcul de poussée de la fusée, repris tel quel d’Ariane 4, dans lequel la poussée était stockée sur une variable d’une taille trop petite pour la nouvelle fusée, munie de moteurs plus puissants ; habituellement, en programmation, quand une variable numérique reçoit une valeur trop grande pour sa capacité de stockage, et en l’absence de vérification, la valeur passe à 0 (cas non signé) ou à la plus petite valeur négative (cas signé), donc en tout état de cause une valeur anormalement basse.

Du coup, la fusée s’est crue dans une position nécessitant une intervention immédiate et radicale du pilote automatique pour rectifier la trajectoire, intervention qui a exercé des contraintes telles sur la fusée qu’elle a commencé à se disloquer, aboutissant à l’enclenchement du mécanisme d’auto-destruction, et à un joli mais très coûteux feu d’artifice. Tout ça pour une variable stockée sur 8 bits au lieu de 9 nécessaires, dans un module repris à l’identique, mais… non testé dans les nouvelles conditions.

De ces deux exemples, on peut déduire une première règle : ne jamais oublier que quelle que soit la petitesse de la modification effectuée sur le code, ce qui n’est pas testé ne fonctionne pas.

Et deux tests valent mieux qu’un…

Une autre de mes activités, récemment en croissance, est de débusquer des trous de sécurité, que ce soit sur des sites nous appartenant ou que nous hébergeons ; rien de très évolué, plutôt du très classique : injection SQL permettant de s’identifier avec n’importe quel compte ou de consulter toute une base de données payante sans l’acheter, cross-site scripting lors de la soumission de données pour intégrer du code actif envoyant discrètement des données du site attaqué vers un tiers ou pour faire du hameçonnage, ce genre de choses. Le point commun de ces défauts de sécurité, également commun avec les classiques attaques buffer overflow à la base de la plupart des failles des systèmes d’exploitation ? Le système définit des entrées – par exemple, le premier paramètre doit être un entier, et le deuxième une chaîne de caractères de moins de 256 octets de long – mais ne vérifie pas que les valeurs passées respectent cette définition.

Tendance bien naturelle : quand on programme la fonction et les appels à la fonction puis que dans la foulée, on effectue les tests, il est assez logique de mettre en oeuvre des tests respectant les contraintes qu’on a soit même définies, elles sont assez fraîches dans notre esprit. De nombreuses façons d’éviter ces erreurs existent : faire écrire les tests par une autre équipe que l’équipe de développement est une parade classique, certains langages de programmation incluent ce type de contraintes dans la signature des fonctions comme Ada par exemple, etc. Mais aucune n’est plus efficace que d’être conscient de la problématique et de la mettre au cœur de ses pratiques !

Ces exemples nous permettent d’énoncer une deuxième règle : ne jamais faire confiance aux données envoyées par le client.

Si vous gardez ces deux règles présentes à l’esprit tout au long de vos développements, quels que soient les outils que vous utilisez, aussi protecteurs que vous pensiez qu’ils soient contre les fautes de programmation, vous aurez fait un grand pas vers la production de programmes conformes et sûrs.

Le côté obscur de l’information

L’Union Européenne publie depuis 2014 un indice répondant au doux nom de DESI (Digital Economy and Society Index, Indice d’Economie et de Société Numérique) dont le but est de comparer l’avancement des états européens en termes de pénétration des outils numériques. La France se trouve classée au milieu de la mêlée, avec d’assez mauvaises notes en déploiement du très haut débit et en utilisation par les PME – allez par là pour vous lancer, amies PME – mais des bonnes notes en formation professionnelle et en administration numérique.

Le choix des indicateurs est à mon sens au moins aussi éclairant que les résultats eux-mêmes : l’omniprésence de l’utilisation d’internet, qui pourtant n’existe pour le grand public que depuis moins d’une génération, est frappante, comme si les usages numériques se limitaient quasiment exclusivement aux services disponibles sur internet.

Mais les sous-catégories qui ont particulièrement attiré mon attention sont la 3a et la 3b, usage d’internet / contenu et communication, sensées traiter des contenus et de l’interaction en ligne. Commençons par décrire les indicateurs.

Le contenu sur internet en 2015, objet de consommation ?

L’étude mesure la pénétration des contenus numériques en Europe en évaluant le pourcentage d’internautes consommant des actualités, de la musique, des vidéos et jeux, de la vidéo à la demande et de la télévision par IP, et la communication par les appels voix ou vidéo sur IP et l’utilisation des réseaux sociaux.

Ces indicateurs, combinés les uns avec les autres, dessinent un réseau dans lequel les contenus sont produits par des services centraux, puis poussés vers des consommateurs dont la seule action est le commentaire et le partage. Pour une étude débutée en 2014, c’est un choix assez surprenant, sachant que la révolution du web 2.0 – dont la principale caractéristique est de décentraliser la production de contenus par la démocratisation des moyens de création et de diffusion – est maintenant bien stabilisée. Malheureusement, les choix des indicateurs sont trop peu motivées pour en tirer une quelconque conclusion éclairée ; est-ce un reflet du lobbying des acteurs historiques de la production de contenus ? Est-ce une impossibilité matérielle d’obtenir des chiffres exploitables ? Mystère.

Les résultats n’en sont pas moins intéressants ; par exemple, la France, créatrice du modèle « triple play », est en tête et pas qu’un peu dans les domaines de la télévision par IP et la vidéo à la demande, alors que nous sommes dans les derniers de la classe pour l’abonnement au très haut débit dont on pourrait pourtant penser qu’elle est une condition du déploiement de ces services. Là se trouve résumée la grande faiblesse de cette étude : aucune corrélation n’est faite entre les indicateurs et aucune tentative d’explication n’est apportée ; d’une part, on peut assez facilement attribuer le relatif faible débit constaté en France à la structure géographique de notre pays – les pays plus physiquement centralisés trustant les premières places – et d’autre part, quelle importance accorder à la pénétration du très haut débit si l’implantation des services l’utilisant le plus en semble totalement décorrélée ?

Mais le chiffre le plus amusant est pour moi le 3b2 : la France est la dernière dans toute l’Union Européenne pour l’utilisation des réseaux sociaux, mesurée comme l’écriture de message ou autres contributions à Facebook, Twitter, etc. J’ai immédiatement rapproché ce chiffre d’un concept très rigolo : le « dark social ».

Le « dark social », késako ?

J’ai vu apparaître le terme en fin d’année 2014, ici ou  ; il semblerait qu’après la vague de croissance des réseaux sociaux, et leur tentative d’apprivoisement pas toujours réussie par les entreprises, les services marketings et communication se soient réveillés d’un seul coup pour s’apercevoir que les moutons les consommateurs avaient le front de parler de tout et n’importe quoi en dehors des réseaux sociaux, loin des capacités d’analyse automatisée : échanger des liens intéressants, donner leur avis sur des produits, etc. D’après les évaluations relayées, nous serions les rois de l’OCDE du « dark social », ce qui entre parfaitement en résonance avec les chiffres de l’Union Européenne.

Au delà de l’ironie de voir nommer « dark social » la communication interpersonnelle qui existe depuis la nuit des temps – donc en opposition avec une tendance pourtant extrêmement récente à considérer qu’il est loisible de rendre public ses avis, ses goûts et ses opinions – il me semble intéressant de juger de la pertinence de considérer que c’est une preuve de maturité numérique que d’utiliser massivement les réseaux sociaux.

Maîtriser les nouvelles technologies de l’information, au delà de l’utilisation des outils, ce doit être comprendre ce qu’est une information, quelle est sa valeur, sa qualité, à qui la transmettre et comment ; dans le cas précis des réseaux sociaux, l’idée selon laquelle tout y est public, directement ou indirectement, et que s’y exprimer revient à aller crier à tue-tête sur la place du village, commence à faire son chemin, mais prend du temps à être complètement intégré dans les modes de pensée du grand public.

En ce sens, il me semble qu’une utilisation modérée et contrôlée des réseaux sociaux relève d’une appréhension plus fine des outils numériques ; du coup, le critère 3b2 ne me semble absolument pas pertinent, dans un sens ou dans l’autre. Il faudrait certainement le remplacer par des critères plus qualitatifs sur la façon d’utiliser les réseaux sociaux, mais ils sont probablement très compliqués à définir et à standardiser à l’échelle européenne.

Mais au moins maintenant, vous saurez qu’en envoyant un email à vos amis sur une nouvelle vidéo YouTube, tel M. Jourdain, vous faites du « dark social » sans le savoir !