samedi 20 février 2016

Virtualisation, principes et usages

Dans l'optique d'expliquer ce qu'est le cloud computing ou "informatique dans les nuages", il nous faut comprendre les problèmes auquel répond cette forme d'informatique, et nous avons commencé à aborder ceci dans cet article sur la haute disponibilité ; nous allons en dire un peu plus encore.

Mais il est temps d'en dire un peu plus sur les technologies de virtualisation qui sont à la base d'une partie importante de cette nouvelle forme d'informatique.

Qu'est ce que la virtualisation

L'informatique est, à la base, une forme de virtualisation de la réalité : les logiciels divers et variés ne font que rendre immatériels sous une forme numérique (c'est à dire constituée  de 0 et de 1) les artefacts du monde réel : fichiers de traitement de texte vs manuscrits, images numériques vs photographie argentique, email vs courrier etc.

Le plus souvent l'informatique ne créé rien dans un premier temps mais reproduit avec ses moyens les activités humaines ; puis s'appuie dans un second temps sur ses capacités de traitement dé-multipliables à l'infini pour dégager de nouvelles façons de faire, de nouveaux "usages" comme on aime dire.

Ce recours à l'informatique est sans cesse croissant depuis 2 ou 3 décennies et ne fait que s'accélérer. On assiste à une transformation en profondeur des usages de l'informatique qui pénètre tous les domaines. On entend souvent le terme de '"digitalisation" (ou encore plus pédant : transformation digitale) qui est une très mauvaise traduction de l'anglais et n'a en fait pas grand sens au niveau étymologique. Mais c'est le terme consacré ; c'est ainsi, le marketing a encore frappé.


Et en poussant cette logique à l'extrême, on en vient à virtualiser les ordinateurs eux même.

Les systèmes de virtualisation ce sont donc simplement des logiciels qui permettent de simuler le fonctionnement d'un ordinateur avec l'ensemble de ses composants matériels, son système d'exploitation, les logiciels qui y sont installés, et les données qu'il stocke sur ses périphériques de stockage (disque dur).

La forme virtuelle d'un ordinateur prend donc la forme d'un fichier (ou d'une série de fichiers) qui nécessite pour être exploité un logiciel spécifique. Comme un document Word nécessite le traitement de texte du même nom, un fichier Excel le tableur du même nom, une vidéo un player vidéo sachant en exploiter le format etc.

Les logiciels qui permettent de créer des ordinateurs virtuels proposent une interface qui permet de décrire l'ordinateur qu'on veut virtualiser : architecture processeur, nombre de coeurs du processeur, quantité de mémoire, type de firmware (bios ou uefi), taille du disque etc.

Les logiciels qui permettent d'exploiter ces ordinateurs virtuels permettent de les démarrer, comme on le ferait en appuyant sur l'interrupteur d'un vrai PC, de les éteindre, de les rebooter (bouton reset) etc...

Une fois un ordinateur virtuel démarré, la première chose à faire est d'y installer un système d'exploitation, comme on le ferait pour un vrai ordinateur, puis ensuite on l'utilise comme un vrai : installation de logiciels, utilisation des logiciels etc.

Et cette capacité de virtualisation a permis l'essor de nouveaux usages au fur et à mesure qu'on s'est familiarisé avec l'idée et qu'on a pris conscience des possibilités nouvelles qu'elle offrait.

A partir d'ici nous utiliserons l'acronyme VM (Virtual Machine) pour désigner une machine virtuelle.

Deux types de logiciel de virtualisation

On appelle hyperviseur un système de virtualisation.

Le premier type de système de virtualisation est constitué d'applications qui s'installent et s'exécutent sur un système d'exploitation, de la même façon qu'un navigateur, un traitement de texte ou tout autre logiciel auquel vous êtes accoutumés.

Les produits les plus connus sont probablement Workstation Player (de la société VMWare), VirtualBox (de la société Oracle, anciennement Sun) mais il en existe d'autres. Ces produits sont gratuits, ils se téléchargent et s'installent simplement en quelques minutes.

Le second type de système de virtualisation est constitué d'un système d'exploitation dédié qui s'installe donc sur un ordinateur physique, ou d'un service optionnel fourni par un système d'exploitation traditionnel.

Activation de Hyper-V sous Windows

Les produits les plus connus sont probablement ESX de la société VMWare (qui est leader dans le secteur et a largement contribué par ses produits à la large adoption de la virtualisation), KVM (solution open source basée sur le noyau Linux et soutenue par Red Hat) et Hyper-V (Microsoft, anciennement Virtual PC), mais il en existe d'autres.

Ces produits sont disponibles gratuitement en open source ou soumis à licence.

Les logiciels de virtualisation s'appuient pour plus de performance sur des jeux d'instructions supplémentaires fournis par la majorité des processeurs ; cependant, des versions bas de gamme de processeurs peuvent en être dépourvues (point d'attention à avoir pour choisir un processeur si on prévoit de faire de la virtualisation).

Comment ça fonctionne ?

Loin de nous l'idée d'expliquer en détail le fonctionnement d'un hyperviseur, nous nous contenterons de brosser un tableau général.

Tout d'abord, il faut avoir en tête qu'en informatique, tout est architecturé en couches successives : chaque couche s'appuie sur la couche immédiatement inférieure qui lui expose les services dont elle a besoin, et n'a connaissance que de cette couche. 

Chaque couche constitue une couche d'abstraction pour la couche supérieure : elle est là pour lui masquer la complexité des problèmes qu'elle gère.  

La couche supérieure exploite donc les services et s'en sert elle même pour faire son propre job et fournir à son tour des services à sa couche supérieure (a qui elle épargne les détails de mise en oeuvre) etc.

Prenons un exemple approximatif mais réaliste. Le micro-contrôleur (couche 1) d'un disque dur masque l'utilisation des moteurs et autres éléments mécaniques au driver (couche 2). Le driver (ou pilote) masque les spécificités de chaque modèle de disque dur en fournissant une interface commune à tous les modèles au système d'exploitation (couche 3). Le système d'exploitation fournit une API bas niveau aux applications qui ont ainsi la possibilité de lire et écrire des fichiers Certaines applications, comme l'interpréteur d'un langage interprété constituent une 4éme couche et fournissent des instructions pour les programmeurs qui vont pouvoir écrire des programmes destinés cette fois ci à des êtres humains, qui constituent la dernière couche. Et encore on pourrait imaginer une couche de techniciens spécialisés manipulant les programmes pour fournir un service à des donneurs d'ordre, eux mêmes prestataires consommant les résultats ainsi obtenus pour les agréger avec d'autres sources d'informations et constituant ainsi une nouvelle couche vis à vis d'un consommateur final : et ici encore on se rend compte que cette organisation en couche n'est une fois de plus qu'une reproduction des activités humaines.

Un système d'exploitation hébergé par un ordinateur virtuel croit parler à la couche matérielle (par l'intermédiaire d'un pilote en général) mais en fait une couche est intercalée : l'hyperviseur.

Il se charge de faire le lien avec la couche inférieure (le vrai matériel) mais il en profite pour jouer son rôle, par exemple en arbitrant l'utilisation des ressources réelles de la machine entre plusieurs VM.

Donc au final, on a un hyperviseur qui se fait passer pour le matériel. Le système d'exploitation virtualisé fonctionne de la façon habituelle mais au lieu de parler avec le matériel d'un ordinateur sur lequel il serait installé, il parle avec l'hyperviseur.

Ce qu'il est primordial de comprendre, c'est que pour la VM c'est totalement transparent : le système d'exploitation n'a aucunement conscience d'être virtualisé.

A quoi ça sert ?

Il y a de nombreux usages, et probablement d'autres à inventer, nous en citons quelques un, à commencer par les plus basiques et les plus évidents.

Pouvoir disposer simplement et à moindre coût d'environnements multiples

La virtualisation permet de disposer d'une multitude de configurations de façon simple. Si on a besoin d'avoir des ordinateurs sous différentes versions de Windows, Linux, Mac OS, ou avec différentes architectures processeurs, on n'a plus besoin d'avoir 1000 m2 d'entrepôt pour stocker tous ces matériels. Il faut juste un bon disque dur pour stocker les machines virtuelles : ben oui, ce n'est plus du matériel mais une virtualisation de matériel.

Au delà du côté pratique, il y a un côté financier : le matériel n'est pas gratuit. Les solutions de virtualisation non plus mais c'est quand même beaucoup moins cher.

Et pourquoi aurait on besoin de tout ce matériel toutes ces configurations ? Hé bien par exemple car on développe un logiciel utilisé par des gens qui ont toutes sortes de matériels et d'OS différents. Et il nous faut tester notre logiciel sur chaque plateforme. Egalement, la compilation du produit final ne peut parfois se faire que sur la plateforme cible.

Bien sur, on peut virtualiser autre chose que des ordinateurs ; au hasard et par exemple, les smartphones. Il existe des dizaines de modèles, il n'est guère réaliste de devoir tous les posséder pour faire des tests d'un logiciel pour mobile. Idem pour les tablettes.

Pouvoir disposer rapidement d'un environnement 

Cas de figure : vous signez un contrat avec un client pour développer une application. Il s'agit d'une application qui s'exécutera à terme sur un serveur dans l'environnement du client.

Pour vos tests, vous devez disposer d'une plateforme serveur identique, ou la plus proche possible, de la cible (de celle de votre client). Vous n'en disposez pas nécessairement. Et en admettant que vous en disposiez, elle n'est sans doute pas disponible.

Sans virtualisation, il faudrait commander un serveur chez un fournisseur, il y aurait un coût qui viendrait manger votre marge, et il y aurait surtout un délai de livraison. Or, les délais sont toujours insuffisants et on n'a pas de temps à perdre. Grâce à la virtualisation, la machine virtuelle est créé en quelques minutes (le plus long sera l'installation et le paramétrage de l'OS et des éventuels pré-requis).

Quelles opportunités encore ?

La consolidation des serveurs

Ce point est particulièrement mis en avant par le sociétés qui vendent des solutions de virtualisation.

Il faut savoir que de façon générale, les entreprises dimensionnent le matériel qui héberge une application serveur en fonction de l'activité maximale dudit logiciel. Et c'est bien logique, il s'agit que le système ne s'effondre pas en période de pic d'activité.

Mais du coup, si les pics n'ont lieu que 10% du temps, pendant 90 % du temps le matériel n'est exploité que pour une faible part de ses capacités. Il y a donc du gâchis, d'autant que comme il est très délicat de dimensionner une infrastructure et qu'on ne veut pas prendre de risque, on a tendance à tailler large.

La consolidation consiste à virtualiser les environnements serveurs et à les regrouper sur une machine physique chargé de les faire tourner (un serveur de VM). 

Il s'agit d'une machine puissante et coûteuse, mais beaucoup moins que la somme des serveurs utilisés dans la situation initiale. Comme les VM n'ont pas toutes un pic d'activité en même temps, tout fonctionne (en théorie).

La consolidation de n VM sur un seul serveur a bien sur des limites, on ne peut pas ajouter éternellement des VM sur un seul serveur, il y aura toujours un moment où la somme des besoins de l'ensemble des VM, hors période de pic, dépassera les capacités du serveur. Et il y aura toujours le risque que plusieurs VM aient des pics d'activité simultanés, le risque augmentant de façon statistique avec l'augmentation du nombre de VM sur un même serveur de VM.

Mais les éditeurs ont des solutions à ça : on peut multiplier les serveurs physiques, et mieux encore équilibrer automatiquement la charge des différents serveurs en déplaçant les VM d'un serveur à l'autre, de façon transparente pour les utilisateurs. Et qui plus est de façon dynamique (c'est à dire au moment même ou "on" va se rendre compte qu'un serveur atteint ses limites, le "on" étant ici encore une sonde logicielle ou matérielle).

Parenthèse : la stratégie des éditeurs de solutions de virtualisation

Il existe des solutions de virtualisation qui sont disponibles gratuitement dans des versions "basiques" (en fait toutes je suppose) : elles offrent le service de virtualisation (voire un peu plus) et c'est tout. Il faut se débrouiller ensuite avec le problème de répartition des VM entre serveurs de VM, et plus généralement avec toutes les problématiques liées à l'exploitation de ces infrastructures (supervision, sauvegardes etc.).

Comme bien souvent avec les solutions gratuites, il faut passer par une version payante dite "enterprise" ou "advanced", ou encore par un contrat de support payant, pour pouvoir tirer la quintessence de ces solutions : il faut bien que les éditeurs gagnent de l'argent quelque part pour financer les coûts de développement (et bien sur dégager des marges pour leur pauvres actionnaires).

Les entreprises avec des petits moyens et/ou des petits besoins peuvent tout à fait se contenter des solutions gratuites.

Par contre, si la technologie est adoptée (et c'est généralement le cas car elle a de nombreux avantages), il arrive un moment où inévitablement le recours aux solutions payantes est obligatoire. Et là, le piège se referme... coûts de licences, options innombrables et incompréhensibles, bref les éditeurs dont c'est le métier savent bien tirer le maximum de profit de la bête.

L'alternative est le recours aux solutions open-source. Plus de licence, mais les coûts se situent ailleurs, car il faut recourir à des ressources humaines (des ingénieurs spécialisés en gros) qui d'un part ne courent pas les rues, et d'autres part sont onéreuses. Cette option reste cependant très intéressante pour peu qu'on sache se faire conseiller et qu'on dispose du réseau adéquat.

La Haute Disponibilité

Si vous n'avez pas les idées claires sur le sujet, ce premier article vous donnera le contexte.

La redondance d'une VM est aisée à obtenir puisqu'il suffit de dupliquer une VM pour multiplier le nombre d'instances. 

Même sanction pour la scalabilité horizontale : si on veut paralléliser sur une machine supplémentaire, il suffit de dupliquer une VM et de la mettre en place derrière le répartiteur de charge, tout ceci n'est que de la manipulation de fichier et peut donc s'automatiser.

Et avec la flexibilité qu'apporte la virtualisation, on peut envisager un mécanisme autonome et automatique qui ajuste le nombre de VM en fonction de la charge : la fameuse élasticité. Tout ce qu'il nous faut est un programme qui sache créer automatiquement des VM, et le coupler avec les sondes qui surveillent la charge de nos serveurs de VM (plus facile à dire qu'à faire, mais l'idée de base est simple).

Tout ça est bien beau mais c'est désormais le serveur de VM qui constitue un SPOF. Ici, il faudra passer par l'achat de plusieurs serveurs, et des solutions logicielles ou matérielles commercialisées par les éditeurs.

Et si on veut bien faire, une fois le serveur de VM redondé, il faudra redonder l'espace disque partagé (SAN, NAS, baie de disque dédiée ...), puis les équipements réseau, puis les réseaux d'alimentation électrique, puis les onduleurs, puis les groupes électrogènes, puis les datacenter proprement dits etc... C'est pourquoi on fait généralement appel à des sociétés d'hébergement spécialisées qui mutualisent le coût énorme de tous ces investissement entre une multitude de clients.

La gestion de configuration automatisée

Etant donné que les ordinateurs sont virtualisés, ils peuvent être crées et manipulés de façon automatique par des programmes (ben oui, un ordinateur virtuel c'est juste un fichier). Et l'air de rien ça ouvre des multitudes de possibilités.

En informatique, la gestion de configuration est une discipline très importante : elle consiste à être capable de garder la trace d'un environnement informatique et de le reproduire à l'identique en cas de besoin, même plusieurs mois après.

Il faut être conscient qu'installer un environnement informatique peut être une opération lourde et complexe demandant parfois plusieurs jours entre l'installation du système, sa configuration selon des règles précises, le passage de patchs correctifs à un certain niveau, l'installation de différents applicatifs serveurs, leur configuration, le passage de patchs (encore), l'installation d'applications, leur configuration etc.  Qu'une seule opération diffère et l'environnement final diffère, avec potentiellement des impacts.

Un syndrome courant en informatique est "ça marche sur ma machine" : un programme fonctionne sur la machine du développeur, ou le serveur de test, et dysfonctionne sur son environnement de production. La raison en est souvent une différence entre les environnements. En s'assurant que tout le monde travaille sur le même environnement, on élimine ces problèmes.

Inutile de dire qu'un processus manuel est source d'erreur, et en outre inintéressant dans un environnement virtualisé : ça ne sert à rien d'automatiser la création d'ordinateurs virtuels si on n'est pas capable d'automatiser toute la chaîne.


La virtualisation permet déjà par simple manipulation de fichier de reproduire des machines à l'identique, mais cette façon de faire que nous avons évoquée jusque présent a des limites.

Mais, il existe tout un ensemble de logiciels spécialisés qui savent créer automatiquement des VM et y installer des logiciels selon un plan précis (on parle de provisioning).

Ce sujet est actuellement en plein développement avec des solutions comme Vagrant, Chef, Puppet, Ansible, Docker ... On rejoint ici une des thématique du mouvement DevOps dont nous parlerons dans un autre article.

Cloud privé, Cloud public



Cloud privé

On appelle "Cloud privé" une infrastructure de virtualisation avancée, avec toutes les fonctionnalités évoquées plus haut pour le support de la haute disponibilité (redondance des serveurs de VM, équilibrage de la charge des serveurs de VM par répartition dynamique des VM entre serveurs, et plus si affinité) déployée dans un le centre informatique privé d'une entreprise.

Mais je comprends plus rien : on me dis qu'on parle de Cloud car c'est une forme d'informatique basée sur Internet, et là on parle de cloud privé et il n'y a aucun lien avec Internet... C'est le problème avec le jargon marketing, il n'a pas de sémantique précise, chacun met ce qu'il veut derrière, et ça change selon le sens du vent. Décryptons.

On utilise le terme Cloud privé par opposition au Cloud public qui lui est bien basé sur l'utilisation d'Internet.

En fait, les infrastructures et les logiciels qui permettent de mettre en place, et d'exploiter facilement, une infrastructure de virtualisation ont d'abord été développées pour un usage interne par des sociétés novatrices, qui les ont ensuite commercialisées :  ce fut l'émergence d'une forme particulière de cloud public (au sens d'un modèle économique basé sur la mise à disposition de ressources en location sur Internet) appelé IAAS (expliqué plus bas).

Puis ces solutions se sont répandues et des entreprises ont fait le choix de les déployer au sein de leurs propres centres informatiques (aka datacenter). Dès lors, il n'y a plus de lien avec Internet mais comme c'est la même technologie que celle utilisée par le acteurs du Cloud Public pour leurs offres IAAS, on a appelé ça Cloud Privé.

Cloud public

L'économie du Cloud prend plusieurs formes dont une au moins est directement liée à l'essor des techniques de virtualisation : IAAS (Infrastructure As A Service).

Le principe est de commercialiser la mise à disposition de machines virtuelles qui s'exécutent sur des serveurs de VM qui sont externes à l'entreprise et hébergés "quelque part" sur Internet (donc dans le Cloud), selon un modèle de facturation à l'usage.

Le client loue de la puissance de traitement rendue disponible grâce à Internet, et ne se soucie plus de toute l'infrastructure requise pour disposer des avantages les plus avancés procurés par la virtualisation (haute disponibilité, ajustement automatique des capacités, et donc des coûts, en fonction des besoins, automatisation des opérations poussée au maximum).

Contrairement au "Cloud privé" l'entreprise est déchargée de la gestion de l'infrastructure de virtualisation et de l'exploitation de la plateforme (par contre, ses données sont hors de ses murs ce qui peut être un vrai souci).

Nous détaillerons les différents formes que prend le cloud computing dans un prochain article 

Conclusion

Le premier article sur la haute disponibilité visait à préparer vos esprits aux avantages apportés par la virtualisation en la matière.

Ce second article sur la virtualisation vous fait toucher du doigt l'intérêt qu'il peut y avoir a s'appuyer sur un modèle de consommation de ressources virtualisées via Internet (IAAS).

Le prochain article en dira un peu plus sur ce point, et détaillera les autres formes que prend le cloud computing (SAAS, PAAS, DAAS).

mercredi 17 février 2016

Mythes et légendes de la POO 2/2

Voici donc le second article de cette série qui vise à démystifier certains concepts classiques de la POO. Les choses sont infiniment plus simples qu'on veut bien le faire croire, il faut que ça se sache.


AOP

L'AOP est une des deux techniques fréquemment mise en oeuvre en sous main par la plupart des frameworks pour réaliser leurs tours de magie. 

Par là, je veux dire que quelqu'un qui chercherait à comprendre comment font ces outils pour rendre les divers services qu'il nous offrent, n'aurait aucune chance d'y arriver sans connaissance de ces techniques. 

En effet, la simple utilisation des techniques de programmation "classique" ne permet pas de faire ce qu'ils font.

Attention spoiler ! je dévoile des secrets et je vais me mettre tout la profession à dos (nan je déconne).

Alors AOP ça veut dire Aspect Oriented Programming. C'est parfois considéré comme une extension de la POO même si je trouve ça un peu prétentieux. 

Le plus compliqué dans l'AOP c'est le jargon difficilement compréhensible qui entoure la discipline, et la syntaxe horrible de son langage d'expression (nous verrons ce que c'est). ça sent encore le geek poilu cette histoire. Nous allons soigneusement éviter d'utiliser ce vocabulaire tout pourri.

L'idée de base est très simple et comme d'habitude, pour comprendre la solution, il faut commencer par comprendre problème qu'on vise. 

Le problème à résoudre

Le problème : un investisseur veut démarrer une startup, il lui faut un logiciel qui réalise son idée, Pour faire le logiciel, il lui faut des développeurs. Et les développeurs, ça coûte cher en taux horaire. Mais comme il ne lui faut que 5 écrans, il se dit que ça va aller vite et que ne sera pas cher. Puis quand on lui donne le devis, il défaillit : quoi, comment ça peut coûter aussi cher, je me fais arnaquer ou quoi, expliquez moi ! Mon fils il m'a dessiné mes écrans HTML en 2 jours sur son PC et vous me demandez 2 mois de travail à 3 personnes ?

Et là,on lui explique qu'il faut gérer tout un tas de problématiques techniques bien compliquées et auxquelles il n'a bien sur pas pensé, car comme la plupart des gens qui croient s'y connaître en informatique, il ne voit en fait que la surface des choses (je passe les détails de toutes les problématiques à gérer, l'inventaire serait trop long). Et là, il se rend compte qu'en fait la plus grande partie du temps des développeurs est consacrée à gérer autre chose que les fonctionnalités rendues à l'utilisateur final. D'où le coût.

Si les développeurs passent du temps sur ces problèmes techniques, c'est que leur prise en compte est transverse à l'ensemble des développements : tous les écrans (ou presque) nécessitent une gestion de la sécurité pour contrôler l'accès aux seules personnes authentifiées et avec le niveau de droit requis, tous les écrans (ou presque) impliquent de contrôler l'ouverture et la fermeture d'une connexion vers la base de données, etc.


Tous les écrans impliquent une gestion d'erreur rigoureuse qui permet de loguer les problèmes pour avoir une chance de les détecter et de les résoudre. En effet, quand l'internaute hurle chez lui car l'application vient de planter, et qu'il a perdu sa saisie, on ne l'entend pas depuis Bengalore en Inde.

Dans l'espace (d'internet) personne ne vous entend crier.


Tous ces points ennuyeux et sans réelle plus-value sont ceux qui demandent le plus de technicité et réclament la main d'oeuvre la plus qualifiée, donc la plus chère.

Dernier point, essentiel, les problématiques visées sont génériques (ouvrir une connexion à la base de données, c'est la même chose quelque soit l'écran pour lequel on a besoin de lire des données, il n'y a que la nature des données lues qui change ).

Du coup, ce qui serait bien, ce serait qu'on puisse développer séparément la prise en compte générique de ces problèmes transverses, par des experts, puis qu'on se débrouille pour que ce soit "mixé" avec le code "métier" (les fonctionnalités de l'application) plus simple et implémenté par des développeurs moins qualifiés et moins chers.

Et là, on touche au cœur de l'AOP : 

  • la séparation des problématiques, (separation of concern) : pouvoir faire développer séparément et par des personnels différentes les aspects techniques transverses complexes, appelés aspects, et les développements métiers plus simples et plus importants tant en valeur ajoutée qu'en volume
  • le tissage des aspects : "tissage" (weaving) est le terme consacré en AOP  pour désigner l'opération qui permet de regrouper le code métier et le code transverse (aspects) en un tout unique et cohérent (le programme final)
Au delà de l'aspect économique; il y a surtout un aspect qualitatif ; le développeur pas cher qu'on à tendance à utiliser pour le gros du développement, ben si il est pas cher, c'est pas par hasard : soit il est débutant, soit il est mauvais, et si vous n'avez pas de chance, il est les deux à la fois. Ou pire encore, il peut être bon mais tellement mis sous pression par le respect des délais et du budget qu'il commet des erreurs.

Et, il est bien sur plus facile de faire des erreur sur les aspects les plus techniques et les plus répétitifs. Du coup on a plein de petites erreurs de programmation disséminées un peu partout, non couvertes par les tests unitaires fonctionnels automatisés, avec un impact global sur le niveau de qualité de l'application.

Un exemple typique est une mauvaise gestion des erreurs, qui entraîne la non libération de connexion à la base de données, qui entraîne l'épuisement du pool de connexions du serveur d'application, qui entraîne un dysfonctionnement général de l'application difficilement détectable par les équipes de supervision. J'ai vu ce genre de chose un nombre incalculable de fois, pourtant les techniques pour éviter ceci (AOP ou autre) existent depuis toujours. En assurant une gestion transverse de ces aspects via l'AOP, on évite ces erreurs de programmation, et en outre les développeurs peuvent consacrer toute leur attention au code métier qui apporte la réelle plus-value.

On notera au passage, que tout étant lié, il y a aussi des problématiques de management cachées derrière ces choix : il y aura toujours dans vos équipes des gars qui voudront absolument traiter les problèmes technique (pour des tas de raisons différentes selon les individus), et ils seront frustrés de ne pas pouvoir le faire.

Ca se gère mais il n'est pas inutile d'avoir un lead technique qui surveille le respect de l'architecture.

Les techniques de tissage

Une fois qu'on a compris ça, il reste à comprendre les façons d'y arriver. Il y en a 3, à ma connaissance en tout cas, deux simples à expliquer et une troisième que je vais développer car elle est très intéressante d'un point de vue technique :
  • au "compile time" : au moment de la compilation, on mixe les aspects au code métier dans le code code source fourni au compilateur. Il faut bien sur un compilateur spécial. Le projet open source AspectJ fournit ça
  • au "loading time" : plus rusé, le code compilé n'est pas modifié mais on instrumente les classloaders de la JVM pour qu'ils modifient dynamiquement le bytecode au chargement des classes. Pour ceux qui ne connaissent pas Java, retenez que le programme est modifié au moment où il est chargé en mémoire avant d'être exécuté. On ne perd pas de temps à la compilation mais à l'exécution. Je détaille aussi le principe de manipulation de bytecode plus loin dans l'article.
  • "runtime" : à l'exécution. C'est la technique la plus utilisée. Je vais la détailler plus loin.

Avant de détailler plus avant, il y a une première question qui se pose. Comment l'outil, quel qu'il soit et qu'elle que soit la stratégie de tissage retenu, fait il pour savoir à quel endroit il doit ajouter le code des aspects au code métier écrit par les développeurs ?

Hé bien pas de magie ici, c'est le développeur qui le lui a dis (enfin l'architecte logiciel en charge de la conception globale). Pour ce faire, il s'appuie sur un "langage d'expression" (défini par le projet AspectJ) et qui permet de cibler par des expression régulières spécifiques les endroits où "injecter" le code transverse. Ce langage d'expression a une syntaxe particulièrement barbare mais on s'y fait ;-)

Par exemple, on peut exprimer qu'on veut injecter un code transverse "avant", "après", "autour" de l'exécution de toutes les méthodes présentant une certaine signature, ou étant dans un sous package quelconque de tel package de base. "avant et "après" se passent de commentaire, "autour" permet de mettre en place des blocs de gestion d'erreurs pour du code de terminaison (bloc finaly) ou de gestion d'exception (bloc catch).

Bien, on a presque fini, il nous reste le plus amusant, la technique utilisée pour le weaving au runtime (le tissage des aspects à l'exécution). A partir d'ici, je cesse d'essayer de m'adresser à tout le monde et j'aborde un vocabulaire plus technique car ce serait très fastidieux autrement.

Focus sur le tissage à l'exécution

Attention ; maîtrise de la POO et du JDK requis.

Commençons par le design pattern "Proxy". Un proxy (intermédiaire en Français) est un objet qui reçoit un appel à la place de l'objet qu'il proxifie, et qui retransmet l'appel à l'objet initialement ciblé (il  a donc une composition sur l'objet proxifié). Il en profite pour ajouter  du comportement avant l'appel, après l'appel, ou autour de l'appel (try/catch/finaly).

Le proxy fournit impérativement la même interface que l'objet qu'il proxifie pour pouvoir être invoqué à sa place de façon transparente, par simple application du polymorphisme.

Pour cela, il existe deux techniques. La plus simple consiste à s'appuyer sur la fonctionnalité de "proxy dynamique" fournie en natif par le JDK depuis la version 1.4 de mémoire. Cependant, cette technique implique que la classe à proxyfier (le code métier dans lequel on veut injecter du code transverse) implémente une interface dont le contrat inclus les méthodes à proxyfier. Si tel n'est pas le cas, une seconde technique consiste à générer dynamiquement (par manipulation de bytecode), une classe qui étend par héritage la classe à proxyfier. Cette technique a ses propres contraintes car bien entendu la classe à proxyfier ne peut pas être finale (les méthodes non plus), ni les méthodes statiques (pour des raisons évidentes, de tout façon le statique c'est pas bien).

Etant donné que le proxy a vocation à être invoqué en lieu et place de l'objet proxyfié, il faut également que le code instanciant l'objet à proxyfier soit "polymorphique", c'est à dire qu'il déclare et manipule l'objet au travers de son interface (ou par la classe ancêtre au pire) et que l'instanciation ne soit pas codée en dur mais déléguée à un mécanisme qui permette de faire varier la classe effectivement instanciée, une factory donc (design pattern).

Depuis le temps qu'on vous dis qu'il faut programmer au travers de types abstrait, vous devez commencer à comprendre pourquoi ;-)

Injection de dépendances et framework : la boucle est bouclée

Si vous avez suivi, et compris, tout ce que j'ai expliqué ici, et dans l'article précédent sur l'IOC et l'injection de dépendance, vous devez comprendre qu'un framework d'injection de dépendances est le compagnon idéal de l'AOP.

Et bien sur, c'est la technique mise en oeuvre par Spring pour apporter des services transverses, à l'instar des EJB d'un serveur JEE. La gestion déclarative des transactions par spring-tx (framework de gestion de transaction) est une simple mise en oeuvre de ce mécanisme avec simplement une légère surcouche de configuration, et des aspects pré-implémentés conçus en outre pour pour profiter de la grande versatilité de Spring en matière de gestionnaire de transaction selon l'environnement d'exécution et le type de transaction (distribuée ou non).

Je connais moins intimement spring-security (framework Spring de gestion de la sécurité, ex ACEGI) mais je n'ai aucun doute sur le fait que c'est ce même mécanisme qui est utilisé en cas de gestion des contrôles d'accès au niveau de la couche métier (en cas de gestion de la sécurité au niveau de la couche d'invocation web, il utilise les filtres http de l'API Servlet JEE).

Voilou, rien de bien compliqué au final. Et en prime, tout ceci est parfaitement expliqué dans la documentation de Spring. Encore faut il se donner la peine de la lire (bon c'est pas un roman non plus).

Génération de bytecode

J'invite les personnes qui n'ont pas les idées totalement claires sur la relation entre un code source, un code compilé, une architecture de processeur, et la virtualisation de processeur (tiens au hasard par la JVM) à lire rapidement cette série de deux articles "qu'est qu'un programme"

Produire du bytecode est normalement le travail du compilateur ; il lit le code source, et le transforme en instruction binaires suivants la spécification de la JVM. 

Mais rien n'interdit d'écrire un programme qui fasse la même chose. C'est même plus qu'intéressant étant donné la nature compilée de Java et l'impossibilité qui en découle d'exécuter du code évalué dynamiquement (contrairement par exemple et au hasard à javascript). Et en quoi est ce intéressant au fait ? 

Le premier cas d'utilisation serait celui où il nous faut un logiciel très versatile, au delà des capacités déjà importantes apportées par le paradigme objet (qui impose en gros de pouvoir au moins définir une interface et qui dans l'esprit requiert un typage fort incompatible avec la gestion de cas de figure imprévisibles). Soyons clair, ce n'est pas un cas de figure fréquent dans le développement en entreprise, hormis pour les éditeurs de logiciel qui doivent s'adapter fortement (genre ERP). En outre, il existe la possibilité depuis quelque temps déjà d'intégrer un moteur de scripting dans la JVM ce qui est fait pour répondre à ce genre de cas, avec même un interpréteur Ecmascript fourni en standard (Rhino dans java 6 et Nashorn depuis java 8).

Le second cas d'utilisation est celui qui nous intéresse dans le cadre de cet article sur les tours de passe passe des frameworks. Ces derniers font un usage immodéré de la génération dynamique de bytecode, en particulier Hibernate. Spring également pour la mise en oeuvre de l'AOP dans certains cas. Et bien d'autres.

Donc ne vous flagellez pas si vous n'arrivez pas à comprendre comment font ces frameworks : ils trichent purement et simplement. Si l'AOP en mode "runtime" n'est après tout qu'une utilisation judicieuse des capacités natives des langages objets (héritage, composition, polymorphisme) et une combinaison de design pattern, la génération de bytecode est clairement un procédé malhonnête ;-)

Un dernier mot : la génération de bytecode est quelque chose de non trivial... si vous voulez l'envisager, il est plus que recommandé de vous appuyer sur une des deux librairies existantes (cglib, javassist), librairies que comme par hasard vous trouverez dans les dépendances (tirées par Maven ou Graddle, on est bien d'accord) de vos frameworks préférés. Ceci dis, un développement d'entreprise classique n'a guère de chances de nécessiter le recours à ces techniques.

Conclusion

Ma première motivation pour écrire ces deux articles, sur des sujets qui ne sont en rien nouveaux, est venue, je pense, de l'incapacité que j'ai constatée chez de très nombreux développeurs de s'exprimer clairement sur ces concepts de base. Alors même qu'ils les utilisent à longueur de journée au travers des frameworks qu'ils manipulent.

Il y aurait encore  bien des choses à dire. L'informatique n'échappe pas aux phénomènes de mode et régulièrement des sujets viennent sur le devant de la scène et finissent par arrive au comptoir, ou à la machine à café : tout le monde en parle, sans forcément maîtriser, ce qui est par ailleurs bien compréhensible quand il s'agit de concepts novateurs. Il en résulte beaucoup de bruit et de fausses idées qu'il faut bien finir par débrouiller

Par ailleurs, l'informatique est un business. Faire croire que les choses sont plus compliquées qu'elle ne le sont réellement est un travail, mais ce n'est pas ma vision de choses, ça me perdra ;-)

dimanche 14 février 2016

Mythes et légendes de la POO 1/2

Dans cet article, je vais essayer de m'attacher à vulgariser quelques concepts liés à la programmation objet, et en profiter pour en démystifier certains autour desquels j'ai entendu trop de bullshit depuis des années. Les concepts que je vais aborder sont très généraux et nous allons les étudier sans plonger dans le code, avec une vision haut niveau afin de bien en faire ressortir les éléments clés.

Un premier niveau de compréhension des concepts objets, en particulier l'héritage, la composition et le polymorphisme est parfois requis, mais la plupart de l'article reste accessible sans connaissance préalable.

Design Pattern / (Patron de conception)

Assez logiquement, tous les développeurs travaillant dans un même domaine d'application se retrouvent confrontés aux mêmes problèmes à résoudre. Et chacun va expérimenter différentes façons de faire, sans doute se planter sur ses premiers programmes, puis trouver un tour de main à peu près satisfaisant, puis le repenser et l'améliorer au fil du temps, jusqu'à trouver "la solution parfaite" ; dès lors, il pourra l'appliquer à chaque occasion qui se présentera à nouveau sans devoir refaire le même cheminement ponctué de tâtonnements, de révision déchirantes, et d'engueulades du chef de projet désespéré de voir le budget exploser et les plannings se décaler.

Ne serait ce pas magnifique si l'expérience ainsi acquise pouvait se transmettre ? Si on pouvait écrire un livre de recette décrivant les bonnes façon de faire ? Ainsi, il suffirait de s'y plonger pour avoir directement la quintessence des bonnes pratiques.

Vous en avez rêvé, et bien le GOF l'a fait. Le GOF (pour Gang of Four) désigne 4 légendes vivantes de la POO, 4 ingénieurs d'exception, qui il y a des décennies déjà on écrits ces tours de main, les fameux design pattern, dans des recueils qui doivent figurer sur l'étagère de tout ingénieur.

L'apprentissage de ces pattern est donc une bonne idée pour tout ingénieur qui se spécialise dans le domaine de la POO, et leur existence un atout pour la discipline. Jusque là tout va bien, que du bon sens.

Mais pour autant, il est totalement faux de croire que la connaissance livresque des pattern suffit à faire un bon ingénieur : l'expérience en matière de POO est primordiale (sans parler d'un solide sens pratique).

J'insiste sur ce point car la connaissance des design pattern a été survalorisée pour des raisons purement marketing (c'est un bon argument pour augmenter le tarif journalier d'un expert , ça permet de développer des activités de consulting et de formation...). Et avec un effet de bord sur des développeurs se comportant en "idiots savants" abusant de l'usage systématique des pattern, en dépit du bon sens, en aboutissant généralement à un assez piètre résultat (le risque de sur-conception, de concevoir quelque chose d'inutilement complexe, est un écueil classique et bien connu de la POO).

Donc oui, la connaissance des design pattern est un plus significatif et un pré-requis pour certains postes nécessitant un fort niveau de technicité, mais pour autant ce n'est en rien une garantie de succès ou une recette magique.

MVC

MVC est un design pattern classique. C'est un pattern assez abstrait, disons un concept général, une idée, qui peut se réaliser de multiples façons.

Expliquons rapidement ce qu'est MVC : de façon courante, les logiciels sont architecturés selon un système de couches superposées. Il existe plein de façon de faire mais on trouve en général au moins une couche chargée de la gestion des interactions avec l'utilisateur (l'IHM), et une couche qui implémente les fonctionnalités voulues. La couche IHM fait appel à la couche "fonctionnalités" en fonction des actions de l'utilisateur (par exemple lancer un traitement suite au clic sur un élément de menu), et à l'inverse la couche "fonctionnalités" peut provoquer des mises à jour de l'IHM (par exemple, affichage d'un message pour communiquer le résultat d'une action déclenchée par l'utilisateur). Ces deux couches sont donc fortement couplées et mutuellement dépendantes, ce qui est un gros souci pour la maintenabilité et la fiabilité (sans parler que l'idée de base dans un système en couche superposées, c'est que chaque couche ne doit parler qu'à sa couche inférieure).

Le pattern MVC vise à découpler la couche "IHM" (le V de MVC, pour View) et la couche "fonctionnalité" (le M de MVC, pour Model) afin qu'elles ne se parlent plus directement mais par le biais d'un intermédiaire appelé contrôleur (le C de MVC). ça n'a l'air de rien comme ça, mais ça amène énormément de bénéfices, faîtes moi confiance. C'est aussi simple que ça.

Le monde du développement est régulièrement agité de soubresauts liés à la guerre entre tenants des différents variations autour de ce thème, certains s'en s'ont fait une spécialité et peuvent en parler pendant des heures...moi je trouve ça super chiant, mais bon c'est personnel.

Si je parle de MVC en particulier, c'est car ici  aussi le marketing a fait des ravages... A une époque, on en a fait des caisses sur la mise en oeuvre de ce pattern dans les architectures web, un peu comme si c'était la recette du succès d'un projet... Bien sur il n'en est rien, c'est une bonne pratique et un facteur de succès mais c'est tout. On peut très bien réussir sans et échouer avec.

IOC, injection de dépendance

IOC est encore un pattern abstrait. Mais encore beaucoup plus abstrait et plus généraliste que MVC, en fait je dirais même que le terme de design pattern n'est pas adapté.

Comme MVC, c'est un grand classique des sujets d'ingénierie dont le marketing s'est emparé et dont tout le monde s'est mis à parler, généralement à tort et à travers.

Comme pour MVC, c'est du au fait qu'une technologie innovante et/ou résolvant un problème fréquent a occupée le devant de la scène, et que cette technologie s'appuyait sur ce concept. Pour MVC ça a été le framework web STRUTS (une grosse daube au passage, une preuve de plus qu'en informatique ce ne sont que rarement les meilleures solutions qui deviennent des standards), pour IOC ça a été le framework SPRING qui dans sa première version a popularisé les mécanismes d'injection de dépendance (l'injection de dépendance étant une forme particulière d'IOC).

IOC est un acronyme signifiant Inversion Of Control, inversion de contrôle en Français. Mais de quoi parlons nous ici ?

Le plus simple pour expliquer IOC est de revenir 25 ans en arrière. A l'époque du DOS, avant l'arrivée de Windows et des interfaces graphiques. Imaginons un programme simple : un écran de saisie avec 3 zones de textes. A l'époque, un programme dessinait les zones à l'écran, positionnait le curseur au début de la première zone, et se mettait en attente d'un signal du clavier. Si c'était un caractère autorisé, il l'affichait à l'écran et déplaçait le curseur, sinon il faisait un beep. Si la touche enfoncée était "flèche bas", il déplaçait le curseur sur la zone suivante etc. Bref, le programmeur était le maître du monde, il avait le contrôle total de ce qui se passait. Inutile de dire que le moindre écran prenait un temps fou, raison pour laquelle l'ergonomie était pourrie (car sinon il aurait fallu passer un temps infini sur chaque écran). Puis, on a vu arriver Windows et de nouveaux modèles de programmation (je simplifie à outrance pour l'exemple) : désormais, le programmeur ne code plus la gestion de l'écran, il se contente de le dessiner avec un outil graphique puis il demande à Windows de l'afficher. C'est Windows qui gère tout ce que gérait le programmeur autrefois ; saisie de caractères au clavier, déplacement de zone en zone, plus dimensionnement des fenêtres etc... Tout ce qui est générique et commun à tout écran de saisie est géré par le système, le développeur ne s'en soucie plus, on a un gros gain d'ergonomie et de productivité. Cependant, à un moment donné le programme va faire des choses qui lui sont spécifiques, comme par exemple calculer un montant TTC après qu'on ait saisi un montant HT et un taux de TVA. Et ça le système d'exploitation ne peut pas le prendre en charge car ce n'est pas générique mais spécifique au programme. Il va donc rendre la main au programme au moment voulu (après validation d'un montant HT et d'un taux de TVA par exemple). C'est le programmeur qui aura spécifié au système a quel moment on doit lui donner la main et quel morceau de code il faut appeler à tel ou tel moment. Peu importe la façon de faire, il existe différents mécanismes mais ce qu'il faut retenir c'est que le contrôle est inversé : ce n'est plus le programme qui a le contrôle mais le système chargé d'exécuter le programme, alors qu'auparavant c'était le contraire. Le contrôle est inversé. Voila, c'est aussi simple que ça.

Voyons maintenant l'application de ce principe dans l'univers JEE. C'est un peu plus technique.

JEE est une version de java qui est utilisée pour le développement web. C'est aussi une norme qui est implémentée par des serveurs d'applications. Ces serveurs constituent l'environnement d'exécution des applications web qui sont développées selon certaines conventions spécifiques. Une application web c'est par exemple le site internet de consultation de votre compte bancaire. Quand vous cliquez quelque part, une requête http est émise, interceptée par un serveur http qui la transmet au serveur d'application, qui va exécuter la partie de l'application qui va bien (qui va générer une page html et vous la renvoyer, par exemple). Si ce fonctionnement n'est pas clair pour vous, commencez par lire cette série de 3 articles sur le fonctionnement du web.

Dans cet univers, les serveurs d'application fournissent des services techniques aux développeurs afin de les décharger de certain aspects rébarbatifs et très complexes, afin qu'il puissent se focaliser sur ce qui est vraiment important pour l'application : ses fonctionnalités. Pour cette raison, l'IOC est appliquée à la problématique d'instanciation des classes.

En POO, on doit commencer par instancier une classe, qui est un bout de code spécialisé sur une tâche, avant de pouvoir utiliser ses services (l'instance d'une classe étant un objet). Habituellement, c'est le programmeur qui se charge d'instancier ces classes. Mais en environnement JEE, afin que le serveur d'application puisse rendre les services évoqués, il doit avoir le contrôle de ces instanciations : on a donc une inversion de contrôle ; l'IOC est un concept clé de JEE.

IOC nous l'avons vu est un principe général, et il peut s'implémenter de diverses façons. Dans un projet utilisant les fonctionnalités avancées de JEE (appelées EJB, leur utilisation étant facultative), c'est implémenté via un pattern appelé "service locator". En gros, le programmeur s'adresse au serveur et lui demande une instance de la classe dont il a besoin (au lieu de la créer lui même) ; pour les connaisseurs, c'est bien entendu de l'API JNDI et ses fameux lookup dont il s'agit (sur les EJB, avant la version 3).

JEE a souffert de gros défauts de conception durant très longtemps : c'était une usine à gaz, lente à l'exécution, et complexe à la mise en oeuvre. L'IOC et le pattern "service locator" n'étaient pas en cause mais toujours est il qu'une alternative plus légère est apparue dans le monde de l'open source : SPRING. Cette alternative qui a connue un très grand succès s'appuie également, et pour les mêmes raisons, sur le principe d'IOC appliqué aux instanciations. Mais l'implémentation s'appuie sur un design pattern différent qui est mis en oeuvre d'une façon très astucieuse, pour réaliser ce qu'on appelle l'injection de dépendances (qui est donc une autre forme d'IOC).

Bref, le grand succès de Spring, et le fait que dans leur communication les ingénieurs qui l'ont conçu ont mis en avant le mécanisme d'injection de dépendances, ont générés encore un buzz marketing sur les notions d'IOC et de DI (Dependency Injection). Alors que le vrai débat entre Spring et JEE se situe à un tout autre niveau.

Et au fait, comment ça fonctionne l'injection de dépendances ?

L'idée générale est que Spring a la main (le contrôle) sur toutes les instanciations : le programme écrit par le développeur en s'appuyant sur le framework Spring ne fait aucune instanciation, au lieu de cela il demande a Spring de lui fournir l'objet dont il a besoin (jusque là rien de neuf). Ce qui est novateur, c'est quand l'objet en question a une dépendance sur une autre classe, Spring la détecte grâce à des meta-données fournies par le développeur qu'il a consommé lors de son initialisation (fichiers xml ou annotations java), et dès lors qu'il instancie la classe qui a une dépendance (qui utilise une autre classe), il instancie également, si nécessaire, la dépendance et la passe à la première classe (soit via un appel au constructeur, soit via un appel à une méthode de la première classe qui  va setter la propriété dépendante). Pour en revenir aux design patterns, c'est une implémentation sophistiquée et générique du design pattern "Factory" (un objet chargé d'instancier des objets).

Comme Spring instancie tous les objets, il peut en profiter pour interférer avec leur comportement et apporter des services transverses, exactement comme le faisait le conteneur EJB d'un serveur d'application JEE dans notre exemple précédent. Pour cette raison, on qualifie Spring de conteneur léger (léger car le mécanisme de fonctionnement est beaucoup plus simple et rapide que celui d'un container EJB soumis à d'autres contraintes, en particulier le support des appels distribués par la technologie RMI). Je décrirais la façon dont Spring interfère sur le comportement des classes dans un second article consacré plus spécifiquement à l'AOP.

Pour en finir avec la parenthèse sur la comparaison JEE/Spring a laquelle m'a conduit cette explication de l'IOC, je rappelle simplement que JEE a complètement changé son fusil d'épaule et s'appuie sur l'injection de dépendance (et l'AOP) depuis la version 6 de la norme ; il n'y a plus aujourd'hui de grosse différence en terme d'IOC entre Spring et JEE.

Voilà, un très long article pour expliquer un truc tout simple. Mais j'ai tellement entendu d'absurdités sur le thème IOC/DI (Dependency Injection) que ça me semblait pas totalement inutile.

Framework

Le concept objet est simple, le langage Java est simple, les APIs de base ne sont pas pire qu'avec tout autre langage (encore que, java est un peu lourdingue il faut bien le dire). Mais il faut encore avoir un bon niveau de connaissance des design pattern classiques, et beaucoup d'expérience pour faire un développeur objet expert.

De ce fait, les vrais experts sont rares et chers. Par ailleurs, les technologies objet sont très présentes en particulier à cause de la très large implantation de JEE dans les grandes entreprises (qui ont les moyens de sa mise en oeuvre), et il y a une très forte demande en développeurs dans les SSII.

Heureusement, les frameworks sont là pour simplifier les développements et masquer une grande partie de la complexité, réduisant ainsi la nécessité de recourir à des experts pointus.

Du coup, il y a un déplacement du centre de gravité des compétences : on cherche souvent plus un développeur formé et directement opérationnel sur tel ou tel frameworks (généralement plusieurs) qu'un expert pointu (même si bien sur l'un n'empêche pas l'autre).

Bien, mais c'est quoi un framework ?

La notion de framework est liée au l'idée d'IOC. En gros, un framework c'est un programme qui gère une problématique donnée sur tous ses aspects invariants, qui garde le contrôle, et qui sait passer temporairement le contrôle au programme qui s'appuie sur lui, afin de le laisser prendre en charge les aspects spécifiques. En reprenant mon exemple de l'écran de saisie avec 3 zones, le framework serait la partie du système qui se charge d'exécuter l'écran et de gérer le déplacement de zone en zone, le clavier, la souris etc., toutes choses dont le développeur est déchargé.

Martin Fowler, un des 4 du GOF dont j'ai parlé plus haut, a écrit un excellent article sur le sujet, j'en reproduis une partie très éclairante ici :
Inversion of Control is a key part of what makes a framework different to a library. A library is essentially a set of functions that you can call, these days usually organized into classes. Each call does some work and returns control to the client.
A framework embodies some abstract design, with more behavior built in. In order to use it you need to insert your behavior into various places in the framework either by subclassing or by plugging in your own classes. The framework’s code then calls your code at these points.” (Fowler, Martin. Inversion of Control. 2005.)

J'espère que la notion de framework est à peu près claire. Les frameworks occupent une grande partie de la boite à outil des développeurs, elle accroît leur productivité en masquant la complexité et en mâchant une partie importante du travail. Les autres outils sont les libraires (ou APIs) qui sont des collections de code tout écrit qui résolvent des problèmes courants, et les divers outils utilisés pour lé développement (éditeur de code, debugueur pour la mise au point, compilateur, outil d'automatisation des tests, outil d'automatisation des chaînes de build etc.).

On a des frameworks web focalisés sur la problématique de navigation entre pages, de génération de pages html mixant sur code statique de présentation et des données en provenance de la base de données, de gestion de la session ; on a des frameworks de persistance focalisés sur l'optimisation des lecture et écriture en base de données, on a des frameworks spécialisés sur les problématiques de sécurité (authentification, habilitation, sso...) ; on a des frameworks de test focalisés sur l'écriture de programme qui testent les programmes (oui oui vous avez bien lu) ; bref, il en existe énormément.

Mais tout n'est pas rose, il y a des effets pervers à l'utilisation de ces outils qui mâchent le travail. Le premier souci est que beaucoup de développeurs ne développent plus un niveau très élevé de maîtrise de la POO (d'où bien des problèmes). Comme bien souvent quand on utilise des outils évolués, les développeurs en deviennent dépendants et finissent par ne plus savoir ce qui se passe sous le capot ; ils sont incapables de se débrouiller sans leur outil magique : qu'il atteigne ses limites et ils trouvent les leurs, ils ne savent plus rien faire par eux mêmes et méconnaissent les API de base. Le second souci est que ces frameworks sont souvent largement surdimensionnés pour des problématiques simples, et du coup, si on laisse faire les développeurs, ils emploient souvent un marteau (et bien souvent une caisse à outil complète) pour écraser une mouche, avec des conséquences sur l'empreinte mémoire, les temps de build, et surtout les pré-requis pour la maintenance (la maîtrise d'un framework s'acquiert elle n'est pas innée ...).

Pour cette raison, on a différents niveaux d'intervenants dans la profession, et on trouve désormais souvent des développeurs qui ne sont guère que des exécutants avec un faible niveau de qualification (enfin tout est relatif), qui travaillent dans un cadre le plus étroit possible défini en amont par des experts qui maîtrisent les concepts objets et ont une connaissance pointue des frameworks et modèles d'architecture applicative. Le développement du recours à l'offshore (envoi des développements à l'étranger dans des pays à faible coût de main d'oeuvre, avec aussi un niveau de compétence et de formation inférieur à celui de la France, je dis ça j'ai rien dis...) va également dans ce sens.

Voilà pour les réflexions philosophiques sur l'organisation du travail dans notre merveilleux monde libéral.

Conclusion temporaire

Mon objectif ici était double :
  • dégonfler tout le bullshit autour de notions techniques simples montées en épingle par un marketing peu inspiré (encore que, il faut reconnaître que ça a bien marché, ce qui n'est pas très rassurant en soi)
  • expliquer le plus simplement possible ces notions afin d'en faciliter la compréhension


Il reste encore quelques points aborder, mais ce sera dans un second article, celui ci me semble assez long déjà ;-)

mardi 9 février 2016

PC Desktop Fanless 3/3 - Assemblage et test

Troisième et dernier épisode de fin de mes aventures au pays du fanless

Premier épisode : le cahier des charges et le choix de la solution 
Second épisode : réception du boiter HDPLEX


1er contretemps

Deux caloducs trop long sur la gauche
J'ai commencé l'assemblage et je suis tombé sur un os.

Deux des quatre caloducs orientés vers le fond du boitier (angle à gauche) se sont avérés trop longs, ils dépassent du fond du boitier.

Renseignement pris auprès du fournisseur, le problème a été rencontré également avec d'autres personnes ayant opté pour une carte mère au format micro-ATX.

Je ne saurais dire si c'est un problème de conception, ou si le problème est aléatoire en fonction des cartes mères (le plus probable cependant). Comme je ne pense pas que la norme micro-ATX aille jusque spécifier la distance du socket depuis les bords de la carte, le problème ne pouvait pas être anticipé. Il est à noter que HDPLEX publie une liste de cartes mères validées sur son site. Si comme moi vous prenez un modèle non listé, je suppose que vous n'êtes pas à l'abri de ce genre de petit désagrément.

En inversant les caloducs 3 et 4, je n'en ai plus qu'un qui dépasse. Après m'être renseigné il s'est avéré que je pouvais soit ne pas monter le quatrième, soit m'arranger pour le raccourcir, le caloduc devant cependant rester fermé (on ne peux pas juste le scier pour le raccourcir).

Téléphone arabe
Tant qu'à faire je l'ai fait transmettre, par personne interposée, à un ami qui a le matériel pour travailler des tuyaux de cuivre de petite section, pour avoir quelque chose de propre ; mais le téléphone arabe est passé par là et la pièce que j'ai récupérée était écrasée en son extrémité, du coup elle n'était plus ronde et ne rentrait plus dans les rainures latérales. Pour finir, j'ai coupé la partie écrasée et j'ai fait ressouder le bout qui avait été coupé en insérant un pas de vis en interne pour guider le tout. Un peu brutal mais ça l'a fait.

Montage aisé, ou presque

Je n'ai pas rencontré de difficulté particulière pour le montage. Il faut dire aussi que mon montage était très basique, juste un SSD, pas de carte d'extension, pas de carte vidéo.

La visserie est fournie en nombre et en qualité. J'ai pu monter et démonter certaines parties sans souci, c'est qualitatif.

J'ai pris quelques photos au fur et à mesure de l'avancement

La première étape ne présente aucune difficulté. On fixe sur la carte mère le support du bloc de refroidissement, puis on la pose sur des entretoises en fond de panier.

On enfiche le processeur et on fixe la partie inférieure du bloc de refroidissement (en cuivre).

Fixation du côté droit puis test de mise en place des caloducs. C'est là que j'ai relevé le problème mentionné plus haut.

Ensuite, on met en place les deux parties de l'alimentation électrique, leur emplacement est repéré.
Mise en place des deux éléments de l'alimentation sur le fond du boitier

Je n'ai pas pu fixer le bloc d'alimentation sur les 4 trous prévus, l'ajustement n'étant pas parfait mais ce n'est pas un souci du tout, 3 vis suffisant bien. C'est une pièce qui ne subit aucune vibration, il ne peut rien lui arriver.

Fixation du bloc AC/DC
Les trous de fixation du premier puis du second bloc
Je suppose que le problème a été vu et corrigé car quand j'ai reçu un second bloc (le premier étant défectueux), j'ai vu que les pâtes de fixation ont été modifiées.





Cage disque en place
Mise en place de la cage disque et fixation du SSD

Flanc gauche
Mise en place du côté gauche et branchement de ses connecteurs
(le reset, les prises USB3, prise casque, les prises USB2)

Facade avant
Mise en place de la façade avant (amovible)
Si vous êtes observateur, vous avez du voir que le disque est fixé dans le mauvais sens sur la cage (et pas le même que sur la photo précédente). Je l'avais monté dans le mauvais sens, je m'en suis rendu compte quand j'ai voulu le brancher et que je n'avais pas accès au connecteur SATA (non mais quel crétin !)

Mise à la masse
Ne pas oublier de relier la terre à la carcasse (non mentionné dans le manuel)

L'interrupteur de la façade avant comporte deux câbles à relier à la carte mère.

Le câble avec deux fils vert et blanc est à brancher sur le connecteur "panel", sur les pins PWR+ (fil vert) et PWR- (fil blanc).

Le second connecteur avec deux câbles noir et rouge est à connecter sur un header pour ports USB2. Il utilise les pins normalement destinés à l'alimentation d'un port USB pour alimenter la lumière du connecteur en façade (les effets de lumière se configurent via des petits jumpers sur le dos de l'interrupteur).

A noter : on ne branche ni haut parleur interne, ni voyant d'activité du disque (non prévus dans le boitier conçu pour un usage HTPC).

Le câble de reset (branché sur le connecteur "panel" sur RST+ et RST-) est relié au connecteur de façade inclus dans le côté gauche.


Non, la seule difficulté, et là je dois dire qu' avec mes gros doigts maladroits j'ai eu du mal, c'est d'appliquer la pâte thermique proprement dans les rainures du boitier et du bloc de refroidissement, avec le petit outil en forme d'haltère.

L'outil est tout petit à manipuler, il serait pertinent d'avoir un bout plus gros pour faciliter la prise. La boule de l'haltère s'est désolidarisée du manche et la récupérer dans la rainure n'est pas simple, je me suis mis de la pâte plein les doigts. Bref, j'ai fait ça un peu comme un malpropre et j'ai manqué un peu de pâte du fait que j'en ai gâché.

Pour le reste, ça va tout seul.

2nd contretemps

Tout content, j'allume la bête pour un premier test et là grosse désillusion ; le bloc AC/DC produit un sifflement aigu insupportable, surtout quand on a craqué sa bourse pour une machine totalement noiseless.

Bloc cramé
Le premier bloc qui a cramé (zoomer)
Contact pris avec le fournisseur, pas de souci, il m'en renvoie une autre sans discuter.

Finalement, le sifflement devait être lié avec un défaut quelconque car l'alimentation a fait sauter mon disjoncteur et a cramée au bout d'une journée.

Je reçois la pièce de rechange très vite, je la met en place et là que du  bonheur. La machine est totalement silencieuse.


Bon finalement j'ai donné le premier bloc à mon frère, il est électricien et avec un peu de chance il va pouvoir  le réparer et le recycler pour un autre PC qu'il veut se mettre en place.

Bios
Un petit contrôle avant de refermer le dessus du boitier

Installation de l'OS, pas un long fleuve tranquille

Normalement c'est une simple formalité. Ben non, pas cette fois.

Premier souci, la clé USB bootable n'est pas détectée... Après avoir fouillé en vain les options de l'UEFI pendant un moment, et testé plein de combinaisons sans trop y croire (et sans succès), je finis par tilter qu'il faut la brancher sur un port USB2 directement connecté à la carte mère, et pas sur un port USB3 branché sur un header d'extension. Sans doute une limitation des drivers de l'UEFI. J'étais à deux doigts de désosser le graveur de DVD d'une autre machine.

Désillusion suivante, qui n'a rien à voir avec le boitier : je m'aperçois que la GPU intégrée des skylake (dernière génération des processeurs Core) n'est pas supportée par Linux... Il faut attendre la version 4.4 du noyau, et les distributions de bureau ne seront sans doute pas disponibles avec cette version du kernel avant un petit moment.

Il y a bien moyen d'activer un support expérimental, avec plus ou moins de garantie, ou d'upgrader le noyau, avec plus ou moins d'instabilité résultante du système, mais je n'ai pas envie de me prendre la tête pendant des semaines.

Je suis un peu dépité, je n'ai pas pensé à vérifier que le driver était disponible quand j'ai élaboré ma configuration mais jamais je n'aurais imaginé avoir un problème pour un composant aussi standard et mainstream, quand même sorti depuis quelques mois. Bref, Linux sur le desktop a encore des progrès à faire.

Tant pis, je reviens en Windows 10. Je récupère une licence Pro via un contrat MSDN, et roule ma poule. Contrairement à ma première installation (upgrade d'un Seven), je ne me fais pas avoir par le gros bouton "installation rapide" et je vais bien chercher le petit lien planqué pour désactiver toutes les options merdiques activées par défaut.

J'ai quand même dû m'y prendre à plusieurs fois : j'ai d'abord laissé l'installeur créer les partitions sur le disque vierge, et il m'a fait une partition système qui prend 100% du disque...

J'essaye de retailler la partition mais rien à faire, je ne peux pas la descendre à moins de 120 Go !

je refais une installation et cette fois je prend la main pour créer une partition bien taillée, et là Windows refuse de s'installer : l'installeur a créé une table de partition MBR et Windows détectant qu'il tourne sur un système UEFI réclame une table de partition GPT. NomdidjieuDeNomdidjieu !

Après quelques instants de perplexité, je reboote sur une distribution Linux live, je lance GParted (outil de gestion des partitions), je supprime toutes les partitions, je créé une table de partition GPT et rebelote. Cette fois ça passera.

En fait, je ne sais pas si c'est un bug de l'installeur Windows qui en l'absence de table de partition en créé une en MBR par défaut, ou si c'est moi qui ai fait une erreur : je ne connais pas bien cette carte mère et elle propose plusieurs modes de démarrage quand on boote sur USB, il est possible qu'il faille prendre une option démarrage UEFI et que je ne l'ai pas fait le moment venu. Ca restera une interrogation, après 3 installations je n'ai pas envie de m'en taper une quatrième, voire une cinquième, juste pour déterminer ce point. On va dire que c'est un bug de Windows (mauvaise foi quand tu nous tiens).

Le SSD de bâtard !

J'ai regardé "les tuches" hier à la TV. Pas très fin m'enfin ça passe une soirée, et j'ai retenu l'expression favorite du mongol de la famille : le "ce que tu veux" de bâtard !

Je commence à utiliser la machine, et je suis impressionné par la performance. Du coup, je fais quelques tests basiques en comparant le temps de traitement d'un très gros fichier RAR multi-volumes entre mon ancienne configuration et la nouvelle.

En passant d'un core i7 à un core i5 moins rapide en fréquence, avec la même quantité et les mêmes barrettes de mémoires, le même OS, sur SSD dans les deux cas, je divise par plus de deux mon temps de traitement (et à priori WinRAR exploite bien le multi-threading).

Il me faudra faire d'autres tests plus poussés mais d'ores et déjà je m'aperçois que je ne me suis pas trompé dans le choix de mon SSD.

Il est vraiment impressionnant de vitesse : j'ai choisi un modèle qui explosait tout dans les benchmark et je l'ai payé cher, en me sentant presque un peu coupable de me laisser convaincre par les sirènes du marketing. Mais non, c'est vraiment une bête de course.


Et le refroidissement ?

J'ai trouvé, avec un peu de difficultés, le soft idéal sous Windows 10 : Piriform Speccy. Il m'affiche dans la barre de notifications en temps réel la température du processeur. ça me rassure.

Pour le moment que du bon. En utilisation bureautique, je suis à maximum 31° (29 en idle). Ca reste stable après plusieurs jours sans éteindre la machine (qui passe en veille ceci dit).

Je n'ai pas encore lancé la machine en burn car de toute façon je ne vais pas l'utiliser pour des traitements lourds. Je ferais un update ici quand j'aurais un peu de temps, disons cette semaine, mais pour le moment, sur quelques traitements un peu plus conséquents je n'ai pas dépassé les 45°.

Conclusion

J'ai atteint mes objectifs. J'ai débranché mon ancien système qui va être désossé et réutilisé pour un NAS qui sera dans une autre pièce, et je me délecte du silence total de fonctionnement de mon petit plaisir.

Le boitier est gros et c'est normal car il n'est pas prévu du tout pour un usage bureautique (à la base c'est un boitier au format équipement hifi pour un système home-média), et c'est exactement ce qu'il me fallait car je peux le poser sous mon scanner/imprimante et ainsi ne pas perdre de place sur mon (petit) bureau.

Même si j'ai eu quelques petits soucis, je ne peux que me féliciter de la collaboration avec HDPlex, Larry l'ingénieur qui a conçu le boitier s'est toujours montré très réactif en réponse à mes divers mails et n'a pas sourcillé une seconde quand il a fallu renvoyer des pièces (dont une petite pièce que je ne trouvais pas et que j'avais probablement égarée).

Je doit faire encore quelques tests plus poussés pour vérifier le refroidissement en conditions de forte charge, mais je ne suis pas inquiet. Je ferais une mise à jour de ce post, et d'ici là je ne peux que recommander ce boitier, à condition toutefois d'être un minimum expérimenté en assemblage d'ordinateur et de lire l'anglais. Je posterais également le résultat de ces tests sur la section du forum hardware.fr dédié à la communauté du fanless en France.

02/04/2016 : Update (important)

Il y a une erreur que j'ai commise et il me semble important de le préciser car je me rends compte à la lecture des stats que l'article est pas mal consulté.

J'ai coupé un des caloducs : c'est une erreur. En effet, un gaz circule à l'intérieur qui participe au refroidissement. Donc en coupant un caloduc je lui ai retiré toute efficacité. Mon anglais limité et les échanges par mail avec l'ingénieur de chez HDPlex m'ont enduit avec de l'erreur. La préconisation était de courber le caloduc afin qu'il puisse prendre place mais en aucun cas je n'aurais du le couper. Voilà la précision est apportée, mea culpa.

Autre petit point. J'ai eu une mauvaise surprise avec la carte mère Gigabyte (en plus j'en ai acheté une deuxième pour une seconde machine). Impossible de faire fonctionner un périphérique SATA connecté en USB3 sous Windows 10. J'ai tout essayé et après moult échanges avec le support technique j'ai fini par jeter l'éponge. Peut être une mauvaise série (le support Gigabyte a monté une plateforme à l'identique et ne reproduit pas). Ils m'ont proposé de renvoyer la carte pour échange mais j'ai besoin de ma machine et je n'ai pas envie de refaire le montage des caloducs... donc tant pis, je ferais autrement et sait on jamais ça se réglera peut être tout seul avec une maj de pilotes. Au pire, je peux toujours booter sur un linux live, car bizarrement ça fonctionne parfaitement sous Linux... L'informatique quelque fois c'est quand même un peu du vaudou.