Plus on enlève de code, mieux ça marche

Encore récemment, dans le cadre du chiffrage d'une migration d'un projet vers la dernière version d'RBS Change (CMS / e-commerce dont j'ai déjà parlé plusieurs fois ici), l'un des développeurs disait en parlant de certaines fonctionnalités développées sur le projet en spécifique et qui entre temps ont été implémentées dans le produit que maintenant que le code spécifique était écrit, ça ne coûtait pas cher de le garder tel quel plutôt que de prendre le temps de le remplacer par des appels au code du produit.

À part si un besoin spécifique n'est pas compatible avec le code du produit, je suis intimement convaincu que c'est faux. Et ce pour un certain nombre de raisons.

Le point le plus évident pour moi c'est le coût en maintenance. S'il y a bien une chose que j'ai appris en travaillant sur un logiciel qui fait plusieurs centaines de milliers de lignes de code, c'est que plus on a de code, plus c'est couteux à maintenir. D'une part parce que chaque ligne ajoutée peut comporter des bugs ou s'avérer incompatible avec d'autres parties du logiciel et d'autre part parce que plus il y a de code, plus il est difficile de retrouver la source d'un problème. C'est d'autant plus vrai si l'équipe chargée du projet change. Quand le développeur est le même pendant des années, il peut connaitre assez bien son code pour s'y retrouver parmi les implémentations parallèles (et encore... que celui qui ne s'est jamais senti perdu en se replongeant dans du code qu'il avait écrit rien qu'un an plus tôt lève la main) mais un nouvel arrivant sur le projet mettra beaucoup plus de temps à s'y retrouver s'il doit apprendre à connaitre les implémentations parallèles en plus du produit lui-même.

On en arrive du coup à un second point connexe au précédent : l'évolutivité. Naïvement on se dit que vu que la fonctionnalité est codée spécifiquement, on peut faire ce qu'on veut avec et donc on est bien plus libre qu'en utilisant une fonctionnalité native du produit sur laquelle on n'aura pas autant la main. Ce n'est pas faux. Mais cela implique de se couper en partie des évolutions du produit et de devoir tout faire soi-même de son côté. De plus, se pose le même problème qu'évoqué précédemment où tout nouvel arrivant devra oublier ce qu'il sait déjà du produit pour apprendre ce que fait le projet.

Ensuite on a les coûts d'interface utilisateur et d'apprentissage. De deux choses l'une : soit on laisse les deux implémentations parallèles accessibles dans l'interface et là c'est l'utilisateur qui se sentira perdu, ne sachant quoi choisir (ce qui implique du coût de formation et de réparation de ce que l'utilisateur aura mal fait), soit on doit masquer de l'interface les éléments relatifs à l'implémentation standard pour les remplacer par l'implémentation spécifique (ce qui implique un coût initial plus un coût à chaque mise à jour pour revalider les choses et les réadapter si besoin).

Après on peut avoir du mal à jeter le produit de nombreuses heures de développement. C'est normal mais pour un développeur c'est une chose à laquelle il faut s'habituer. Un logiciel qui n'évolue pas, à part s'il est extrêmement ciblé sur un besoin très pointu qui n'évolue pas du tout (chose très rare), c'est un logiciel mort. Un logiciel vivant évolue continuellement au gré des nouveaux besoins, des nouvelles possibilités et des nouvelles idées. Seulement on ne peut pas se contenter d'empiler de nouvelles choses dessus, sous peine de voir l'ensemble s'effondrer sous sa complexité, de devenir inmaintenable et incompréhensible au nouvel arrivant.

Des choses qui semblaient - et potentiellement étaient réellement - pertinentes à un moment donné ne le seront plus un an plus tard parce que le besoin aura évolué ou simplement parce qu'à force d'y greffer des verrues, on aboutit à un ensemble qui ne ressemble plus à rien. Il ne faut donc pas hésiter à remplacer des fois des pans entiers du logiciel pour repartir sur des bases plus saines. Qui elles-mêmes dégénèreront plus ou moins rapidement (selon la qualité de l’implémentation et la vitesse à laquelle les besoins liés évoluent) avant d'être à leur tour remplacées à nouveau.

Ce principe vaut aussi bien au niveau macroscopique (une API entière finit par devenir trop lourde et doit être remplacée) qu'au niveau microscopique (une méthode donnée peut souvent être réécrite en cinq fois moins de code parce qu'elle prévoyait des cas qui n'existent plus ou bien parce qu'à force de refactoring, le code se répète trop). Il faut toutefois prendre garde à ne pas sauter trop vite aux conclusions et tout réécrire continuellement, sans quoi d'une part on n'avance plus et d'autre part, à aller trop vite, on passe à côté de subtilités qui ne sautent pas aux yeux sans examen approfondi (pour ce dernier point, des tests unitaires ou autres peuvent aider à éviter les régressions, encore faut-il avoir le temps ou simplement prendre le temps de les mettre en place).

Comme souvent il s'agit de trouver un juste milieu entre tout réécrire et conserver à tout prix l'existant. Mais quand la réécriture consiste à utiliser quelque chose qui existe par ailleurs et qu'on n'aura donc pas à maintenir soi-même, je pense qu'il n'y a pas à hésiter : si fonctionnellement c'est compatible, ça vaut le coup de jeter le spécifique pour utiliser du natif.

Voilà voilà, félicitations si vous avez tout lu jusqu'ici et n'hésitez pas à réagir dans les commentaires si vous avez quelque chose à ajouter sur le sujet ou des objections à formuler :)


Récupérer sa bibliothèque iTunes

Je ne m'étais jamais penché sur comment fonctionnait iTunes ou ce qu'il faudrait que je sauvegarde... Au départ il ne contenait rien d'important du coup c'était sans importance (en gros exclusivement mes CD encodés qui sont également sur mon iPhone). Puis j'ai fini par m'abonner à quelques podcasts et du coup sans trop m'en rendre compte, il en est venu à contenir des choses qu'il aurait fallu sauvegarder.

Je savais que je risquais de perdre des choses en cas de crash disque ou en cas de gros plantage du système (virus ou autre). Mais je ne soupçonnais pas qu'un vidage de la batterie et une extinction violente (et sans préavis) du mac pourrait suffire à perdre toutes les données de bibliothèque. Pas les fichiers de son, hein, juste métadonnées (notes des morceaux, playlists, etc) et surtout - dans mon cas la donnée la plus importante - les abonnements de podcasts.

Ce avec quoi je n'étais pas non plus très familier c'est un gros fichier fourre-tout qui s'il est endommagé n'est pas réparable. J'ai l'habitude de bases de données MySQL où quand on a un problème, 99,9% du temps une réparation de la table fautive suffit (au pire on perd quelques entrées mais l'essentiel est toujours là). J'ai l'habitude aussi de fichiers XML ou autre qu'on peut éditer au besoin pour corriger les erreurs. Mais là, rien de tout ça. Juste un gros fichier qui peut que vraquer complètement si l'ordinateur s'éteint alors qu'on est juste en train d'écouter de la musique.

En cherchant un peu sur le net, différents mot-clés, je suis tombé principalement sur des solutions du type "efface tout et réimporte ta musique". La belle affaire. La partie que tu perds dans un cas comme ça est justement celle qui m'importe.

Une autre piste proposée par Apple consiste à récupérer ses podcasts dans le fichier "iTunes Music Library.xml". J'ai bien trouvé le dit fichier mais manque de bol, quand iTunes a trouvé que son fichier de bibliothèque n'était pas valide il en a d'office créé un nouveau et... s'est empressé d'écraser le fichier XML susnommé qui contient une déclinaison human readable des infos de podcasts (entre autres mais c'est ça qui m'intéresse). C'est ballot.

En fouillant dans le dossier iTunes je suis tombé par hasard sur un dossier "Previous iTunes Libraries" contenant... des copies de sauvegarde du fichier de bibliothèque. Je ne sais pas quand il les fait effectivement mais je soupçonne que ce soit lors des mises à jour d'iTunes (celles que j'ai sont réparties tous les 2 à 5 mois)... Quoique, pas seulement puisqu'après que je lui aie refilé la dernière sauvegarde et relancé iTunes, il s'est empressé d'en faire une nouvelle. Super. C'est AVANT le plantage que ça servait à quelque chose, hein. Là c'est un peu tard.

Donc j'ai pu repartir avec une version d'il y a trois mois. C'est toujours ça. J'ai plus qu'à réimporter ce qui manque et ré-abonner les podcasts récents.

Alors bon, je vais maintenant automatiser une sauvegarde plus fréquente de ce fichier (et du XML aussi tant qu'à faire) pour pas me faire avoir une nouvelle fois mais je pensais pas que c'était aussi peu robuste...


Quelques petites BD #1

Au collège et lycée, je dessinais beaucoup, puis j'ai progressivement arrêté. Ces dernières années, ça me reprend une ou deux fois par an mais comme la plupart du temps je n'arrive pas à faire ce que je veux, ça ne dure pas.

Depuis quelques semaines, j'ai commencé à faire quelques petites BD allant de quatre cases à une page présentant de petits gags inspirées pour la plupart (parfois assez librement) d'anecdotes de bureau.

Pour une fois, ça semble tenir un peu. Principalement, je pense, parce que le dessin n'est ici qu'un support pour un gag et pas une fin en soi. Le fait que je trouve la plupart assez ratés techniquement n'est donc pas un si gros problème que d'habitude.

Je les publie au fur et à mesure sur Twitter ou encore deviantART mais je vais aussi les récapituler ici.

Voici donc la première fournée :

BD #1 - 09/04/2012 BD #2 - 21/04/2012 BD #3 - 30/04/2012 BD #4 - 12/05/2012
Images sous licence CC-BY

Concernant la dernière, quelques précisions pour mieux comprendre :

  • Boulder Dash est une célèbre série de jeux vidéos démarrée en 1983 (presque aussi vieille que moi :peur2:), probablement le jeu sur lequel j'ai passé le plus d'heures dans ma vie (même si Guild Wars se défend bien aussi), les captures d'écran sont des captures d'écran du jeu
  • RBS Change, j'en ai déjà parlé ici plusieurs fois, c'est le CMS / solutions e-commerce auquel je contribue au boulot
  • Magento est une solution e-commerce concurrente (l'une des plus connues)
  • Les deux logos dans la dernière case sont les logos des deux solutions

Côté réalisation je fais mes brouillons sur papier (parce que ça reste encore le support où j'arrive le mieux à quelque chose), puis je les scanne je mets au propre, mets en page et colorise via Photoshop Elements et tablette graphique Bamboo de Wacom (ça faisait depuis septembre dernier que je l'avais, il était temps de la rentabiliser un peu ^^).

Là ce sont les premières, donc je tâtonne un peu sur la technique mais j'espère m'améliorer un peu au fil du temps et notamment arriver à les faire un peu plus vite (là même celles qui comporte peu d'illustrations différentes me prennent facilement trois heures... du coup ça bride un peu les choses).


Visionner des fichiers ODT sur iPhone

Comme j'en avais marre (d'oublier) de réimprimer ma liste de livres/mangas/DVD/etc. à chaque fois que je la complète, je me disais que ce serait pratique de pouvoir la stocker directement sur mon iPhone. Sauf que forcément sur un système aussi fermé et cloisonné, ce n'est pas immédiat :

  • on ne peut pas juste le copier dessus vu que l'iPhone ne permet pas de transférer des données autrement que via iTunes (et là je saurais même pas où aller pour transférer un tel fichier)
  • le format ODT n'étant pas ©®Apple Inc.™, forcément l'iPhone ne le lit pas

Du coup il faut forcément passer par une appli dédiée avec toute la lourdeur que ça implique, en particulier la phase de recherche pour en trouver une... qui marche.

Premier essai : Drop Box

Sans trop d'illusions, j'ai tout de même vérifié que l'application Drop Box que j'ai installée il y a quelques temps n'en serait pas capable. La réponse est non. En même temps elle ne prétend pas le faire, on lui pardonne donc volontiers :o

J'ai donc fait une rapide recherche sur Google, pas grand chose d'intéressant à part "Cherchez « ODT » sur l'AppStore". C'est donc ce que j'ai fait.

Second essai : OliveODT

L'appli s'installe et démarre (c'est déjà un on début). On uploade un fichier dessus en activant un serveur web embarqué qui permet d'envoyer des fichiers dessus depuis n'importe quelle machine connectée en réseau local. Ok, ça fonctionne.

Enfin on affiche les fichiers... et là ça se corse : le premier que j'essaie d'ouvrir (et contenant de grands tableaux) bloque l'application que je suis obligé de relancer deux fois pour pouvoir tenter le second qui lui accepte de s'afficher mais qui ressemble à rien (taille du texte aléatoire, respect des sauts de ligne une fois sur deux... bref illisible).

Donc exit OliveODT. Je ne tente pas OliveOfficeBasic du même auteur parce que je doute que le rendu soit meilleur.

Candidat suivant.

Troisième essai : ConfettiDisk

Là aussi ça s'installe et se démarre sans problème, par contre on arrive sur un écran de login : il s'agit en fait d'un système en mode cloud, avec 100Mo de stockage gratuit. Pourquoi pas. C'est peu dans l'absolu mais totalement suffisant pour les 150Ko de listes que je veux pouvoir visionner.

Une fois le compte créé, l'upload depuis un ordinateur, ça se passe via une interface dans le navigateur. L'interface est simple, intuitive et fonctionne. Bon début.

Je me logue donc sur mon iPhone, synchronise les fichier (qui sont bien stockés sur le téléphone jusqu'à la prochaine synchro, pas besoin d'être connecté). Et là l'affichage est bon : conforme à ce que j'ai dans OpenOffice, le format A4 n'est pas idéal sur un écran de la taille de l'iPhone donc il faut zoomer mais ça fonctionne et c'est lisible.

Seul petit bémol : apparemment leur système de cloud ne permet pas de partage avec des amis (or ces listes contiennent aussi bien mes possessions que celles de mes frère et sœur, pouvoir partager les choses directement par là plutôt que par mail comme on le fait actuellement aurait pu être pratique).

Dans le doute, j'ai jeté un œil au dernier gratuit de la recherche "ODT" sur l'AppStore mais il semble apparemment se synchroniser via iTunes, ce qui ne m'arrange pas (je ne l'ai installé que sur mon Macbook, pas sur mon PC principal).

Je retiens donc ConfettiDisk comme répondant le mieux à ma problématique parmi les solutions gratuites.


Quelques trucs sur l’iPod Touch/iPhone #3

Ne plus ouvrir iPhoto lorsque l'iPhone est branché

Par défaut quand vous branchez un iPhone sur un Mac, il ouvre automatiquement iPhoto (l'iPhone étant reconnu comme un appareil photo). Pour désactiver ça, rendez-vous dans les préférences d'iPhoto et modifiez la valeur de l'option "Le fait de connecter l'appareil photo ouvre :" en sélectionnant "aucune application".

Verrouiller la touche majuscules

Sur un ordinateur, la touche permettant de verrouiller le clavier en mode majuscules est souvent assez inutile (on peut facilement utiliser un second doigt pour activer la majuscule), voire gênante : on l'enclenche plus souvent par erreur que volontairement... mais sur un iPhone, ça permet d'éviter de re-cliquer sur majuscule à chaque frappe quand on tape un mot en majuscule (sigle ou autre).

Pour cela il faut que dans les préférences (Réglages > Général > Clavier), vous activiez l'option plutôt mal nommée "Maj. verrouillées". Mal nommée parce que tout ce qu'elle active c'est le fait de pouvoir double-cliquer sur la touche de majuscule pour la bloquer (elle devient alors bleue)... Donc elle active le mode permettant de bloquer en majuscules et non le mode majuscules lui-même.

Voir la source

Cette petite astuce trouvée ici consiste à ajouter un signet dont la cible est en réalité un code JavaScript qui affichera la source de la page.

La méthode est simple :

  1. copiez ce code JavaScript, que je reprends ici au cas où le site en question cesserait d'émettre :
        javascript:(function(){var d=window.open("about:blank"),a=d.document;a.write("<!DOCTYPE html><html><head><title>Loading Source</title></head><body></body></html>");a.close();var b=a.body.appendChild(a.createElement("form"));b.setAttribute("method","post");b.setAttribute("action","http://ole.michelsen.dk/viewsource/?uri="+location.href);var c=b.appendChild(a.createElement("input"));c.setAttribute("type","hidden");c.setAttribute("name","DOM");c.setAttribute("value",encodeURIComponent(document.documentElement.innerHTML));b.submit()})()
        
  2. ajoutez un signet bidon nommé "Voir la source" (ou toute autre dénomination qui vous plaira)
  3. éditez le signet précédemment créé et collez ce code à la place de l'URL

Il vous suffit maintenant pour voir le code source d'un lancer le signet.