vendredi 1 janvier 2010

Comment être indispensable à un projet


Y en a marre que « mon génie » ne soit pas reconnu à sa juste valeur.

Comment être indispensable à un projet ? Certains savent parfaitement le faire soit volontairement, soit sans le faire exprès. Dans tous les cas, cela flatte l'ego - « Sans moi, tout s'écroule !» - et cela présente quelques avantages. Il y a en effet plusieurs stratégies pour bénéficier de ce privilège.

Il faut tout d'abord être seul. Ne jamais travailler en équipe. Sur un projet, il faut s'arranger pour récupérer une mission stratégique pour le projet, mais pas trop complexe pour être seul à en être chargé. Une petite couche de communication fera l'affaire. Si de plus, l'environnement de développement est complexe et coûteux, c'est l'idéal. On ne va pas donner quatre serveurs à chaque développeur !

Ensuite, il faut coder en respectant certains principes. Le premier, évident, est l'absence de documentation. Des commentaires peuvent être présents pour faire croire à une bonne volonté, mais ceux-ci ne doivent être que des plagiats du code. « /* Met zéro dans xzy */ ». Ou bien, si le chef de projet est plus exigeant, il faut proposer une documentation qui n'est pas à jour. Elle doit être rédigée comme cela, décalée de la réalité. À aucun moment, le document ne doit être conforme à l'application. Personne ne le saura sans entrer dans les sources.

Le code doit générer, en mode DEBUG, de très nombreuses traces, toutes plus incompréhensibles les unes que les autres et quelques warning. Utilisez des abréviations ou un vocabulaire rare, montrant la profondeur de votre analyse. Les messages ne doivent en aucun cas avoir un sens, sauf pour vous. Vous pouvez utiliser un code numérique par exemple et garder la fiche d'explication pour vous. « Erreur 23 ? Mauvais paramètre IP ». À la moindre occasion, activez ces traces pour montrer à quel point votre code est complexe. Ne loupez aucune occasion de le rappeler. Si on vous demande des explications pour la présence des warnings, répondez invariablement par « c'est normal ». Personne n'ira plus loin. Demandez régulièrement une copie des traces pour analyse. Comme elles sont volumineuses, personne ne souhaitera s'y plonger.

L'architecture doit être la plus éloignée possible de l'architecture évidente à l'énoncé de la mission. C'est assez facile à obtenir. Il suffit d'écrire un framework très ouvert, avec de nombreuses possibilités d'extensions, sans que cela soit nécessaire à l'application. « On ne sait jamais. Si un jour tu as besoin de … alors tu pourras grâce à ... ». Complétez vous-même.

Il faut ensuite utiliser toutes les techniques les plus absconses. L'introspection est un bon candidat. Ainsi, le code n'est pas lisible, car l'exécution est le fruit de traitements plus complexes, n'apparaissant pas directement dans le code. L'idéal est de rédiger une sorte de machine virtuelle, avec un automate à états, contrôlé par des données et des syntaxes binaires. Bien entendu, aucune documentation n'accompagne la syntaxe. Ainsi, la seule façon de comprendre le code est de le suivre en pas à pas. Deux, trois automates à états feront également l'affaire. Rien n'est plus incompréhensible qu'un énorme switch, complété de if en cascade ou un tableau de transition d'états, avec des valeurs numériques réparties apparemment aléatoirement.

Il est également possible d'abuser des inners-classes anonymes pour répondre à des interfaces. Ainsi, les classes importantes sont cachées dans le code des méthodes. L'absence de classe implémentant une interface ne manquera pas de laisser pantois tout développeur normalement constitué. Une classe externe peut également hériter d'une classe interne à une autre.

Les types génériques sont également un bon fermant pour du code illisible, à condition de les utiliser pour autre chose que pour les conteneurs. Comme personne ne sait comment cela fonctionne, il y a peu de chance que l'on critique votre code.

« Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter » - Edsger Dijkstra

La gestion d'erreurs doit également être complexe. Cela peut s'effectuer par l'utilisation d'une variable de thread et/ou une variable globale, maintenant la dernière erreur et/ou son contexte. Une petite modification d'un attribut d'un objet avant de propager l'erreur est également une bonne stratégie. Ainsi, le code des exceptions entraîne des effets de bords, impossible à suivre. Par exemple, utilisez des « return » ou des « continue » dans des blocs « finally » ; convertir des exceptions à la moindre erreur, pour empêcher de connaître l'origine du problème, etc.

Abusez également du multitâche. À la moindre occasion, lancez une tâche pour effectuer le traitement, et endormez la première en attente de la réponse. Cela ne sert à rien, mais complexifie le code de telle sorte que personne n'osera y toucher.

Certains frameworks peuvent aider à offusquer le code. La programmation par aspect est une merveille pour cela. Une petite règle par-ci par-là, et le code de l'application ne correspond plus du tout au code exécuté. « Si A invoque la méthode f() de B, alors invoque la méthode g() à la place ».

Choisissez judicieusement le nom des méthodes. L'idéal est de pervertir les conventions. Par exemple, les méthodes getX() doivent avoir un effet de bord, comme, par exemple, supprimer un élément d'un conteneur. Utilisez le même nom de méthode pour différentes classes, mais avec des sémantiques très différentes. Ainsi, le sens ne peut être connu sans vérifier à qui la méthode s'adresse. Dans les classes, ajoutez des méthodes de même nom que dans les sous-classes, mais avec plus de paramètres. Ainsi, l'intuition fera croire à l'appel de la méthode de la super classe, alors que ce ne sera pas le cas.

Utilisez plusieurs langages de programmation. C'est très efficace, car chaque projet est constitué d'une équipe « mono langage ». En choisissant des langages complémentaires abscons, Perl par exemple, ou plus confidentiel, Awk, Python, personne n'aura les compétences croisées permettant de maîtriser votre code.

Bien entendu, le code ne doit en aucun cas être efficace et performant. Ainsi, à la moindre occasion, il faudra faire appel à vous pour intervenir, analyser, tester, patcher (plusieurs fois évidemment). Bien entendu, à chaque sollicitation il faut répondre invariablement : « Oh là, là ! Cela va remettre en cause l'architecture. Je vais étudier les impacts avant de te répondre ». Une semaine est un minimum avant de revenir avec une solution qui ne doit jamais être complète. Elle doit imposer des modifications un peu partout dans le code de l'application. Eh bien oui, l'impact n'est jamais neutre, même pour remplacer un texte de message par un autre. « Tu comprends, je continue à améliorer mon code. Tu as ainsi la nouvelle version qui est vachement plus rapide ! » (quelques micro-secondes gagnées ici en en perdant plusieurs milli-secondes là).

Les paramètres. C'est très important les paramètres. Ils doivent être très nombreux, très dépendants les uns des autres, de telle sorte qu'il soit difficile d'en modifier un seul à la fois. Chaque modification doit au minimum en concerner deux. Pour cela, il faut que chaque décision de codage se traduise par un paramètre. Il ne faut jamais prendre aucune décision dans le code. Tout est le fruit de paramètres. Faut-il utiliser tel framework sous-jacent ou tel autre ? L'application accepte les deux, mais un seul à la fois. Un paramètre pour cela. On ne sait jamais. Faut-il privilégier la taille du code ou les performances ? Un paramètre. Faut-il activer la découverte automatique du contexte d'exécution ou paramétrer en dur les adresses IP ? Quel port réseau faut-il utiliser ? Bien entendu, il doit être strictement le même qu'un autre paramètre ailleurs, voire sur un autre serveur. Des conventions peuvent également valoriser d'autres paramètres s'ils ne sont pas renseignés. Port+1 pour tel paramètre, port-1 pour tel autre. Faut-il récupérer les paramètres en XML, dans un annuaire, en clef=valeur ? L'idéal est d'utiliser toutes les approches, via plusieurs frameworks. Certains paramètres peuvent être valorisés avec les trois approches, mais pas toujours dans le même ordre, d'autres seulement en XML et d'autre seulement en clef/valeur. Ainsi, aucune intuition ne peut s'appliquer à la valorisation des paramètres. Bien entendu, il faut que certains paramètres soient en dur dans le projet, afin d'obliger de le régénérer à chaque modification de déploiement. Plus il y a de paramètres, plus vous êtes indispensable.

Et les frameworks et autres composants Open Source ? Il faut les multiplier, en mélangeant les frameworks connus à des extensions inconnues de ces frameworks. « Tel plugin de log4j est indispensable ! ». Ainsi, vous présentez une façade séduisante, tout en cachant le diable dans les détails.

L'écriture d'un driver ou pseudo driver est un bon candidat pour rester à tout jamais dans un projet, sans être dérangé. Des algorithmes apparemment complexes peuvent également vous faciliter la tâche. « Mon algo calcule la répartition des tâches pour l'écriture des logs en parallèle de manière optimisée ! » Ou bien, il faut travailler sur des sujets très récents, dont les normes et les spécifications évoluent continuellement. La diversité des téléphones sans fil en est un bon exemple. Chaque jour présente son modèle, différent des autres, qu'il faut intégrer. Pour coder une implémentation d'une norme, il faut suivre l'approche de Microsoft, consistant à l'implémenter de telle sorte que toutes les décisions d'implémentation non décrites, soient des choix arbitraires, rigides, absolument incompatibles avec les autres implémentations. Le code est presque conforme HTML, mais le « HTML Microsoft ».

Bien entendu, juste avant vos congés, il faut apporter une modification « mineure » qui fera tout planter. L'équipe devra reprendre la version précédente du composant, en attendant votre retour. Vous saurez alors que vous avez gagné.

Comme le projet aura du retard sur le planning, on vous demandera de faire des heures supplémentaires. Vous les effectuerez sans oublier de signaler que cela vous coûte, que vous devez annuler des rendez-vous très importants, que c'est très exceptionnel, que c'est uniquement pour le bien du projet. Peu importe que la dérive du projet soit, entre autres, de votre fait, ce qui compte c'est que les chefs voient que vous vous investissez pour la réussite du projet. On remercie les efforts pour sortir de la panade, jamais les efforts ayant évité d'y être. C'est une règle importante à comprendre, dès le début de tout projet.

« Attends le dernier moment pour régler les problèmes, les félicitations n'en seront que plus importantes. » - Jean-Pierre Troll

Attention, il faut se méfier des audits internes ou externes. Les audits, surtout s'ils sont pratiqués par des consultants compétents – cas rare – risquent de vous nuire. Un auditeur consciencieux peut découvrir que votre code est fait en dépit du bon sens. L'auditeur devant regarder tout le code de l'application, il ne peut consacrer beaucoup de temps à votre œuvre. Pour éviter qu'il y mette trop de zèle, prenez rendez-vous en dernier, un vendredi soir veille de fête, et très tard. Vous êtes trop occupé à régler les problèmes des autres, ces incompétents. Arrivez en retard au rendez-vous et noyez le de discours, de justification tardive, de solutions alternatives sans jamais en choisir une, enfin, faite durer la réunion. Commencez par l'interroger sur son parcours, ses motivations. Demandez lui son avis sur les autres membres de l'équipe et saisissez toutes les occasions de déléguer vos responsabilités sur les choix des autres.

Vous avez une arme très forte : il est trop tard pour tout ré-écrire. Expliquez que les demandes initiales étaient plus ambitieuses, que c'est pour cela que vous avez anticipé les évolutions avec une architecture si complexe, etc. Enfin, il faut noyer le poisson. À chaque question difficile, expliquez que c'est plus compliqué qu'il n'y paraît, à cause d'une compatibilité ascendante, d'un historique, du respect d'une norme, etc. Enfin, justifiez vos arguments en faisant référence à des sources d'informations que l'auditeur ne peut connaître.

Il est temps d'aller voir votre manager pour demander une augmentation. Le couteau sous la gorge, et conforté par les sollicitations nombreuses de toute l'équipe à votre égard, il ne pourra que s'exécuter.

Quel est le risque ? Vous finirez inévitablement par vous lasser de votre code. D'une part, il est très difficile à déverminer, d'autre part, c'est fatiguant à la longue. Comment s'en débarrasser pour pouvoir faire autre chose ? Impossible de transmettre le bébé à un autre. C'est très difficile et il risque de découvrir la supercherie. En général, avec un peu de patience, le projet finit par échouer lamentablement. L'équipe est dissoute et l'application n'est jamais mise en production.

L'aura que vous aurez acquise ainsi vous permettra d'avoir de nombreuses sollicitations pour d'autres projets. Bis repetita.


« Si les ouvriers construisaient les bâtiments comme les développeurs écrivent leurs programmes, le premier pivert venu aurait détruit toute civilisation » - Gerald Weinberg

Parce qu'y'en a marre de la médiocrité et des parasites nuisibles, auréolés par des ignorants.


Jean-Pierre Troll

jp.troll@gmail.com

Parce que vous n'êtes pas prêts de vous débarrasser de moi.