Cette fois, je ne veux pas parler d’une fonctionnalité géniale d’IRIS (qui en possède de nombreuses), mais plutôt d’une fonctionnalité qui manque cruellement.
Aujourd’hui, parler de POO n’est pas sexy. Bien que presque tous les langages de programmation modernes implémentent une sorte de POO, les discussions sur les problèmes fondamentaux du développement logiciel ne sont pas très courantes entre les développeurs de technologies telles que les développeurs. En fait, l’informatique dans son ensemble n’est pas un sujet courant parmi les développeurs, ce qui devrait l’être à mon avis.
Dans cette communauté de développeurs InterSystems, la plupart des messages portent sur des questions (Comment puis-je… ?) sur la façon d'utiliser la technologie ou sur des solutions pratiques à un problème (Comment puis-je… ?).
Mais peu d’entre eux portent sur les concepts fondamentaux de l’informatique et sur la manière dont ils sont implémentés (ou non) dans notre plateforme de données préférée.
Comment peut-on utiliser un concept fondamental tel que la POO, sans en discuter sur la manière dont il est implémenté sur votre plateforme préférée ?
C'est la même chose pour tout le monde qui utilise (et a des opinions sur) les API REST sans même savoir ce que signifie REST ou avoir lu la thèse de Roy Fielding.
Ou en utilisant le concept d'ESB et en ne sachant rien du livre de Dave Chappel dans lequel il a introduit pour la première fois le terme Enterprise Service Bus.
(Mal)Utiliser le terme « agile » sans jamais avoir lu le Manifeste Agile.
L'un de mes livres préférés de tous les temps sur l'informatique et la POO est le livre de Bertrand Meyer Object-Oriented Software Construction (2e édition) (OOSC), un classique sur la qualité, la robustesse, l'extensibilité et la réutilisabilité des logiciels, et pourquoi la POO est une solution pour bon nombre de ces problèmes.
Tout développeur utilisant des classes, des objets, des méthodes et des héritages devrait lire ce livre.
Sur la base du travail de DataTree, InterSystems a réalisé une excellente implémentation POO avec les extensions Caché et Caché Object Script pour Mumps. Excellent héritage multiple (sur lequel j'écrirai probablement un autre article) et polymorphisme, non seulement dans le langage de programmation mais aussi dans la base de données. À mon avis, la seule (mais unique) combinaison qui implémente véritablement la POO : le code et les données en un seul endroit.
Mais ce qui manque à IRIS et qui est décrit en détail dans OOSC, c'est une fonctionnalité qui pose une couche de robustesse concise sur la POO appelée Design by Contract.
Ce que nous voyons souvent dans le code (méthodes) est :
méthode getMail(id) → Mail
S'il n'y a pas d'id, la méthode renvoie « L'identifiant est requis »
C'est ce que nous appelons la « programmation défensive », la méthode appelée s'arme contre les invocations « illégales ».
Mais le « contrat » de la méthode est évident : si vous me donnez un identifiant (valide) je vous renverrai l’e-mail associé, ce code, exécuté à chaque invocation, ne devrait pas être nécessaire. De cette façon, la responsabilité est transférée de l’appelant à la méthode appelée.
DbC est tout cela, le « contrat » d'une classe ou d'une méthode ou d'une instance d'objet de cette classe indique précisément ce qui est attendu en entrée et ce qui est promis en sortie tant que l'appelant adhère au contrat de la méthode (ou la classe dans son ensemble).
DbC est une programmation défensive sous stéroïdes, sans la pénalité d'exécution consistant à tout vérifier : vous décrivez toutes les contraintes au moment de la conception.
DbC dispose de deux modes d'exécution : développement et production.
En mode développement, toutes les contraintes et vérifications sont exécutées et rapportées.
En mode production, ils ne seront exécutés qu’en cas d’exception.
Comment DbC fait-il cela ?
Au niveau de la classe, vous définissez des « invariants » : des conditions qui doivent être remplies à tout moment (saisie des méthodes de constructeur exclues).
Au niveau de la méthode, vous définissez des pré-conditions et des post-conditions.
Avant même d’exécuter une seule ligne de code, les conditions préalables doivent être remplies.
Après avoir exécuté le code de la méthode, les post-conditions doivent être remplies, pour que pour chaque propriété il y ait une « ancienne » valeur, la valeur qu'avait la propriété avant l'exécution de la méthode.
Et tant pour entrer que pour sortir de la méthode, les invariants doivent toujours être valides.
En mode développement, ces conditions seront toutes exécutées. À ce niveau, vous pouvez choisir comment gérer les conditions non remplies : générer une erreur ou simplement signaler l'événement.
En mode production, les conditions ne seront pas exécutées, mais en cas d'exception dans la méthode, les invariants et les pré-conditions seront vérifiés et feront partie des informations sur l'exception, après quoi une erreur sera générée à tout moment.
Vous pouvez également définir une méthode de « sauvetage », un code qui est exécuté lorsqu'une exception se produit, depuis la définition des valeurs de la base de données, la fermeture des fichiers et des connexions, l'exécution du code de réparation, etc. Vous pouvez même définir un indicateur « réessayer ».
Bien entendu, vous pouvez également obtenir ce dernier résultat avec les mécanismes $ZTrap ou Try-Catch standard d'IRIS.
Pourquoi devrions-nous vouloir DbC dans IRIS Objectscript ?
Je pense que le code sera beaucoup plus robuste et, n'ayant pas à se soucier des pénalités de performances au moment de l'exécution, les conditions peuvent (devraient) être assez élaborées.
Après avoir construit le bon ensemble de conditions, les tests unitaires ne seraient guère nécessaires, les « tests » seront exécutés à chaque invocation d’une méthode. Et, contrairement aux frameworks de tests unitaires séparés, les conditions sont directement dans le code, c'est aussi dans la documentation.
Si DbC est si génial, pourquoi n’est-il pas largement appliqué ?
Revenons à mon introduction : l'ignorance.
Comme les développeurs, en général, ne « font » pas d’informatique, ils ne seront jamais en mesure de saisir l’essence des concepts fondamentaux de l’ingénierie informatique. Mais, pire encore, les enseignants, les programmes de formation professionnelle et les « experts » connaissent à peine le concept DbC.
Les tests (unitaires) sont un concept beaucoup plus facile à comprendre que la rédaction d'un « contrat » pour des classes ou du code.
Je m'attends également à ce qu'il soit assez difficile à intégrer dans un langage ou un compilateur existant.
Il existe quelques langages intégrant DbC, le plus important étant Eiffel, un langage, ce qui n'est pas surprenant, conçu par Bertrand Meyer.
Chez InterSystems, la tendance semble s'éloigner lentement d'ObjectScript, en particulier avec la fonctionnalité Embedded Python, ce qui est une brillante initiative.
Mais du fait qu'ObjectScript pourrait intégrer DbC, le langage bénéficierait d’un formidable élan pour la conception d’applications robustes.
Il serait intéressant de savoir ce que les principaux développeurs d'ObjectScript ont à dire à ce sujet.