Sommaire
Petit aperçu commenté de veille de ces derniers jours.
Vous connaissez le principe, ça n'a pas changé depuis la dernière fois il y a bien longtemps. La liste des liens est toujours dispo à la fin. Et pour planter un peu le contexte, ça parle de méthodes, de tests, de javascript, de clojure, de go et d'autres bricoles.
Il n'est pas dit que j'arrive à mieux le tenir que ces derniers temps, mais on va tenter :-)
Un peu de contenu
Méthodes, langages et bonnes pratiques
S'il est un point qui me tient vraiment à coeur c'est celui d'écrire du code maintenable et qui tende à comporter le moins (zéro si possible) de bug.
Si on prend l'aspect maintenabilité il existe en réalité différentes visions qui s'affrontent ou se complètent selon les cas. Si on prend le développement objet il y a tout ce qui tourne autour d'Object Calisthenics, de SOLID par exemple.
Néanmoins il existe d'autres approches. Un article que j'ai lu cette semaine apporte un autre éclairage sur le sujet, très pragmatique j'ai trouvé et très en accord avec les pratiques que nous mettons en place dans divers projets : Write code that is easy to delete, not easy to extend. C'est un article que je vous recommande vraiment de lire.
Et pour illustrer un peu plus le principe, je vais juste vous parler de ce que j'ai réalisé dans un projet actuel. Pour placer un peu le contexte, je participe avec quelques collègues au développement des applications mobile d'hexo+, une caméra volante autonome. Vous comprendrez donc que la sécurité est un sujet hautement critique. Lorsque nous avons entrepris de refondre toute la gestion des alertes (l'ensemble des actions à réaliser lorsque le drone n'a plus de batterie, de gps, perdu la connexion, etc) il s'agissait de faire cela de la meilleure manière possible et avec le moins de régressions possibles. La solution classique aurait été de se lancer petit à petit dans un refactoring des classes concernées. De transformer le comportement jusqu'à avoir quelque chose qui convienne à nouveau. Sauf que cela représente un très gros travail, plutôt en mode big bang (le logiciel devient inutilisable tant que cela n'est pas terminé). Au contraire, nous avons commencé… par ne rien toucher ! Nous avons monté une deuxième architecture de gestion des alertes en parallèle. Pendant un temps les deux systèmes fonctionnaient d'ailleurs de concert. Puis, lorsque le nouveau système s'est avéré suffisament avancé, nous avons simplement débranché et supprimé l'ancien. Au final nous avons porté la notion de maintenabilité et d'évolutivité non pas au niveau des objets mais bien au niveau du système (ce qui compte au final). Mais, et c'est aussi le propos de l'article, cela n'est possible que si nous sommes capables de supprimer l'ancien code. Plus ce code sera dur à supprimer (parce qu'il est présent partout, parce qu'il est mal découpé, etc) plus la tâche sera ardue.
Ecrire un code qui pourra facilement être supprimé c'est l'une des choses les plus importantes pour faire évoluer en douceur un système entier.
Une fois que vous êtes dans cette optique, il vous reste à écrire du code qui réalise réellement ce qu'on attend de lui. Et là… et bien c'est loin d'être simple.
Prenons un exemple qui d'apparence est trivial :
Étant donné une liste de valeur et une valeur, retourne l'index de la valeur dans la liste ou indique qu'elle n'est pas présente dans la liste.
Je suis certain que vous avez déjà réalisé un code du genre. Et que ça n'a pris que quelques lignes. Facile. Maintenant, que vous indique votre code en terme de documentation, de robustesse aux cas limites, de spécifications, de garanties d'exécution normale, etc ? Vous pensez que votre code est bon ? Je vous suggère dans ce cas d'aller tout de suite lire cet article sur les Tests vs Types et vous devriez voir qu'en réalité c'est loin d'être trivial. Et lorsqu'on voit l'effort qui peut être nécessaire pour un code d'apparence si simple, que penser d'un code plus complexe ?
Si vous voulez d'ailleurs aller un peu plus loin, vous pouvez aller lire ce tutoriel à propos de SPARK 2014 qui tente de répondre à exactement la même spécification. Cette fois ci en allant jusqu'à la preuve. Très instructif encore une fois du travail nécessaire pour garantir qu'une si petite portion de code fera bien ce qui a été demandé.
Histoire de rester dans des sujets connexes, connaissez-vous la règle numéro 1 des choses à ne pas faire de Joel Spolsky ?
David Heinemeier Hansson (créateur de Ruby on Rails, Basecamp, etc) n'est quant à lui pas d'accord. Et il vous explique pourquoi (et comment ils ont réécrit plusieurs fois Basecamp) dans cette vidéo.
Javascript
Si vous avez déjà fait du javaScript (What else?) vous avez nécessairement été confrontés à la problématique de bind et au fait que this n'a pas le même comportement que dans la plupart des langages habituels. Après pas mal de bricolages on est arrivé à avoir une solution correcte en ES6 :
$('.some-link').on('click', view.reset.bind(view))
Avec la méthode bind
présente sur les objets on peut ainsi s'assurer que la méthode reset
de view
sera bien appelée sur l'objet view
et non sur l'objet DOM derrière $('.some-link')
. Cette méthode bind
est quand même une grande avancée. Mais ES7 va encore plus loin (même si ce n'est pour le moment qu'une proposition) :
$('.some-link').on('click', ::view.reset)
L'introduction de l'opérateur ::
réalise justement la même chose que le bind
précédent avec une plus grande lisibilité et de manière un peu moins verbeuse. Si vous voulez en savoir un peu plus sur cet opérateur (qui ne fait pas que le bind
) je vous suggère d'aller lire cet article.
Toujours du côté des nouveautés JavaScript, si vous avez un peu suivi ce qui se passe depuis quelque temps (ok, ces dernières années en fait) le code que nous écrivons est de plus en plus tourné vers de l'asynchrone (parfois à l'excès malheureusement). Et qui dit code asynchrone dit souvent code difficile à tester. C'est sur ce point qu'une nouvelle bibliothèque de test est sortie avec pour nom le très explicite painless. Elle nous promet d'être plus rapide et surtout de faciliter le test du code contenant des promises, async/await, generators et autres nouveautés ES6/ES7.
Sur le même segment est aussi apparu AVA de Sindre Sorhus. Plus rapide, adaptée à toutes les nouveautés du langage mais aussi avec le point particulier d'exécuter les tests en isolation pour éviter tout effet de bord et s'adapter au matériel actuel pour de meilleurs performances.
Clojure
De manière personnelle j'ai toujours apprécié utiliser de nombreux langages différents. Et ça tombe bien, dans mon taff aussi :-) Et s'il en est un qui sort un peu du lot par son style c'est bien clojure. Fonctionnel, bourré de parenthèse (Lisp signifie bien Lots of Irritating Single Parentheses non ?) mais tellement expressif et concis qu'il est difficile de ne pas tomber sous le charme :-)
Et justement, si vous vouliez savoir comment il est possible de passer d'un magnifique amas de ces parenthèses à un bytecode pour JVM (et que vous avez quelques heures devant vous…) voici un magnifique article sur le sujet : Clojure Compilation: Parenthetical Prose to Bewildering Bytecode
Toujours à propos de clojure, voici un petit tutoriel très bien amené qui présente comment réaliser une interface d'administration de blog à base de Om et de clojure script. Om est un binding clojurescript pour react. Le code présenté est plutôt intéressant, ce que j'ai apprécié est la concision et la facilité de traitement des requêtes asynchrones, un peu comme on ferait avec async/await en ES7 mais ici au travers de channels et, surtout, sans promises. Finalement comme si on utilisais des goroutines
S'il est une notion centrale à clojure et l'ensemble des langages fonctionnels, c'est bien l'immutabilité. Néanmoins, savoir l'expliquer simplement n'est pas toujours aisé. Voici un article qui se propose d'expliquer l'immutabilité à partir un post de blog. Plutôt réussi, il devrait vous permettre de comprendre la base ou de la faire comprendre facilement.
Go
Un point qui peut être déroutant au début lorsqu'on vient de ruby, nodejs ou autre est l'absence d'un gestionnaire de paquet dédié au langage. Et lorsque je lis So you want to write a package manager je me dis que finalement c'est très (très) loin d'être trivial. Mais cela permet aussi de mettre en exergue les problèmes que d'autres gestionnaires peuvent avoir (bien que parlant de Go, cet article est très généraliste). Par exemple bower
n'avait pas d'équivalent aux fichiers de lock permettant de reproduire une installation d'un poste à l'autre.
A l'autre bout de la chaine, il y a l'exécution et la mise à jour des programmes. overseer est une bibliothèque qui agit sur cette partie critique en production : monitorer, redémarrer et mettre à jour des binaires Go. Attention il n'est pas encore à un stade utilisable en production (ou à vos risques et périls) mais à surveiller et garder sous le coude dès qu'il sera prêt.
Git, vous connaissez ? Outre l'outil de gestion de sources tel qu'on l'entend, une chose que j'adore avec est de pouvoir facilement l'intégrer dans une application, y compris en tant que base de données. Sur le marché, en général la solution est d'utiliser un binding au dessus de la libgit2. La plupart des langages en ont, Go y compris. Néanmoins, une nouvelle bibliothèque a vu le jour récemment, et elle ne se base justement pas sur libgit2. Attention tout de même, elle n'est faite que pour de la lecture, il n'y a pas d'écriture possible avec. Il s'agit de go-git et elle est utilisée par source{d} qui entre autre analyse l'ensemble des dépôts de github ! A tester plus en avant et voir ce que ça apporte réellement de plus (ou de moins) que le binding Go qui existait déjà.
Sécurité
Un point toujours central dans la sécurité de nos applications est la manière dont on stocke et compare les mots de passes. Hors de question ici de les garder en clair dans une base ! Par contre, régulièrement les bonnes pratiques changent ou, simplement, de nouvelles bibliothèques apparaissent pour nous faciliter la vie (et hors de question ici de réinventer la roue). Voici donc un article qui vous présente les bonnes manières de stocker un mot de passe en 2016 et ceci dans 6 langages différents.
Divers
En tant que développeur nous avons souvent tendance à nous cacher derrière la technique, derrière la création d'outils et non leur usage. Pourtant il est nécessaire d'avoir conscience que l'usage fait de nos développement peut avoir des impacts non négligeables, autant dans des bons que des mauvais côtés. C'est (une partie au moins) du message que Stéphane Bortzmeyer a tenté de faire passer lors du Mix-IT 2015.
Dans un tout autre registre, regardez comment un réseau de neurones entraîné sur des milliers de photos arrive à coloriser des images noire et blanc. C'est fascinant et plutôt juste comme résultat !
Et comme on apprécie les Lego, on ne peut que rester admiratif devant cette machine tout en Lego qui plie et lance un avion en papier !
Liste des liens
Méthodes, langages, etc
Javascript
Clojure
- Clojure Compilation: Parenthetical Prose to Bewildering Bytecode
- Om
- ClojureScript: Real world app
- Explaining immutability
Go
- So you want to write a package manager
- overseer
- libgit2
- go-git A low level and highly extensible git client library
# micro erreur
Posté par Dreammm . Évalué à 2. Dernière modification le 18 février 2016 à 15:48.
La fonction bind date déjà d'ECMAScript 5.
Et sinon je te conseille de regarder Om Next, la future version d'Om : plein de bonnes idées
[^] # Re: micro erreur
Posté par CrEv (site web personnel) . Évalué à 3.
Au temps pour moi, en plus on m'avait fait la remarque avant que je publie (c'est ça d'avoir aussi des collègues qui moulent ici :-))
Je me suis fait avoir par l'article qui comparait ES7 et ES6 et j'ai indiqué ES6 mais en effet ça date d'ES5. Merci de la précision.
Sinon pour le moment j'utilise plutôt reagent que Om. Faut dire que ça marche plutôt bien.
# Tests vs Types
Posté par kantien . Évalué à 3.
Un commentaire pour ajouter des compléments de lecture à ton article tests vs types, qui est relatif aux questions : comment définir les spécifications d'un code ? et comment être certain que le code répond bien à ses spécifications ?
Un journal récent de Big Pete m'a rappelé les excellents cours de Gérard Berry au Collège de France. Sur le sujet en question, il y a tout le cours de l'année 2014-2015 : Prouver les programmes : pourquoi, quand, comment ? ou celui de cette année structures de données et algorithmes pour la vérification formelle (la première leçon et le séminaire qui suit est une bonne présentation, avec des exemples en Java et intégration dans les commentaires du code).
Comme l'article auquel tu renvoies traite de Haskell et de Idris (du ML made in England), il y a l'équivalent made in France. Dans un ancien journal Qui fait des trucs "cool" en France et en Europe ?, j'avais essayé d'expliquer les principes à la base de la différence entre OCaml et Coq et pourquoi le système de types du second permet de se dispenser des tests unitaires.
Au passage, comme tu abordes aussi la question des gestionnaires de paquets, OCaml dispose du sien : opam dont l'architecture est basé sur les résultats de recherches du projet Mancoosi (qui a aussi servie au projet Debian pour son assurance qualité), en particulier sur la nature NP-complet du problème de gestion des dépendances.
Last but not least, en rapport avec la compilation clojure vers du bytecode JVM, la machine virtuelle Coq (qui est LE langage fonctionnelle le mieux typé) a été compilé en javascript via OBrowser (et tourne donc dans un navigateur) par une start-up française : edukera.
P.S : le journal de Big Pete renvoie a une leçon en cours sur les réseaux neuronaux convolutionnels qui permettent, en autre, de faire de la reconnaissance d'images. ;-)
Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.
# Types a quel prix?
Posté par reno . Évalué à 2.
L'article Test vs Types est intéressant, mais bon quand on clique sur le lien pour l'implémentation en Idris, ça calme carrément sur les types: autant de lignes et de difficultés pour prouver un bout de code trivial?
Non, merci..
[^] # Re: Types a quel prix?
Posté par CrEv (site web personnel) . Évalué à 5.
Si je ne me trompe ce ne sont pas les types qui calment, mais la preuve.
Après le non merci, c'est rapide comme jugement. Parfois tu veux vraiment prouver que ton code fait ce que tu lui as demandé. Et oui ça a un coût.
Ce qui est intéressant dans SPARK (en tout cas le 2014) c'est que tu peux alterner en disant que telle portion est uniquement couverte par des tests unitaires, telle portion est prouvée. Justement dans le but de réduire le coût total.
Mais ce que je trouve intéressant c'est que justement, même pour un cas hyper trivial comme chercher un élément dans une liste on se rend compte que ce n'est pas trivial au final. Rien que la valeur de retour lorsqu'on ne trouve pas d'élément est un vrai problème.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.