Article original : The Top Five Developer Skills That'll Make You a Hero (Hint: Involves LEGOs)

Par Jean-Paul Delimat

Programmer, c'est comme construire quelque chose avec des LEGO. N'importe quel développeur peut prendre un tout nouveau set de LEGO et le construire en suivant les instructions. C'est très facile. Pensez à cela comme aux devoirs de codage à l'école ou aux tutoriels de niveau débutant.

Un vrai projet logiciel est différent. C'est comme construire un très grand château en LEGO. Sauf qu'il a déjà été construit dans le passé. Ensuite, quelqu'un l'a démoli en morceaux avec un coup de pied sauvage. Les plus grosses parties restent plus ou moins ensemble. Mais les plus petites parties ont été complètement écrasées. Certains éléments sont passés par la fenêtre.

Vous obtenez une boîte contenant ce qui reste, mais aussi des milliers de pièces d'autres sets. Et bien sûr, les instructions ont disparu. Vous ne pouvez compter que sur une seule photo pour savoir à quoi ressemble le château.

Maintenant, c'est intéressant ! Voyons ce que nous pouvons faire pour travailler efficacement dans un tel environnement.

1. Acceptez les inconnues

La première étape de toute tâche de développement est de comprendre ce que vous devez faire. Cela semble évident. Et pourtant, plus la tâche est grande, plus vous avez de variables inconnues. C'est le moment de fixer des attentes claires.

Si vous n'avez aucune idée de comment commencer, il est inutile de trop réfléchir et conceptualiser. Commencez et familiarisez-vous avec les éléments clés dont vous avez besoin. Ensuite, réfléchissez à nouveau. Si quelqu'un vous demande des estimations ou un délai dès le départ, soyez ouvert et honnête. Certaines parties du système que vous ne connaissez pas ou que vous ne comprenez peut-être pas. Et c'est OK.

Pensez à des plateformes comme Facebook, Netflix ou Oracle. Ou à tout autre logiciel d'entreprise plus grand. Très peu de personnes peuvent saisir toute l'étendue. Ceux qui le peuvent l'ont soit construit, soit passé des années à travailler dessus. Donc, tout d'abord, ne vous en voulez pas de ne pas tout savoir. Et plus important encore, acceptez que vous ne saurez pas tout.

Les développeurs expérimentés et productifs ne sont pas de meilleurs codeurs. Ils sont meilleurs pour évaluer ce qu'ils doivent faire. Et pour choisir les bonnes stratégies pour faire face aux inconnues.

Analogie LEGO : Pensez au set de château que nous voulons reconstruire. Supposons que quelqu'un vous donne une photo du château et la boîte, et vous demande "combien de temps avez-vous besoin pour construire le château ?" Il n'y a pas de bonne réponse à cela sauf "Je ne sais pas encore. Laissez-moi commencer et voyons où j'en suis après un jour ou deux".

L'approche ultime "J'ai peur des inconnues" pour cette tâche serait de disposer tous les éléments de la boîte sur le sol. Essayez de les séparer dans les sets auxquels ils appartiennent en fonction de la couleur et de la forme. Ensuite, regardez la photo et faites une carte mentale de la façon d'assembler les briques.

Cette approche n'est pas très efficace pour deux raisons. Premièrement, si le château est trop grand, vous n'y arriverez probablement jamais. Deuxièmement et surtout : vous ne pouvez pas évaluer les progrès. Vous pourriez être sur la bonne voie ou pas du tout. Vous n'avez pas de boucle de feedback.

Une autre approche serait de commencer à construire le château. Au fur et à mesure, vous apprendrez si c'est facile de trouver les pièces dont vous avez besoin ou non. Vous saurez si la photo montre tous les détails ou si la construction est plus complexe qu'elle n'y paraît.

Sur la base de ces informations, vous pourrez faire une estimation plus éclairée du temps et de l'effort qu'il faudra pour faire le travail. Et si cela vaut la peine de le faire.

Si vous en avez besoin pour demain matin, peut-être que le fait d'aller au magasin et d'acheter le même château à nouveau est une meilleure solution ? Ce n'est peut-être pas à vous de décider, mais les solutions à un problème ne passent pas toujours par plus de code.

2. Acceptez le compromis

Les développeurs louent et valorisent souvent "une grande attention aux détails". Chaque offre d'emploi contient cela sous une forme ou une autre. C'est très bien. Mais ne confondez pas attention aux détails avec entêtement et perfectionnisme.

Lorsque vous commencez une grande tâche, vous devez en définir deux versions. La première version est le minimum nécessaire pour vérifier que les choses fonctionneront comme vous le pensez.

C'est ce que j'appelle "travailler horizontalement". Chaque partie de votre grande tâche est une verticale. Vous n'avez pas besoin d'aller en profondeur pour obtenir les premiers résultats. Concentrez-vous d'abord sur le cas d'utilisation ou le scénario principal. Et partez de là.

Les choses que vous pouvez laisser de côté dans la première version :

  • gestion des erreurs
  • cas limites
  • code propre
  • configuration

Ne pensez pas à tout cela et écrivez simplement le code dont vous avez besoin tel qu'il vient sous vos doigts. Vous devriez obtenir une couverture fonctionnelle élevée rapidement. Bien sûr, il faudra beaucoup de temps pour passer de cette première version simpliste à la version finale. Alors, quel est l'intérêt ?

C'est une manière plus sûre de progresser. Vous voulez vérifier vos hypothèses. Aussi intelligent et capable que vous soyez, la conception et la conceptualisation ne peuvent vous mener que jusqu'à un certain point. Mettez les mains dans le cambouis. Cela vous donnera plus de connaissances et de perspicacité que n'importe quel "réflexion approfondie".

C'est le même principe qui s'applique aux MVP pour de nouveaux produits ou fonctionnalités en entreprise. L'approche a également l'avantage que vous pouvez montrer votre première version et obtenir des feedbacks. Ou poser des questions. Il est plus facile de brainstormer sur du code existant que sur un dessin ou un concept.

Analogie LEGO : Vous construisez la tour du château. Sur la photo, les murs de la haute tour sont faits de briques grises et blanches entrelacées. Il y a une princesse enfermée dans la tour et un dragon sur le toit.

Vous trouvez la princesse et le dragon, mais il vous faudrait une éternité pour trouver les briques grises et blanches dont vous avez besoin. La bonne approche est de construire le mur en utilisant n'importe quelles briques, et de placer la princesse et le dragon. Vous pouvez laisser un TODO comme "Améliorer les briques du mur".

L'idée est que vous avez identifié un problème : il va être difficile de construire le mur parfait. Acceptons cela et passons à la découverte de tous les autres obstacles que nous ne connaissons pas encore. Accepter le compromis vous empêche de rester bloqué.

Même si vous ne revenez jamais au TODO, vous pouvez dire à votre client : "Voici le château complet. Nous savons que nous devons améliorer le mur de la tour, mais il est construit". C'est bien mieux que "Nous avons un retard important parce qu'il nous a fallu une éternité pour trouver les bonnes briques pour la tour. Mais regardez, la tour est parfaite et exactement comme sur la photo que vous nous avez envoyée. Maintenant, nous allons nous occuper du reste du château".

Important : ne confondez pas compromis et négligence.

Les éléments clés de la tour sont la princesse et le dragon. Ne mettez pas un fermier dans la tour et un chat sur le toit en pensant que c'est un compromis acceptable. Cela ne fonctionnera pas :)

3. Commencez par le monde extérieur

Il y a beaucoup de choses que vous pouvez contrôler. Et des choses que vous ne pouvez pas. Je l'ai appris à mes dépens lors de l'une de mes premières missions en tant que développeur il y a dix ans. La tâche était d'intégrer une API externe et de traiter les données. J'avais une semaine. C'était un délai très raisonnable, même pour un débutant comme moi.

Voici ce que j'ai fait (et ce que vous ne devriez pas faire) :

C'est lundi matin. J'ai lu la documentation de l'API pendant 10 minutes. Cela semble très facile. Je crée un ensemble de données de test et passe à l'écriture du code pour le traiter. Je testerai avec la vraie API une fois que j'aurai terminé.

Mercredi matin et j'ai presque terminé. Je pense que mon code est propre et bien conçu et tout (ce n'était pas le cas). Maintenant, je dois simplement intégrer l'API et je finirai probablement en avance. Je ne peux m'empêcher de penser que "Je suis génial".

Je passe rapidement à la partie API. J'essaie de l'atteindre avec mon code. Sauf que je n'y arrive pas. Quelque chose ne va pas. Je perds toute la journée à tout vérifier. En utilisant différents clients API. Aucun progrès. La journée passe et il est maintenant mercredi soir.

Je suis bloqué, et je me sens tout sauf génial.

Je me mets au travail jeudi et demande de l'aide à un collègue. Il me dit que l'accès à l'API peut être restreint par IP et que je dois contacter l'entreprise pour mettre nos IP sur liste blanche. Bien, j'ai une voie à suivre.

J'envoie un email à l'entreprise propriétaire de l'API. Il est environ 8h. Je m'attends naïvement à une réponse rapide et à une résolution en quelques minutes. Je transpire toute la matinée et à midi, je prends enfin le téléphone et appelle le numéro de support. J'explique mon problème et essaie de souligner le mieux possible à quel point c'est une "urgence" (ce n'était pas le cas).

La personne à l'autre bout du fil m'explique que le temps de mise sur liste blanche est généralement de 1 ou 2 jours. Maintenant, je suis déprimé. 1 ou 2 jours ? Comment est-ce possible ? Ma tâche est la plus importante au monde (seulement pour moi bien sûr) et ils me disent "1 ou 2 jours" ?

Tout à coup, je ne suis plus en avance. Je suis en retard. J'ai échoué. Je vais voir mon patron et lui dis que j'ai tout gâché. J'aurais dû vérifier l'API lundi matin. J'aurais alors demandé l'accès le même jour et j'aurais écrit mon code en attendant. Il me sourit simplement en disant "Oui, tu aurais dû".

J'obtiens enfin l'accès vendredi et dois rester très tard pour terminer le travail. J'adapte mon code aux nombreuses surprises que les données de l'API apportent. Adieu code bien conçu et propre. Je le justifierai plus tard en disant "Il n'y avait pas de temps pour cela" (il y en avait).

Dans ma naïveté de l'époque, je pensais que les problèmes d'accès et la mauvaise documentation étaient de la très mauvaise chance. Maintenant, je peux dire que c'était business as usual.

La leçon est de commencer par ce que vous ne pouvez pas contrôler. Confirmez chaque hypothèse que vous avez sur l'environnement. Utilisez des moyens manuels et peu coûteux pour essayer les choses le plus tôt possible.

Analogie LEGO : Imaginez que vous construisez le château et que les choses se passent bien. Vous avez maintenant mélangé la boîte environ 100 fois à la recherche de pièces. Vous ne pouvez vous empêcher de penser "Je ne suis jamais tombé sur ce énorme dragon orange assis sur la tour sur la photo".

Vous ignorez cette information pour vous concentrer sur les bons progrès que vous avez réalisés. C'est humain. Avancer est plus excitant que de traiter les problèmes. À la fin, vous devrez reconnaître que le dragon est manquant. Et dire à votre client très tard que la plus grosse pièce du set ne sera pas présente. Ce n'est pas bien.

La chose à faire à la place est de suivre cette piste : "Où est le dragon ?". Passez le temps nécessaire pour être sûr à 100 % qu'il n'est pas là. Soulevez le problème immédiatement. Dites à votre client "Hey, il n'y a pas de dragon dans la boîte. Je ne peux pas fabriquer un dragon à partir des autres briques. Que faisons-nous ?"

Les gens sont surprenamment OK avec les problèmes lorsqu'ils les connaissent assez tôt. Découvrir les problèmes tôt ouvre plus de solutions possibles. "Devons-nous continuer en sachant qu'il n'y a pas de dragon ?" "Pouvons-nous acheter le dragon seul ?" "Je vois un dinosaure dans la boîte. Pouvons-nous l'utiliser à la place ?"

4. Tracez une ligne claire

Lorsque vous commencez à travailler sur une nouvelle fonctionnalité pour un système existant, commencez par définir comment elle s'interface avec le code existant. Bien sûr, vous devriez essayer de suivre les principes SOLID, etc., mais la partie clé est plus simple que cela. Essayez simplement de rendre la surface de contact aussi faible que possible.

Le simple processus de définir clairement la coupure améliorera votre solution. Cela vous forcerà à aborder les questions clés : Comment les utilisateurs ou le système utiliseront-ils mon code ? Quelles entrées vais-je recevoir ? Quelles sorties dois-je produire ? Cela vous aide à garder les yeux sur l'objectif.

Cela est d'autant plus vrai si vous ne connaissez pas beaucoup le système avec lequel vous travaillez. C'est une bonne opportunité d'explorer les inconnues avant de plonger dans ce que vous connaissez déjà.

Cela facilite également l'activation ou la désactivation de la fonctionnalité. Vous pouvez utiliser un flag booléen ou un mécanisme de basculement de fonctionnalité plus avancé.

Analogie LEGO : Supposons que vous devez construire une extension du château. Les exigences sont plutôt de haut niveau, donc il y a beaucoup de place pour la créativité. Vous ne pouvez pas toucher au château existant.

Vous pourriez construire une grande extension pour vous rendre compte qu'il n'y a pas d'espace pour l'attacher au château. C'est malheureux. Vous devrez rapidement modifier votre extension pour qu'elle s'adapte d'une manière ou d'une autre.

La bonne approche serait de penser d'abord à la surface de contact. Où sera l'extension sur le château ? À quelles briques puis-je l'attacher ? Quelle forme ont-elles ? Assemblez les quelques briques de l'extension en l'attachant au château. Vérifiez qu'elles s'emboîtent pour une connexion solide. À partir de là, vous pouvez construire n'importe quelle extension que vous voulez.

5. Ne soyez pas trop DRY

DRY signifie Don't Repeat Yourself (Ne vous répétez pas). C'est probablement la règle la plus facile à suivre. Dès que vous voyez des lignes de code dupliquées, vous faites une abstraction. Cela peut être une classe de base, une méthode d'assistance, peu importe.

Que se passe-t-il ensuite ? La personne suivante arrive et le code commun doit changer pour couvrir plus de cas. Ils ajoutent des paramètres et des instructions if pour faire face aux complexités émergentes. Bientôt, les 5 lignes initiales et simples deviennent 30 lignes et il est difficile de comprendre ce qui se passe.

Une mauvaise lisibilité n'est pas un bon compromis pour les répétitions de code.

Il aurait été préférable de garder les lignes dupliquées. Vous auriez alors pu changer chaque instance à volonté.

La prochaine fois que vous optez pour "l'abstraction plutôt que la répétition", demandez-vous : combien de fois avez-vous vu quelqu'un revenir d'une abstraction ? Comme supprimer une classe de base et remettre le code commun dans les classes héritées. Je parie que la réponse est jamais.

La raison est que les abstractions et les modèles de conception en général sont cool et sophistiqués. Et s'il en existe, alors "il doit y avoir une bonne raison". Donc, une fois que vous introduisez l'abstraction, il y a de bonnes chances qu'elle reste là pour toujours.

Cela signifie-t-il que vous ne devriez jamais utiliser d'abstractions ? Non. Utilisez des abstractions lorsqu'elles correspondent aux exigences. Des choses comme :

  • "Nous voulons journaliser chaque appel à cette méthode avec les entrées et les sorties"
  • "Nous voulons journaliser chaque requête HTTP avec les données a, b, c"
  • "Chaque fois qu'un utilisateur est créé, nous devons faire ceci et cela"

Ce sont de bons candidats pour l'abstraction et il y a beaucoup d'autres exemples. Mais remarquez comment les exigences sont plus techniques que liées à l'entreprise (journalisation, sécurité, analytique, etc.). Il est rare que les exigences favorables à l'abstraction fassent partie de votre domaine métier.

Pourquoi ? Parce que le domaine métier est proche du monde réel. Et cela, nous ne pouvons pas le contrôler. Les hypothèses faites au début d'un projet sont souvent obsolètes très rapidement. Ne sur-ingéniez pas le code juste pour éviter la répétition.

Analogie LEGO : Aucune. Il n'y a pas de concept DRY dans les briques Lego.

Conclusion

Travailler intelligemment ne consiste pas à écrire un meilleur code. Il s'agit de comprendre ce qui doit être fait et de progresser en toute sécurité vers l'objectif.

Les tâches de développement grandes et difficiles comporteront des inconnues. Acceptez-les. Apprenez à travailler avec elles.

Vous serez plus productif si vous gardez les choses simples et alignez les attentes pour le résultat avec votre équipe, votre patron, votre client, et idéalement tout le monde.

Merci d'avoir lu !

Publié à l'origine sur The Fire CI Blog.