Blogue
Savoir-faire et technologie
Histoires, idées et perspectives sur la stratégie, la technologie et les solutions d’affaires.
Articles à la une
<h2>Qu'est-ce que la certification SOC 2 ?</h2><p>La certification SOC 2 (Service Organization Control 2) est une norme élaborée par l'American Institute of Certified Public Accountants (AICPA) qui évalue la capacité d'une organisation à gérer les risques liés à la sécurité, à la disponibilité, à l'intégrité du traitement, à la confidentialité et à la protection de la vie privée des données qu'elle traite pour le compte de ses clients.</p><p>La certification SOC 2 repose sur cinq principes, appelés critères de confiance, qui définissent les exigences minimales que doit respecter une organisation pour assurer la sécurité et la qualité de ses services. Ces critères sont les suivants :</p><ul> <li><strong>Sécurité</strong> : l'organisation protège les données contre les accès non autorisés, les modifications, les divulgations, les dommages ou la perte.</li> <li><strong>Disponibilité</strong> : l'organisation assure la disponibilité et le fonctionnement continu de ses services conformément aux accords conclus avec ses clients.</li> <li><strong>Intégrité du traitement</strong> : l'organisation traite les données de manière complète, valide, exacte, opportune et autorisée.</li> <li><strong>Confidentialité</strong> : l'organisation respecte les engagements et les obligations de confidentialité envers ses clients et les tiers concernant les données qu'elle traite.</li> <li><strong>Protection de la vie privée</strong> : l'organisation respecte les principes de protection de la vie privée définis par l'AICPA et les lois applicables en matière de collecte, d'utilisation, de conservation, de divulgation et d'élimination des données personnelles.</li></ul><p>« Obtenir et maintenir la certification SOC 2, je le vois comme un ultramarathon et non un sprint sur 100 mètres. C'est une première étape, dans un long processus en constante évolution. La cybersécurité, dans son ensemble, nécessite une rigueur et une attention aux détails constante auquel notre équipe est prête à s’attarder. »</p><p>– Vincent Huard, Vice-Président, gestion et analyse des données</p><p>Pour obtenir la certification SOC 2, une organisation doit faire l'objet d'un audit indépendant réalisé par un cabinet comptable qualifié qui vérifie qu’elle respecte les critères de confiance applicables à ses services. L'audit porte sur la conception et l'efficacité des contrôles mis en place par l'organisation pour assurer la conformité aux critères de confiance.</p><h2>Quelle est la différence entre la certification SOC 2 Type 1 et Type 2 ?</h2><p>Il existe deux types de certification SOC 2. C’est entre autres la durée de l’audit qui les distingue. SOC 2 Type 2 est couvert par l’audit le plus long et rigoureux.</p><ul> <li>La certification SOC 2 Type 1 atteste que l'organisation respecte les critères de confiance à une date donnée à une date précise. Elle évalue la conception des contrôles, mais pas leur efficacité dans le temps.</li> <li>La certification SOC 2 Type 2 atteste que l'organisation respecte les critères de confiance sur une période de temps définie, généralement de trois à douze mois. Elle évalue la conception, mais également l'efficacité des contrôles, en tenant compte de leur fonctionnement réel et de leur évolution.</li></ul><p>En d’autres mots, la certification SOC 2 Type 2 répond à des critères plus exigeants et rigoureux, car elle implique un suivi continu et une vérification régulière des contrôles. Elle offre une assurance plus élevée sur la qualité et la sécurité des services fournis par l'organisation.</p><h2>Quels sont les bénéfices pour nos clients ?</h2><p>En obtenant la certification SOC 2 Type 2, Spiria réaffirme sa posture de partenaire de confiance dans la réalisation de projets de développement de solutions numériques pour ses clients. Voici quelques bénéfices principaux qui permettent à nos clients de se lancer la tête tranquille dans des projets d’envergure avec Spiria :</p><ul> <li>La garantie que nous respectons les normes les plus élevées en matière de sécurité de l'information</li> <li>La garantie que nous protégeons les données de nos clients contre les menaces internes et externes.</li> <li>La confiance que nous assurons la disponibilité et la performance de nos services</li> <li>La confiance que nous sommes capables de réagir rapidement et efficacement en cas d'incident.</li> <li>La certitude que nous traitons vos données avec intégrité, en respectant les règles de validation, d'exactitude, de traçabilité et d'autorisation.</li> <li>La tranquillité d'esprit que nous respectons vos obligations de confidentialité et que nous ne divulguons pas vos données à des tiers non autorisés.</li> <li>La sécurité que nous respectons les principes de protection de la vie privée et que nous nous conformons aux lois applicables en matière de données personnelles.</li></ul><p>La certification SOC 2 Type 2 est un gage de confiance et de sécurité pour nos clients qui témoigne de notre engagement à fournir des services de qualité et à respecter les meilleures pratiques du secteur. Elle représente l’excellence en matière de sécurité des données dans le marché tout en étant de plus en plus prisée pour les projets de développement logiciels. Il était donc tout naturel pour Spiria d’être parmi les quelques firmes d’experts à s’y conformer en Amérique du Nord. Nous sommes fiers d’arborer cette certification et d'assurer à la fois l'excellence, la fiabilité et la rigueur de nos pratiques d’affaires.</p><p>Démarrez un projet en toute confiance : <a href="mailto:nouveauprojet@spiria.com">nouveauprojet@spiria.com</a>.</p>
<p>Les équipes de Spiria ont une longue et riche expérience avec les deux types de contrats, et nous vous dévoilons ici ce que nous avons appris au fil du temps sur le sujet et quels sont les critères de succès pour chaque option.</p><p>Clarifions tout d’abord ce que sont ces deux types de projets :</p><h3>Projets temps & matériel</h3><p>Projets dont la portée (activités, livrables, inclusions comme exclusions, etc.) peut être plus ou moins clairement définie. L’évaluation initiale des coûts présente une fourchette de prix probable pour la réalisation du dit projet. Les coûts sont facturés selon les heures réelles exécutées et le matériel/ressources (autres coûts, par exemple des licences logicielles ou des services infonuagiques) nécessaire. Cette approche est plus flexible, car elle permet des changements de spécifications tout au long du processus de développement. L’agilité est encouragée et les contrôles de gestion de projets sont mis de l’avant.</p><h3>Projets forfaitaires ou fixes</h3><p>Projets dont la portée est plus souvent bien ou très bien définie. Le niveau de confiance de l’évaluation initiale des coûts repose sur des informations plus claires que le précédent type de projet. Comme son nom l’indique, les coûts sont fixés au départ, peu importe les heures réellement exécutées et le coût en matériel et ressources. Par conséquent, les notions de risques et de profitabilité sont des considérations plus critiques à évaluer dans ce type de projet. Toute modification des spécifications est encadrée par un processus de demande de changement et est facturée en tant que travail supplémentaire.</p><p>Dans un premier scénario, pour un projet préalablement qualifié, le type de projet (temps/matériel vs fixe) peut être imposé par le client, les exigences internes des organisations ou encore des réglementations, par exemple dans le cas des appels d’offres (majoritairement fixes). Lorsque possible, Spiria peut proposer une approche pour mitiger les risques et mieux saisir la portée du projet, comme proposer au client un investissement initial dans une phase découverte, en mode temps/matériel ou forfaitaire, dans l’intention de pouvoir proposer par la suite les phases de développement et de déploiement en mode forfaitaire. Ceci n’empêche bien sûr pas le client de changer de priorité ou de modifier la portée à la suite de la phase de découverte. Notre flexibilité doit nous permettre de négocier avec le client la portée définie en variant les inclusions/exclusions, dans l’objectif de rester dans l’enveloppe budgétaire forfaitaire contractuelle entendue.</p><p style="text-align: center;"><img src="https://cdn.prod.website-files.com/67c06f07cfba9b0adb43e16c/68470cad54d506e6dad2ea43_process-fr.webp" style="width: 60%; border: none;" alt="Un cycle projet type." title="Un cycle projet type."></p><p style="text-align: center; font-style: italic;">Figure 1. Un cycle projet type.</p><p>Dans un deuxième scénario, si le type de projet n’est pas imposé, ceci nous donne la latitude du choix de la stratégie. Habituellement, les clients prévoient des sessions de rencontres avec les différents fournisseurs pour répondre à leurs questions. Une réflexion interne s’impose ensuite pour bien évaluer les facteurs décisionnels menant à la meilleure stratégie. À cet effet, le tableau ci-dessous présente une liste non exhaustive de points qui éclairent les équipes dans cette réflexion. Ces points sont pondérables (facilement identifiables, quantifiables ou mesurables) ou impondérables, en fonction des informations fournies lors des rencontres initiales, dans les cahiers de charge, ou pouvant être obtenues par des demandes au client. Les annotations des deux colonnes de droite sont simplement des suggestions de poids relatifs aux deux types de projets.</p><table cellpadding="0" cellspacing="0" style="width:100%"> <tbody> <tr> <td style="width:76%"><strong>Points</strong></td> <td style="width:12%"><strong>Fixe</strong></td> <td style="width:12%"><strong>T&M</strong></td> </tr> <tr> <td>Le plan d’affaires, les requis, les besoins et les attentes sont claires.</td> <td>➕➕</td> <td>➕</td> </tr> <tr> <td>Les processus et règles d’affaires sont nombreux et complexes.</td> <td>➕</td> <td>➕➕</td> </tr> <tr> <td>Le budget client est identifié et la planification budgétaire est cadrée.</td> <td>➕</td> <td>➖</td> </tr> <tr> <td>L’échéancier est strict ou critique en raison du contexte client ou d’affaires.</td> <td>➕</td> <td>➖</td> </tr> <tr> <td>Les expertises nécessaires sont identifiables.</td> <td>➕</td> <td>➕</td> </tr> <tr> <td>La structure organisationnelle et décisionnelle est grande et complexe.</td> <td>➖</td> <td>➕</td> </tr> <tr> <td>Les aspects légaux sont complexes.</td> <td>➖</td> <td>➕</td> </tr> <tr> <td>Les relations sont déjà établies (historique) ou des contacts sont nos promoteurs.</td> <td>➕</td> <td>➕</td> </tr> <tr> <td>Le calcul de risques, les incertitudes et la contingence sont élevés.</td> <td>➖</td> <td>➕</td> </tr> <tr> <td>Les risques de dérives sont probables.</td> <td>➖</td> <td>➕</td> </tr> <tr> <td>Le client détient une capacité en effectifs ou en connaissances internes<br> (designer, équipe de développement, AQ, etc.).</td> <td>➕</td> <td>➕</td> </tr> <tr> <td>L’environnement technologique est connu.</td> <td>➕</td> <td>➕</td> </tr> <tr> <td>Les contraintes technologiques sont importantes (ex. : système hérité).</td> <td>➖</td> <td>➕</td> </tr> <tr> <td>Les défis d’intégration sont nombreux et complexes.</td> <td>➖</td> <td>➕</td> </tr> <tr> <td>Les choix technologiques sont imposés.</td> <td>➕</td> <td>➕</td> </tr> <tr> <td>Les données sont disponibles pour faire l’assurance qualité fidèlement.</td> <td>➕</td> <td>➕</td> </tr> <tr> <td>La solution est assujettie à des certifications spéciales.</td> <td>➖</td> <td>➕</td> </tr> </tbody></table><p><br>Le résultat de cette réflexion peut amener vers différentes approches représentées dans le diagramme suivant :</p><p><img src="https://cdn.prod.website-files.com/67c06f07cfba9b0adb43e16c/68470cb0f4619dcfb509565b_strategies-fr.png" style="width: 100%; border-style:solid; border-width:1px;" alt="Les différentes stratégies (approches)." title="Les différentes stratégies (approches)."></p><p style="text-align: center; font-style: italic;">Figure 2. Les différentes stratégies. (Cliquer pour agrandir.)</p><p>La stratégie sélectionnée dicte la façon donc les ententes contractuelles sont conclues. Ce choix d’approche a des incidences sur tout le déroulement du projet et son succès final. La transparence du processus de choix et la justification des motifs auprès du client permettent de démarrer la relation sur des bases saines. Les objectifs ultimes sont de livrer un projet qui respecte nos valeurs spiriennes et qui apporte la valeur attendue au client.</p>
Tous les articles
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
<p>Nous avons utilisé JMeter pour effectuer des tests de performance pour l’un de nos clients, en visant 400 utilisateurs simultanément. Nous avons rencontré quelques difficultés au départ, que nous avons surmontées en optimisant le code, en utilisant le bon type de samplers et leurs propriétés, le bon type de groupes de threads pour atteindre le niveau de simultanéité souhaité, et bien sûr, en utilisant les listeners uniquement pour le débogage, et non pour les tests de charge réels.</p><p>D’autres difficultés sont apparues lorsque le nombre d’utilisateurs a été porté à 1 000 simultanés, car JMeter n’arrivait pas à gérer un volume aussi important. Par exemple, il a commencé à faiblir tout en imposant la même charge aux serveurs AWS, et les résultats des tests de charge indiquaient plutôt des erreurs de JMeter que des défaillances réelles des serveurs. De sérieux changements de configuration ont été nécessaires pour porter la capacité de JMeter à un niveau où il pourrait générer sans faiblir la charge souhaitée et faire tomber les serveurs AWS.</p><p>Voici nos meilleurs trucs pour faire en sorte que JMeter soit en mesure de mettre à genoux des serveurs AWS :</p><h2>Distribuer les tests</h2><p>Le test distribué est votre première et meilleure arme pour générer suffisamment de charge afin d’amener à son point de rupture un serveur AWS autodimensionnable et parfaitement équilibré en charge. L’utilisation de JMeter en local limite le nombre d’utilisateurs simultanés qui peuvent agir sur un système donné à un moment donné : vous êtes entièrement dépendant du processeur et de la mémoire du système sur lequel le test de charge est effectué.</p><p>En utilisant le mode maître-esclave, l’exécution du test sur deux serveurs ou plus répartit la charge sur les systèmes, ce qui permet de dimensionner JMeter à la taille et à l’espace de toutes les machines maître-esclave combinées. La distribution des machines permet non seulement de répartir la charge pour générer un nombre énorme de threads chaque seconde, mais aussi de distribuer les fichiers CSV de données de test et les énormes fichiers de résultats pour encore plus de puissance. La communauté en ligne atteste de l’exécution de 250 à 500 threads simultanés par serveur. Vous pouvez ajouter des machines au système distribué en fonction du besoin global de génération de charge.</p><h2>Augmenter les ports de connexion TCP</h2><p>Une machine Windows standard n’établit des connexions TCP/IP sortantes que par les ports 1024-5000, et il faut jusqu’à 4 minutes pour les recycler. L’exécution de tests de charge nécessite un grand nombre de connexions en peu de temps, saturant rapidement cette plage de ports. Lorsque nous avons tenté de cibler 400 utilisateurs simultanés pour tester en charge les services AWS, la machine JMeter qui tourne sur Windows n’a même pas pu atteindre cette cible de simultanéité.</p><p>Pour augmenter le nombre maximum de ports éphémères, suivez ces étapes :</p><ol> <li>Sur chaque JVM, lancez l’éditeur de registre.</li> <li>Localisez la sous-clé suivante dans le registre, puis cliquez sur Parameters :<br> HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters.</li> <li>Faites un clic droit sur Parameters.</li> <li>Créez une nouvelle valeur DWORD avec le nom MaxUserPort.</li> <li>Faites un clic droit sur MaxUserPort.</li> <li>Entrez 65534 pour le champ Value Data.</li> <li>Sous le bouton radio de sélection pour la Base, sélectionnez le bouton radio Decimal.</li> <li>Cliquez sur OK. Fermez le registre.</li> <li>Relancez chaque agent de charge JMeter.</li></ol><h2>Augmenter la mémoire heap</h2><p>Après avoir augmenté le nombre de connexions TCP utilisant des ports, nous avons amené JMeter au niveau de simultanéité souhaité. Mais assez vite, les machines JMeter ont commencé à produire des erreurs “Out of memory”. Il était essentiel d’effectuer des tests de charge en utilisant le mode GUI, car une intervention manuelle était nécessaire pour démarrer et arrêter plusieurs groupes de threads pendant que l’application changeait sans cesse d’état, passant d’inactive à active, puis à fermée. Même si seul Aggregate Listener a été utilisé avec le moins de configuration possible pour économiser de l’espace, nous avons continué à obtenir des erreurs provoquées par des problèmes de mémoire.</p><p>La JVM peut être réglée finement pour augmenter la mémoire vive allouée. Lorsqu’un programme Java comme JMeter nécessite une quantité de mémoire importante, la RAM est généralement réaffectée.</p><p>JMeter utilise jusqu’à 512 Mo de RAM par défaut, comme indiqué dans les scripts de lancement jmeter.sh ou jmeter.bat. Nous avons augmenté la taille du heap à 4 Go :</p><pre><code>set HEAP=-Xms1024m -Xmx4096m -XX:MaxMetaspaceSize=1024m</code></pre><p>Cependant, relancer JMeter après avoir augmenté la taille du heap produisait l’erreur suivante :</p><blockquote><p>Invalid initial heap size: -Xms4g<br>The specified size exceeds the maximum representable size.<br>Error: Could not create the Java Virtual Machine.<br>Error: A fatal exception has occurred. Program will exit.<br>errorlevel=1</p></blockquote><p>Pour régler cette erreur, nous avons dû mettre à jour Java (JDK en particulier) et JMeter avec les dernières versions. En effet, le dernier JDK contient un compilateur optimisé serveur qui améliore l’exécution du code Java, donc celle de JMeter. Après avoir téléchargé et installé la dernière version du JDK, nous avons redémarré le serveur JMeter, et voilà, plus aucune erreur JVM n’a surgi.</p><p>Nous avons ainsi pu effectuer avec succès les tests de charge avec 1 000 utilisateurs simultanés, avec même des pics jusqu’à 3 000.</p><h3>Références</h3><ul> <li>Base Logic : “<a href="https://www.baselogic.com/2011/11/23/solved-java-net-bindexception-address-use-connect-issue-windows/">Solved ‘java.net.BindException: Address already in use: connect’ issue on Windows.</a>”</li> <li>OctoPerf : “<a href="https://octoperf.com/blog/2017/10/17/solve-jmeter-out-of-memory-issues/">JMeter out of memory: 12 actionable fixes.</a>”</li></ul>
<h2>Pour commencer, un courriel d’invitation</h2><p>Peu de temps après avoir soumis avec succès votre CV et votre lettre de motivation (voyez notre <a href="https://www.spiria.com/fr/blogue/environnement-de-travail/la-recette-spiria-pour-un-cv-reussi/">recette pour un CV réussi</a>), vous êtes censé recevoir une confirmation automatique de notre part accusant bonne réception de votre candidature. Ensuite, dans un délai de 2 à 3 jours ouvrables, notre équipe de recrutement étudiera votre CV, et si vos compétences coïncident avec nos besoins actuels, nous vous enverrons un courriel d’invitation pour un appel téléphonique. Nous ne vous appellerons jamais sans votre consentement. Surveillez aussi votre dossier de courrier indésirable, car il y a des risques que notre message y atterrisse.</p><h2>Ensuite, vous choisissez l’heure et le jour de notre appel</h2><p>Après avoir reçu notre invitation à passer un appel téléphonique, assurez-vous de vérifier l’offre d’emploi à laquelle vous avez postulé et le CV que vous avez envoyé, cela nous aidera à parler dès le départ des mêmes choses. Vous pouvez aussi consulter le <a href="https://www.spiria.com/fr/">site web de Spiria</a> pour mieux comprendre l’entreprise. Voyez l’emplacement du bureau et s’il correspond bien à vos attentes. Indiquez-nous le jour et l’heure qui vous conviennent le mieux. En cas de besoin, n’hésitez pas à nous appeler à l’heure du déjeuner, après vos cours, avant ou après votre travail. Notre équipe de recrutement fera de son mieux pour vous satisfaire. Nous ne voulons pas vous causer de désagréments ni de stress. Et, bien sûr, préparez toutes vos questions pour nous.</p><h2>Puis, nous discutons</h2><p>Nos questions d’entretien téléphonique sont simples et directes.</p><p>Nous vous demanderons des détails sur :</p><ul> <li>votre situation actuelle,</li> <li>comment vous avez découvert l’offre d’emploi de Spiria,</li> <li>pourquoi vous aimeriez travailler avec nous,</li> <li>la raison pour laquelle vous cherchez un changement de carrière, si c’est le cas,</li> <li>sur votre expérience et vos compétences,</li> <li>sur votre vie de tous les jours au travail,</li> <li>sur les technologies que vous connaissez le mieux,</li> <li>et sur les langages et les technologies que vous aimeriez apprendre à l’avenir.</li></ul><p>Si nécessaire, nous pouvons être amenés à tester vos compétences linguistiques, et si vous êtes bilingue, nous pouvons passer du français à l’anglais lors de la conversation.</p><p>Nous vous demanderons également quelles sont vos attentes en matière de salaire. N’ayez pas peur de cette question, faites simplement quelques recherches au préalable et donnez-nous la fourchette dans laquelle vous vous sentiriez à l’aise. Spiria a également une grille de salaires complète pour tous ses postes. Pour chaque poste, une fourchette salariale inclut un point de départ, plusieurs points médians et un maximum possible. Cette grille permet de s’assurer que tous les employés de l’entreprise sont payés équitablement en fonction de leurs compétences, de leur progression dans le poste, de leurs collègues, des nouvelles embauches et, bien sûr, du marché canadien.</p><p>À la fin, nous vous demanderons vos disponibilités pour un éventuel entretien en personne. Pensez donc à vérifier à l’avance votre emploi du temps pour les jours à venir. Et bien sûr, nous serons là pour répondre à toutes vos questions. L’entretien téléphonique avec Spiria ne dure pas plus de 25-30 minutes. Son but est de mieux vous connaître et de nous présenter. L’équipe d’acquisition des talents est réellement intéressée par votre embauche potentielle et est là pour représenter vos intérêts auprès des responsables de l’embauche.</p><h2>Enfin, nous prenons une décision</h2><p>En général, vous aurez de nos nouvelles dans un délai d’une semaine. Si vous ne recevez aucune réponse dans ce délai, n’hésitez pas à nous envoyer un courriel de suivi. Si les responsables du recrutement sont intéressés par vous, l’équipe d’acquisition de talents vous contactera pour fixer un rendez-vous en personne ou une réunion Zoom. Vous recevrez également un court test de personnalité de 10 minutes et, si nécessaire pour le poste offert, un test technique qui peut prendre jusqu’à une heure.</p><p>Si vous souhaitez connaître les étapes suivantes du processus d’embauche de Spiria, comment vous préparer à un entretien et quelles sont les questions à attendre de nos gestionnaires recruteurs, restez avec nous, suivez Spiria, et nous vous raconterons tout dans nos prochains articles.</p><h3>Voir aussi :</h3><ul> <li><a href="https://www.spiria.com/fr/blogue/environnement-de-travail/comment-preparer-une-entrevue-gagnante-chez-spiria">Comment préparer une entrevue gagnante chez Spiria</a>, par Amanjot Kaur.</li> <li><a href="https://www.spiria.com/fr/blogue/environnement-de-travail/la-recette-spiria-pour-un-cv-reussi">La recette Spiria pour un CV réussi</a>, par Lidiia Meleshchenko.</li></ul>
<h2>Renseignez-vous sur Spiria</h2><p>Comment Spiria se définit-elle comme entreprise? Quelle est sa mission? Quels types de services offre-t-elle?</p><p>Préparez des questions sur tout élément que vous ne comprenez pas, ou que vous voulez approfondir. Cherchez, sur notre site web, les réponses à des questions comme les suivantes :</p><p>1. Où se trouvent les bureaux de Spiria?</p><p>2. Spiria a-t-elle une présence unique, nationale, internationale?</p><p>3. Quelles qualités Spiria recherche-t-elle chez ses employés?</p><p>Prenez note des éléments qui vous intéressent ou vous motivent tout particulièrement.</p><p>« Pourquoi voulez-vous travailler chez Spiria plutôt qu’ailleurs? » est une question souvent posée en entrevue (à bon entendeur, salut).</p><p>Vous trouverez également de l’information utile sur Spiria ailleurs que sur notre site web. Par exemple, Glassdoor contient des évaluations d’employés et de l’information utile sur le processus d’entrevue.</p><h2>Renseignez-vous sur votre intervieweur</h2><p>Si vous connaissez le nom de votre intervieweur, allez voir son profil LinkedIn. Recherchez des intérêts en commun, qui vous donneront l’occasion d’établir un bon rapport interpersonnel. Vous y trouverez également une indication de son niveau d’expertise et d’expérience dans son rôle actuel chez Spiria.</p><h2>Préparez une réponse aux questions d’entrevue les plus souvent posées</h2><p>Tous les interviewés devraient avoir des réponses bien rodées à un certain nombre de questions typiques d’entrevue : questions sur eux-mêmes, leurs objectifs de carrière, leurs motivations et leur intérêt pour leur rôle futur au sein de l’entreprise.</p><p>Par exemple :</p><p><i>Parlez-nous de vous. </i></p><p><i>Parlez-nous de votre expérience jusqu’à ce jour.</i></p><p><i>Pourquoi voulez-vous travailler chez Spiria?</i></p><p><i>L’emplacement de nos bureaux vous est-il facilement accessible au quotidien?</i></p><p>Nous pourrions aussi vous poser des questions techniques! Préparez-vous à des <b>exercices de codage ou de résolution de problèmes</b> sur tableau blanc.</p><p>Enfin, nous pourrions vous poser des questions sur votre expérience en relation avec la clientèle, par exemple :</p><p><i>Comment traitez-vous un <b>client</b> peu raisonnable ?</i></p><p><i>À votre avis, qu’est-ce qu’un bon service à la <b>clientèle</b>?</i></p><p><i>Que feriez-vous si un <b>client</b> avait un problème que vous ne saviez pas résoudre?</i></p><p>Pour répondre à ces questions, nous vous recommandons d’employer la méthode <b>STAR</b> :</p><p><b>Situation</b> : Quelle était la situation?</p><p><b>Tâche</b> : Quelles étaient ses tâches, responsabilités et rôle?</p><p><b>Action</b> : Quelle action a-t-il ou a-elle prise?</p><p><b>Résultat</b> : Quel était le résultat?</p><h2>Comment préparer une entrevue Zoom</h2><p>Les entrevues par vidéoconférence sont de plus en plus usitées.Grâce aux améliorations de la technologie, la plupart des gens peuvent se faire interviewer par Skype, Zoom, ou Google Hangouts sans aucun problème. De plus, une entrevue vidéo vous donne l’aspect visuel que n’autorise pas le téléphone – et ce, sans avoir à s’absenter du travail, ou à voyager à l’autre bout du pays pour se rencontrer en personne! Spiria utilise normalement la plateforme Zoom.</p><p>Voici comment vous préparer :</p><ul> <li>Choisissez un lieu qui vous permet de maîtriser votre environnement.</li> <li>Profitez de la lumière du jour en vous installant près d’une fenêtre.</li> <li>Assurez-vous que la camera se trouve au niveau des yeux.</li> <li>Ayez sous la main un exemplaire de votre CV, un bloc-notes et un stylo, et un verre d’eau.</li> <li>Habillez-vous en tenue de travail, de la tête aux pieds.</li> <li>Testez votre audio et connexion internet à l’avance.</li> <li>Assurez-vous que votre arrière-plan est neutre, sans distractions.</li> <li>Assurez-vous que la tête et les épaules sont visibles.</li> <li>Les écouteurs avec micro intégré évitent l’écho.</li> <li>Souriez et hochez de la tête pour indiquer que vous écoutez bien.</li></ul><h2>La veille de l’entrevue</h2><p>La veille de l’entrevue au plus tard, demandez à votre contact chez Spiria où stationner et où l’attendre dans l’immeuble.</p><p>Si vous vous interrogez sur le code vestimentaire chez Spiria, posez-nous la question! Règle générale, mieux vaut en faire trop que pas assez; mais il est encore mieux de demander, plutôt que de deviner. Préparez votre ensemble la veille et profitez-en pour le repasser, au besoin, afin de vous éviter du stress le lendemain.</p><p>À apporter absolument à l’entrevue : plusieurs exemplaires de votre CV, portfolio, plusieurs cartes d’affaires (si vous en avez), bloc-notes et stylo, et liste de références, au cas où. Bref, tout ce qui peut appuyer votre expertise et soutenir ce que vous avancez.</p><h2>Le jour de l’entrevue</h2><ul> <li>Donnez-vous amplement de temps pour vous préparer, afin d’éviter la panique de dernière minute. Donnez-vous également 15 ou 30 minutes de jeu pour votre déplacement, en cas d’embouteillages.</li> <li>Faites ce qui vous détend le mieux, que ce soit 15 minutes de yoga ou prendre le temps de siroter votre café.</li> <li>Mangez un copieux déjeuner, ça aiguise les neurones!</li> <li>Récitez des affirmations positives, et dites-vous que vous êtes à la hauteur. La confiance en soi compte pour beaucoup en entrevue.</li></ul><h2>Après l’entrevue</h2><p>Communiquez avec nous pour nous dire comment vous avez trouvé votre expérience tout au long du processus. Nous voulons que l’expérience de nos candidats soit la meilleure! Nous recherchons toujours des moyens de nous améliorer.</p><p>Vous êtes maintenant fin prêt à épater votre intervieweur avec vos connaissances du poste et de l’entreprise.</p><p>Bonne chance! ☺</p>
<p>Après tout, il représente votre occasion de mettre le lecteur en appétit, ce qui peut être déterminant pour l’obtention d’un poste. C’est pourquoi votre CV doit jouer le rôle d’entrée avant le plat de résistance (vous). En cette conjoncture de pandémie, alors que nombre d’entre vous ont perdu leur emploi, ont été mis à pied, ou se retrouvent dans des circonstances pour lesquelles vous n’étiez pas préparé, l’équipe d’acquisition de talent de Spiria veut vous aider à mitonner votre CV pour qu’il délecte notre équipe de recrutement.</p><p>Ci-dessous, vous trouverez notre recette pour un CV de professionnel des TI à point.</p><p>1. <b>Soyez bref et concis. </b>Idéalement, votre CV devrait faire 1 ou 2 pages, ou bien une page par décennie d’expérience. Dans ce monde compétitif, nous recevons des dizaines de CV chaque semaine. Le vôtre devrait nous mettre en appétit dès le premier coup d’œil.</p><p>2. <b>Vous êtes bilingue ? Dites-le tout de suite</b>. Nous avons des clients de langue française et anglaise et, souvent, ils recherchent des spécialistes bilingues.</p><p>3. <b>Où êtes-vous ? </b>Indiquez votre ville de résidence, et si vous pouvez et voulez travailler à distance. En cette conjoncture de COVID-19, un nombre croissant d’entreprises font travailler leurs employés à distance.</p><p>4. <b>Qui êtes-vous ? </b>Juste après votre nom et vos coordonnées, insérez une ou deux phrases qui résument qui vous êtes et quelle est votre arme secrète. Indiquez aussi vos deux-trois technologies de prédilection. Par exemple : « Développeur back-end principal, spécialisé en Python, 9 ans d’expérience » ; ou bien, « Développeur full stack intermédiaire, 5 ans d’expérience avec JavaScript, C#, .Net ».</p><p>5. <b>Les informations personnelles sont personnelles.</b> Nous n’avons pas besoin de savoir votre date de naissance, état civil, nombre d’enfants, sexe, religion, race, couleur, ou nationalité ; même votre photo est de trop.</p><p>6. <b>Antécédents professionnels</b>. Pour chacun de vos employeurs, indiquez le nom de l’entreprise, le lieu, votre rôle et dates d’emploi. Résumez chacune de ces expériences en 3 ou 4 points.</p><p>7. <b>Technologies.</b> N’indiquez que les technologies avec lesquelles vous avez de l’expérience, et êtes à l’aise de travailler. N’incluez pas toutes celles dont vous avez entendu parler en classe. Vous pouvez aussi omettre les technologies de base qui vont sans dire, par exemple HTML pour les développeurs Web. ;)</p><p>8. <b>Vous avez de l’expérience en relation avec la clientèle</b> ? Hourrah ! Spiria est une entreprise de développement sur mesure, de sorte que ses employés ont souvent l’occasion d’interagir avec ses clients. Un atout à inclure absolument dans votre CV !</p><p>9. <b>Expliquez les trous dans votre parcours.</b> Par exemple, vous avez obtenu votre diplôme dès 2010, mais votre premier emploi ne débute qu’en 2015 ? Ne laissez aucune place à l’imagination. Expliquez plutôt ce que vous faisiez, par exemple : vous travailliez à la pige, vous lanciez votre propre entreprise, vous avez sillonné le monde ou avez travaillé comme vendeur en magasin (n’oubliez pas que nous valorisons toute expérience en relation avec la clientèle !).</p><p>10. <b>Études</b>. Incluez vos distinctions éducatives, votre participation à des <i>hackathons</i> et autres événements de type « sprint ». Mais de grâce, épargnez-nous vos relevés de notes ; vos titres suffiront.</p><p>11. <b>Réalisations personnelles.</b> Si vous avez une réalisation digne de mention à votre actif, ou si vous faites du bénévolat, nous voulons le savoir. Nous nous intéressons à votre personnalité et à vos valeurs.</p><p>12. <b>“Références fournies sur demande.”</b> Inutile et superflu. Cela n’ajoute rien à votre CV, et distrait de ce qui précède. Ne vous inquiétez pas, nous n’hésiterons pas à vous demander vos références si besoin est.</p><p>13. <b>PDF plutôt que Word</b>. Ne nous envoyez pas votre CV sous forme de document Word. En effet, toute votre soigneuse mise en page sautera dès que nous l’ouvrirons sur notre plateforme.</p><p>Que se passe-t-il après cette mise en bouche ? Eh bien, si nous avons goûté votre CV, nous vous enverrons un courriel pour vous inviter à une entrevue téléphonique. Ainsi, une fois <a href="https://www.spiria.com/fr/carriere/">votre CV transmis</a>, vérifiez vos courriels régulièrement, y compris votre boîte de pourriels ; puisque nous sommes un expéditeur inconnu, nos courriels pourraient ne pas être reconnus. Pour en savoir davantage sur ce qui suivra, suivez le blogue Spiria. Nous vous en dirons davantage dans le prochain article.</p><p>Bonne chance, et au plaisir de faire connaissance ! :)</p>
<p>Tous ces systèmes ont d’abord dû être imaginés et développés, puis il faut les maintenir tout au long de leur vie utile. Tous les jours, nous les utilisons quotidiennement sans même plus y penser. Mais savez-vous en quoi consiste le travail quotidien des programmeurs qui ont développé tous ces outils dont on ne saurait plus se passer ?</p><p>En tant que développeur spécialisé en applications web, je vous propose un aperçu des tâches et défis que je rencontre typiquement chaque jour. Bien sûr, chaque projet de <a href="https://www.spiria.com/fr/services/developpement-axe-performance/developpement-logiciel-sur-mesure/">développement logiciel</a> est unique et chaque équipe a sa façon de faire, mais cette vue d’ensemble est sans doute assez représentative de l’approche générale pour tout type de développement logiciel.</p><p>Notons d’abord que malgré le terme courant de “développement” qui recouvre tout ce qui participe à la naissance d’un logiciel, le développement logiciel n’est pas l’affaire uniquement des développeurs. En fait, il fait appel à différents professionnels et à de nombreuses compétences autres que la seule écriture de code.</p><h2>Le cycle de développement logiciel</h2><p>Dans le cycle de développement logiciel moderne dit “Agile”, une application est continuellement en développement :</p><p><img src="https://cdn.prod.website-files.com/67c06f07cfba9b0adb43e16c/68470c892ff1fdd926a42869_cycle_developpement.png" style="width: 50%; border: none;" alt="Development cycle." title="Development cycle."></p><ol> <li><b>Analyse</b> — L’analyse des besoins : nouvelles fonctionnalités, bogues à corriger, etc.</li> <li><b>Conception</b> — Élaboration des maquettes, de l’architecture logicielle requise, etc.</li> <li><b>Implémentation</b> — Développement (“codage”).</li> <li><b>Tests</b> — Assurance qualité (AQ) pour valider le bon bon fonctionnement et trouver les bogues manqués lors du développement.</li> <li><b>Déploiement</b> — Mise en production.</li></ol><p>Les meilleures pratiques veulent que le développement passe par toutes les étapes de ce cycle à intervalles réguliers, de manière à avoir des mises à jour fréquentes en production. En général, un cycle typique, appelé “sprint”, dure d’une à quatre semaines selon la nature du projet, mais dans les cas d’urgences majeures (par exemple, un “hotfix”), un cycle complet peut être accompli en aussi peu qu’une seule journée.</p><p>Il est à noter que tous les cycles ne produisent pas nécessairement de changements visibles pour les utilisateurs finaux de l’application. Un cycle peut en effet contenir uniquement de l’analyse ou des changements d’architecture en arrière plan, en préparation de fonctionnalités futures ou pour stabiliser la plateforme. De plus, une fonctionnalité peut être divisée en plusieurs petites tâches moins complexes afin de mieux répartir le travail entre les différents développeurs.</p><p>À l’occasion et selon la répartition des équipes au sein d’une entreprise, le développeur est amené à devoir réaliser des tâches relevant de chaque étape du cycle. Un bon développeur doit donc être polyvalent et pouvoir s’adapter rapidement lorsque nécessaire.</p><p>Ainsi, même si on a la plupart du temps une équipe d’<a href="https://www.spiria.com/fr/services/developpement-axe-performance/assurance-qualite-test-automatises/">assurance qualité</a> (AQ) dédiée pour tester l’application et trouver les bogues avant la mise en production des nouvelles fonctionnalités, un développeur effectue tout de même certains tests lors de l’implémentation afin de corriger une partie des bogues en amont.</p><p>Mentionnons que les phases du cycle de développement ne sont pas nécessairement séquentielles. Par exemple, les phases d’analyse et de conception du prochain cycle peuvent être accomplies en parallèle durant le cycle en cours.</p><p>La phase d’analyse s’accompagne généralement des tâches suivantes :</p><ol> <li>Analyse des besoins : identification et priorisation des bogues et des nouvelles fonctionnalités pour le prochain cycle.</li> <li>Documentation des besoins techniques à implémenter pour répondre aux besoins identifiés. Division des fonctionnalités complexes en sous-tâches plus simples.</li> <li>Estimation de la complexité et du temps requis pour chacune des tâches déterminées.</li> <li>Planification et validation du contenu du prochain cycle de développement.</li></ol><p>La phase d’analyse est amorcée en étroite collaboration avec le client (représenté par le “Product Owner”), et les équipes de développement et d’assurance qualité sont généralement impliquées lors des phases finales d’estimation et de planification.</p><h2>Le travail du codeur</h2><p>Pour ce qui est du développement à proprement parler, un développeur réalise généralement les travaux suivants pour chaque tâche :</p><ol> <li>Implémentation de la tâche dans le code (ajout de la fonctionnalité dans le code ou ajustement du code existant pour corriger un bogue) : <ul> <li>Recherche et documentation (utiliser une librairie logicielle externe, trouver une solution existante pour résoudre un bogue, explorer des alternatives technologiques, etc.).</li> <li>Ajout de <a href="https://fr.wikipedia.org/wiki/Test_unitaire">tests unitaires</a> ou même de tests fonctionnels et/ou de tests d’intégration selon le projet.</li> <li>Test de la fonctionnalité dans un environnement de développement dédié.</li> </ul> </li> <li>Ouverture de la <a href="https://fr.wikipedia.org/wiki/Revue_de_code">revue de code</a> aux autres développeurs : <ul> <li>Ajustements et corrections suite aux retours de la revue de code (le cas échéant).</li> </ul> </li> <li>Déploiement de la fonctionnalité dans l’environnement d’AQ dédié : <ul> <li>Ajustements et corrections des bogues trouvés par l’équipe d’assurance qualité (s’il y a lieu).</li> </ul> </li></ol><p>Une fois toutes les tâches complétées et mises ensemble, on peut alors faire le déploiement du “sprint” achevé en production.</p><p>Notons finalement que toutes les étapes du cycle de développement ne sont pas indépendantes, mais bien interreliées.</p><p>Par exemple, après l’implémentation d’une fonctionnalité, si des bogues sont détectés par l’équipe d’assurance qualité, le développeur responsable de la tâche va les corriger en retournant à l’étape d’implémentation.</p><p>Ou bien encore, si un bogue est détecté en production durant un cycle, il est alors analysé et priorisé. Selon sa gravité, il sera soit corrigé en “hotfix”, soit inséré au cycle actuel (possiblement à la place d’une autre fonctionnalité) en vue du prochain déploiement, soit reporté à un cycle ultérieur.</p><h2>Collaborer et communiquer</h2><p>La collaboration et la communication entre les différentes équipes sont l’une des principales clés pour le développement efficace d’une application de qualité. Un développeur est donc en constante communication avec les autres développeurs et membres de l’équipe selon l’état d’avancement du cycle.</p><p>Idéalement, les communications se font directement en personne, mais selon la taille des entreprises et l’emplacement des clients, il peut arriver que les équipes soient réparties entre plusieurs villes, pays ou même continents. Il arrive donc que des réunions ou discussions soient réalisées de manière virtuelle, mais elles n’en sont pas moins importantes pour autant. Notons aussi que de nos jours, plusieurs entreprises offrent également des possibilités de télétravail à leurs employés, auquel cas la qualité et la régularité des communications au sein de l’équipe sont d’autant plus essentielles.</p><p>Pour un développeur, une journée type est donc par exemple accompagnée des tâches suivantes (pas nécessairement dans cet ordre) :</p><ul> <li>Synchronisation avec le reste de l’équipe (par exemple, une rencontre “scrum”).</li> <li>Revue de code des fonctionnalités terminées par les autres développeurs.</li> <li>Ajustement des fonctionnalités terminées à la suite de la revue de code des autres développeurs ou des retours de l’équipe AQ.</li> <li>Développement de nouvelles fonctionnalités (implémentation + test).</li> <li>Participation à l’estimation des prochaines fonctionnalités (généralement une seule fois par “sprint” ou cycle selon les besoins).</li></ul><p>Bien sûr, tout ceci est très variable, selon le projet et selon le rôle de chaque développeur au sein de l’équipe.</p><p>Pour conclure, le développement logiciel reste un processus complexe et en constante effervescence. Outre les développeurs, il fait intervenir plusieurs acteurs clés tous aussi importants. Et la prochaine fois que vous utiliserez votre application préférée, peut-être aurez-vous l’occasion de penser à la somme de travail et les efforts soutenus des équipes de développement qui l’ont rendue possible.</p>
Stratégie
5 min de lecture
Comment planifier mon projet de développement logiciel pour avoir le retour sur investissement le plus rapide ?
<p>Une chose importante à considérer avant de se lancer est : <i>« que cherchez-vous vraiment à atteindre ? »</i>. Il y a une distinction entre une demande de planification et le besoin d’être rassuré — deux préoccupations tout à fait valables.</p><p>Examinons de plus près la planification du retour sur investissement le plus rapide.</p><h2>En préalable</h2><p>Les gens aiment obtenir une question en réponse à leur question (en fait, non, ce n’est pas le cas). Cependant, la première étape est de comprendre : <b>pourquoi le plus rapide</b> ?</p><p>Voici trois questions qui sont essentielles pour bien comprendre les objectifs et les préoccupations d’un client au-delà des tout premiers échanges et des trois lettres magiques (R-O-I) :</p><ul> <li>Quel est le délai acceptable pour être dans le « plus rapide » ?</li> <li>Que sacrifiez-vous pour obtenir un retour sur investissement rapide au lieu de reporter sur le moyen ou long terme ?</li> <li>Qui a décidé de l’objectif d’un retour sur investissement rapide, et cette décision remporte-t-elle l’adhésion au sein de l’entreprise ?</li></ul><p>La dernière question sert à comprendre si cet objectif est quelque chose qui aidera l’entreprise ou bien la personne qui la représente. Bien sûr, nous préférerons être dans le premier cas, mais le second est parfois un passage obligé pour faire approuver le projet.</p><h2>La seule chose qui soit constante, c’est le changement</h2><p>Bien qu’il soit louable de prévoir un retour sur investissement rapide en début de projet, nous devons déterminer quels sont les <b>facteurs de changement</b> susceptibles d’affecter à la fois la définition des termes « le plus rapide » et « retour sur investissement ». Il vaut vraiment la peine de vérifier ces facteurs auprès du client, pour voir si ces définitions sont invariables ou évolutives. Ces facteurs peuvent inclure :</p><ul> <li>Le marché</li> <li>La concurrence</li> <li>La vision de l’entreprise</li> <li>La pression en interne, les promoteurs du projet</li></ul><h2>Qualifier et quantifier</h2><p>En matière de retour sur investissement, vous devez vous éloigner du terme et de ses implications et mettre votre client potentiel au défi de définir ce qu’il signifie réellement. Comment mesurer le « retour sur investissement le plus rapide » et comment déterminer si l’objectif a été atteint ?</p><p>Tout d’abord, demandez à votre client de prévoir le <b>coût de l’inaction</b> dans les délais impartis. En d’autres termes, si le client n’allait pas de l’avant avec le projet de développement du logiciel, combien cela lui coûterait-il ? Cela peut être aussi direct que la perte de revenus, ou indirect comme l’effet sur la motivation et la performance des employés. Par exemple, les employés peuvent passer une partie importante de leur journée à effectuer des tâches qui ne tirent pas parti des compétences pour lesquelles ils ont été engagés. Cela inclut toute saisie manuelle de données qui prend du temps et qui est le préalable nécessaire pour effectuer l’analyse des données pour laquelle ils ont été engagés. Cela peut entraîner de la frustration, une baisse des performances et de la motivation, ainsi qu’une diminution du taux de rétention des employés.</p><p>Ensuite, concentrez-vous sur la dernière lettre de « ROI » : l’investissement. L’investissement peut être élevé au départ, puis diminuer progressivement au fil du temps, ou il peut être assez constant. Le client cherche-t-il à <b>récupérer son investissemen</b>t très rapidement après la mise en service, ou envisage-t-il un retour progressif par phase ou par étape ? Ces informations permettront de fixer des jalons précis pour la mesure du ROI.</p><p>Enfin, nous parlons souvent de <b>la <em>valeur</em> dans le développement logiciel</b>. Ce terme est souvent utilisé, mais il peut avoir une signification différente selon les personnes et leur fonction. L’idée qu’un développeur de logiciels se fait de la valeur d’une fonctionnalité donnée peut différer de celle que s’en font les principaux intéressés chez le client, surtout s’ils ne partagent pas les mêmes critères. Une échelle commune pour déterminer la valeur permettra à chaque membre de l’équipe de fournir la valeur nécessaire pour atteindre un bon retour sur investissement.</p><h2>Laissez les experts être des experts</h2><p>Souvent, les clients décrivent la solution qu’ils pensent pouvoir apporter au problème, au lieu de décrire le problème lui-même. Cela peut avoir l’effet négatif d’orienter votre expert vers une voie préconçue. En décrivant leur problème de manière simple et succincte, les clients ont l’avantage de laisser l’expert envisager une solution de son propre point de vue.</p><p>Il en va de même pour notre question de « retour sur investissement le plus rapide ». Nous avons parlé plus tôt de la définition et de la quantification du ROI — ce sont les lignes directrices qui encadrent l’objectif au niveau macro. Si l’objectif est correctement compris et communiqué, et s’il y a adhésion, les experts peuvent traduire l’objectif macro à un niveau micro.</p><h2>Comment planifier</h2><p>Pour faire simple, voici quelques points importants à prendre en compte lors de l’élaboration d’un plan pour un retour sur investissement rapide :</p><ol> <li>S’accorder sur la définition de « retour sur investissement le plus rapide ».</li> <li>Comprendre les raisons qui se cachent derrière.</li> <li>Fixer des objectifs quantifiables.</li> <li>Suivre et mesurer.</li> <li>Ajuster en fonction de l’évolution des facteurs.</li> <li>Communiquer.</li></ol><p>Pour parler sans détour, cela se résume à <i>« être sur la même longueur d’onde, tous ensemble »</i>. Plus facile à dire qu’à faire, car les affaires et la technologie ne font pas toujours bon ménage. Une bonne équipe — le client et son entreprise de développement — partage son expertise, maximise les forces de l’autre partenaire et minimise les faiblesses. Le « retour sur investissement » peut avoir peu de sens pour un développeur de logiciels qui, en revanche, se soucie de la valeur ; sa définition de la valeur se traduit-elle par un « retour sur investissement », et vice-versa ? Peut-être que oui, ou peut-être aurez-vous besoin de faire un travail de conciliation et de représentation des différentes perspectives pour atteindre votre objectif commun.</p>
<h2>Si vous n’avez pas le temps de tout lire :</h2><p><b>Laissez votre ego à la porte</b><br>Votre ego ne fera que vous ralentir sur le chemin de votre progression en tant que programmeur. Laissez-le derrière vous.</p><p><b>Le travail en équipe est essentiel</b><br>Vous n’irez pas loin sans l’équipe. Mettez de côté vos propres intérêts et regardez les choses dans leur globalité.</p><p><b>Comprenez que chacun a des attentes différentes</b><br>Tout le monde ne travaille pas et ne pense pas comme vous. Cela ne veut pas dire qu’ils ont tort, mais simplement qu’ils ont des attentes différentes ; et il vous faut l’accepter.</p><p><b>Sortez de votre zone de confort</b><br>Évitez de vous confiner dans votre petit confort et allez explorer les vastes mondes de la technologie. Apprenez des choses sans rapport direct avec votre travail ; vous ne savez jamais quand cela vous sera utile.</p><p><b>N’allez pas jusqu’à l’épuisement</b><br>Ce n’est pas un sprint, mais un marathon. Prenez du temps pour vous et profitez de la vie en dehors du travail.</p><h2>Laissez votre ego à la porte</h2><p>La somme de connaissances requise pour mener un projet à bien est tout simplement énorme. Vous devez posséder des compétences appropriées en matière d'UX/UI, de back-end, de front-end, de base de données, de DevOps, d'architecture, de sécurité, etc. Faut-il vous immerger dans Pluralsight et essayer de tout apprendre de fond en comble ? Si vous voulez passer des années à ne rien faire d’autre, pourquoi pas… Autrement, essayez donc d’apprendre de vos pairs qui ont passé de nombreuses années à perfectionner leur savoir-faire.</p><p>Si vous avez un gros ego, non seulement vous n’allez pas écouter et apprendre, mais vos coéquipiers ne seront de toute façon pas enclins à vous transmettre des connaissances. Vous considérerez chaque correctif ou suggestion d’amélioration comme un affront personnel. Vous finirez par gaspiller beaucoup d’énergie à essayer de protéger quelque chose de peu d’utilité : votre ego.</p><p>Je n’ai pas échappé à ce piège. Je pensais tout savoir, jusqu’à ce que je réalise que… ce n’était pas le cas. Mon savoir n’était qu’une goutte d’eau dans l’océan. J’ai réalisé à quel point mon ego était grand et stupide lorsque j’ai commencé à travailler avec des gens qui étaient bien plus savants que moi. Lâcher son ego est plus facile à dire qu’à faire, et cela ne se réalise pas du jour au lendemain, mais les bénéfices en valent la peine. Je vous recommande l’ouvrage <i>Ego is the Enemy</i> de Ryan Holiday. Cet excellent livre est facile à lire, et il vous explique les raisons pour lesquelles votre ego ne vous est d’aucune utilité et pourquoi vous devriez vous en séparer.</p><h2>Le travail en équipe est essentiel</h2><p>Derrière tout excellent logiciel, il y a une équipe formidable qui l’a conçu. Je n’ai réalisé l’importance du travail d’équipe que lorsque j’ai été propulsé dans un environnement concret, avec un vrai projet et une vraie équipe. C’est une dynamique différente de celle à laquelle j’étais habitué, quand mon propre intérêt passait avant celui de l’équipe.</p><p>Communiquez souvent, posez des questions lorsque vous n’êtes pas sûr de quelque chose, signalez les problèmes dès qu’ils surviennent. Tout le monde doit faire sa part dans l’intérêt de la coordination du projet. Ne restez pas sans communiquer pendant des jours. Vos décisions doivent être prises dans l’intérêt de l’équipe et non dans votre propre intérêt, et vous devez travailler avec l’équipe et non contre elle. N’oubliez pas que personne n’apprécie un programmeur « héros » qui pense pouvoir faire le travail de tout le monde.</p><p>Je suis plutôt un loup solitaire, un penseur avant un orateur, un introverti. Pour moi, communiquer et être là pour l’équipe n’avait jamais été un problème parce que je n’en avais pas le besoin. Dans mes emplois précédents et à l’école, je pouvais simplement brancher mes écouteurs et travailler comme je voulais, au rythme que je voulais, avec les outils que je voulais. Mais j’ai fini par devoir adapter mon comportement et mes habitudes, car aussi amusante que soit la liberté totale, il faut être plus d’un pour réaliser quelque chose d’important et de significatif. Seul, on va plus vite, ensemble, on va plus loin.</p><h2>Comprenez que chacun a des attentes différentes</h2><p>Vous travaillerez avec beaucoup de gens tout au long de votre carrière. Comme chaque personne est unique, votre relation de travail avec chacune d’entre elles doit l’être également. Cela signifie que vous devez essayer de comprendre les attentes et besoins de chaque personne afin de mieux comprendre pourquoi elle pense et agit comme elle le fait.</p><p>Cela ne signifie pas que vous devez avoir un doctorat en psychologie. Lisez plutôt les <i>styles interpersonnels</i> selon Larry Wilson. Cela donne un bon aperçu du concept de « personnalités fondamentales » en termes simples. En bref, vous avez :</p><ul> <li>L’analytique : axé sur les données, il a besoin de clarté et de réponses objectives.</li> <li>Le fonceur : concentré sur un objectif, il a besoin d’avancer rapidement et efficacement.</li> <li>L’expressif : animé par le sentiment, il a besoin de liberté et de tâches stimulantes.</li> <li>L’aimable : orienté vers la socialibilité, il a besoin d’interactions et d’une atmosphère positive.</li></ul><p>Le but n’est pas d’essayer de plaire à tout le monde tout le temps, mais plutôt de faire preuve d’empathie lorsque quelqu’un ne se sent pas motivé par son travail. C’est un excellent outil pour vous aider à mieux comprendre vos coéquipiers et à adapter en conséquence votre relation de travail avec eux.</p><p>Pendant longtemps, je ne comprenais pas les gens qui avaient constamment besoin de réponses concernant leur travail. Je me disais : « Si vous ne savez pas, prenez une décision et faites avec. Cela ne doit pas être si difficile que ça ». J’ai toujours eu l’impression qu’ils avaient besoin d’être nourris à la cuillère, alors qu’en fait, ils avaient juste besoin de clarté. Ce sont des analytiques, et c’est tout simplement dans leur nature. Je travaillais plus vite qu’eux, mais mon travail devait être corrigé, tandis que le leur était approuvé à la révision. J’avais besoin de rapidité, alors qu’ils avaient besoin de clarté. Il n’y a pas de bien ou de mal, juste des besoins différents.</p><h2>Sortez de votre zone de confort</h2><p>N’ayez pas peur d’essayer quelque chose de complètement nouveau. Il y a tant de domaines, de langages, de frameworks, de méthodes de travail, d’architectures, de paradigmes différents, et la liste est longue. Même si cela n’est pas directement lié à votre métier, vous devriez explorer. Il y a de fortes chances pour que ce que vous avez appris en sortant de votre domaine profite à votre travail d’une manière ou d’une autre.</p><p>Prenez un peu de temps chaque semaine pour aller explorer, même si ce n’est que quelques heures. Il y a quelque chose d’euphorisant à apprendre par simple curiosité. Vous avez plus de temps pour analyser, questionner et creuser que quand vous devez apprendre les mêmes choses dans la précipitation pour un projet.</p><p>Aucun savoir n’est jamais gaspillé, et vous devriez profiter pleinement de votre jeunesse pour faire bon usage de tout le temps qu’il vous reste à l’horloge de la vie. Le temps est votre plus grand atout. Faites-en bon usage.</p><h2>N’allez pas jusqu’à l’épuisement</h2><p>Il est tout à fait naturel, au début, de vouloir faire ses preuves en travaillant comme un fou. Vous êtes jeune, vous commencez votre carrière et vous voulez que tout le monde sache que vous ne serez pas un poids mort. Mais combien de temps pouvez-vous tenir le rythme avant de tomber en panne de carburant ? Quelques mois si vous êtes chanceux ? Et vous ressentirez les mêmes choses qu’après une chute de glycémie : manque de motivation et de concentration.</p><p>Si vous recherchez le respect, ce n’est pas la façon de le gagner. Les travailleurs plus âgés ont du vécu et savent que votre folle accumulation de “story points” ne durera pas. Ne gaspillez pas votre énergie en début de course ; gardez-la pour quand vous en aurez vraiment besoin. Il y aura des moments où vous aurez besoin de doubler la mise, et ce sera un cauchemar si vous avez consommé tout votre carburant.</p><p>Je suis coupable d’avoir cédé à ce comportement. Je pensais que plus je publierais de “user stories”, plus je deviendrais utile. J’ai essayé d’être le héros que personne n’avait demandé. Ce fut de courte durée. Au début, je me sentais bien. J’ai reçu quelques tapes dans le dos, quelques mentions dans des réunions. Et puis les mois ont passé. Ma motivation s’est effondrée. J’avais peu de patience et moins de concentration : une combinaison mortelle. Tout ce que je voulais alors, c’était juste m’arrêter un moment, mais ce n’était pas possible. Je devais prendre de nombreuses pauses au cours de la journée pour rester lucide, garder mon esprit clair.</p><p>Morale de l’histoire : prenez du temps pour vous, faites de l’exercice, reprenez les passe-temps que vous avez mis de côté parce que vous étiez trop occupé par votre emploi du temps de fou. Voyagez et lisez. Être heureux en dehors du travail est la meilleure façon d’être heureux au travail.</p>
<p>La question que nous allons explorer est la suivante : <i><b>quelle est la vitesse d’accès maximale à un dictionnaire ?</b></i></p><p>Oui, c’est un peu bizarre comme code golf, mais soyez patient. Vous verrez, on va arriver quelque part d’intéressant. Pas nécessairement l’endroit où vous aviez prévu d’aller… mais nous y arriverons ensemble, en équipe ! Non, je plaisante. Pas besoin de travailler en équipe. Je ferai tout le travail et vous pourrez vous asseoir et me regarder.</p><p>L’ensemble du code dont nous allons parler est <a href="https://github.com/pierrebai/FastDict">disponible sur GitHub</a>.</p><p>(Notez qu’il y a plusieurs branches, “master” pour le point de départ, “fast-dict” pour le résultat final).</p><h2>Les règles</h2><p>Comme vous le verrez à la fin, les lois de l’univers seront bafouées. Mais cela ne veut pas dire que nous ne pouvons pas inventer nos propres lois. C’est pourquoi je vais établir des règles, la forme de base de ce à quoi le dictionnaire doit ressembler et la fonctionnalité qu’il fournira.</p><p>Je commencerai par donner une description générale de la fonctionnalité, puis je fournirai une brève déclaration en C++ de l’interface. Pour une vue complète de l’API C++, reportez-vous à la branche “master” sur GitHub. Passons maintenant à la description !</p><h3>Description de haut niveau</h3><table style="width:100%"> <tbody> <tr> <th>Classe C++</th> <th>But</th> <th>API</th> </tr> <tr> <td style="vertical-align: top;"><code>element</code></td> <td style="vertical-align: top;">L’élément du dictionnaire. Contient une valeur de n’importe quel type. Par exemple : un entier, un double, du texte ou un autre dictionnaire.</td> <td style="vertical-align: top;">Définir des valeurs, lire la valeur, réinitialiser l’élément, comparer des éléments, etc.</td> </tr> <tr> <td style="vertical-align: top;"><code>name</code></td> <td style="vertical-align: top;">Une étiquette utilisé pour accéder aux éléments du dictionnaire.</td> <td style="vertical-align: top;">Construire de nouveaux noms, comparer les noms.</td> </tr> <tr> <td style="vertical-align: top;"><code>dict</code></td> <td style="vertical-align: top;">Le dictionnaire, indexé par noms, contenant des éléments.</td> <td style="vertical-align: top;">Construction, ajout, suppression et accès.</td> </tr> </tbody></table><h3>Code C++</h3><p>Je ne donnerai qu’une courte description. Vous pouvez consulter le code sur GitHub pour les détails. Le point principal qui nous intéresse est l’accès au dictionnaire, c’est donc tout ce que je vais montrer :</p><pre><code> // Element retrieval. element & operator [](const name &); const element & operator [](const name &) const;</code></pre><p>Très simple, très standard. La fonction d’accès reçoit un <code>nom</code> et renvoie un <code>élément</code>. Pour aider à comprendre ce que sont les noms, voyons comment ils sont créés :</p><pre><code> // You need to derive from name to create a concrete name. // All instances of a given concrete name are equal. struct name { // Invalid-name, default constructor. name() : _name(nullptr) {} protected: // The text passed for the name by its sub-classes must be static // so that each address is unique. name(strptr n) : _name(n) {} };</code></pre><p>Alors que le <code>nom</code> a un constructeur public par défaut, son autre constructeur est protégé. Pourquoi ? Vous verrez la raison profonde plus loin… mais cela signifie donc que toutes les instances doivent provenir de sous-classes ? Oui ! Chaque <code>nom</code> sera une instance d’une sous-classe de <code>nom</code> ! Mais quelle sous-classe ? Eh bien… <b>toutes</b>, bien sûr !</p><p>En fait, si vous regardez dans le repo GitHub, vous verrez que je fournis un en-tête <code>voc.h</code>. Cet en-tête déclare… un vocabulaire de noms. Comme il a été suggéré plus tôt, chaque <code>nom</code> réel est une sous-classe… une sous-classe différente pour chaque <code>nom</code> distinct ! Le fichier se présente comme ceci :</p><pre><code> namespace voc { #define MAKE_NAME(n) struct n ## _n : dak::name { n ## _n() : name(L ## #n) {} }; MAKE_NAME(apple); MAKE_NAME(person); // etc… const apple_n apple; const person_n person; }</code></pre><p>La classe d’<code>éléments</code> elle-même est une classe simple qui peut contenir une valeur de n’importe quel type commun. Elle n’a rien de particulier. Il serait bon que vous réfléchissiez à la vitesse à laquelle vous pourriez réaliser une telle interface de dictionnaire. Vous pouvez prendre comme point de départ la branche “master” de GitHub. S’agira-t-il de N log N ? N ?, log N ? Temps constant ? Plus rapide ? Attendez, plus rapide que le temps constant ? Qu’est-ce que cela signifierait ?</p><h2>Les plis</h2><p>Maintenant que nous avons établi les règles, il est temps de les plier à notre avantage. Bien sûr, comme avec tout bon arnaqueur, les règles ont été soigneusement pensées pour donner l’avantage à la maison.</p><p>Il y a notamment une bonne raison derrière la conception de la classe de <code>noms</code>. Vous voyez, le fait d’avoir différents types pour différents noms nous permet de subvertir le système de types C++ à notre avantage. En particulier… nous pouvons subvertir le mécanisme de surcharge des fonctions !</p><p>Souvenez-vous des fonctions d’accès aux <code>éléments</code> ? Que se passerait-il s’ils étaient surchargés ?</p><pre><code> // Element retrieval. element & operator [](const name &); const element & operator [](const name &) const; // Overload!!! inline element& operator [](const voc::rock_n&) inline const element& operator [](const voc::rock_n&) const</code></pre><p>Cela signifie que nous pouvons retourner l’<code>élément</code> sans avoir à le chercher ! Une tricherie totale ! Mais comment retrouver l’élément si le <code>voc::rock</code> est accessible par la version prenant un <code>nom</code> simple et non un <code>voc::rock</code> ? Comment les éléments du <code>dict</code> pourraient-ils être trouvés lors d’une itération normale ? Facile ! Nous créons des éléments proxy dans la <code>map</code> du dictionnaire, chaque proxy reporte tout son comportement sur la copie à accès direct. En gros, nous ajoutons quelques fonctions à la classe d’éléments pour enregistrer s’il s’agit d’un proxy. Nous ajoutons également une fonction à la classe <code>dict</code> pour enregistrer chaque <code>élément</code> proxy et l’<code>élément</code> d’accès direct auquel il se réfère.</p><pre><code> struct dict { protected: std::map<name element=""> _elements; // Sub-classes call this during construction // to add the permanent proxy elements. void add_permanent_proxy(const name& n, element &); }; struct element { bool is_proxy() const; bool is_permanent() const; };</name></code></pre><p>Le résultat est que nous pouvons accéder aux éléments de notre choix au moment de la compilation ! Il suffit de sous-classer la classe <code>dict</code> et d’ajouter les éléments proxy qui seront accessibles sous les noms de votre choix. La classe résultante agit comme un <code>dict</code>, et peut être utilisée partout où un <code>dict</code> peut se trouver, mais si vous connaissez le véritable type de <code>dict</code> et le véritable nom auquel vous voulez accéder, vous obtenez un accès à la compilation grâce à l’inlining et à la surcharge des fonctions.</p><h2>La torsion</h2><p>Dans le domaine de la folie, nous ne nous satisferions pas de cette médiocre ruse. Cette subversion ne va pas assez loin. Nous voulons plus de vitesse ! Nous avons un accès en temps réel à notre élément, mais nous voulons un accès en temps réel à la <b>valeur</b> contenue dans l’élément. Est-ce même possible ? Mais oui, c’est possible !</p><p>Le tour de passe-passe que nous utiliserons consiste à sous-classer la classe d’<code>éléments</code>, où réside la valeur. Si nous connaissons à l’avance le type de la valeur que nous voulons conserver sous un <code>nom</code>, nous pouvons l’obliger à toujours avoir ce type, à être connu au moment de la compilation. Connaître le type de la valeur que nous voulons conserver sous un <code>nom</code> spécifique n’est pas inhabituel, c’est même typique ! C’est ainsi que nous concevons les classes, les schémas et les bases de données après tout.</p><p>Voici donc un exemple typique de cette sous-classification. (Voir la branche “fast-dict” sur GitHub pour toutes les variations fournies) :</p><pre><code> struct eint64 : element { operator int64&() { return _i; } // etc... };</code></pre><p>Comme on peut le voir, elle peut <code>inliner</code> l’accès à la valeur réelle contenue dans l’<code>élément</code>. Notre sous-classe <code>dict</code> peut maintenant renvoyer un tel <code>eint64</code> dans sa fonction surchargée d’accès à l’<code>élément</code>, et offrir un accès complet à la valeur directe en temps de compilation ! Comme ceci :</p><pre><code> inline eint64& operator [](const voc::rock_n&) { return _rock; } inline const eint64& operator [](const voc::rock_n&) const { return _rock; }</code></pre><p>Pour supporter les sous-classes de l’élément, une fonction supplémentaire est ajoutée à l’<code>élément</code> pour lui faire savoir que le type de <code>valeur</code> est désormais fixe :</p><pre><code> bool is_fixed() const { return _fixed == fixedtype::fixed; }</code></pre><h2>La preuve</h2><p>Mais je ne me contente pas de prétendre qu’il s’agit d’un accès en temps de compilation, je le prouve ! Pas seulement le prouver, mais le comparer à un accès à une structure pure. C’est exact ! Alors que la sous-classe du dictionnaire avec ses fonctions surchargées peut être utilisée comme un <code>dict</code> normal, et que tous ses éléments, y compris les éléments permanents, proxy, typés peuvent être trouvés par recherche normale ou par itération, elle est tout aussi rapide qu’une <b>structure brute</b> ! Tout aussi rapide que ceci :</p><pre><code> struct rock_struct { int64 rock = 42; };</code></pre><p>Dans la branche “fast-dict”, il existe des tests unitaires, et parmi eux deux tests fictifs qui ont été utilisés uniquement pour comparer la génération du code du sous-dict et de la structure. J’ai capturé le code assembleur des deux, et voici le résultat et comme nous l’avons prétendu, chacun est aussi rapide que l’autre !</p><pre><code> d1.rock = rand();call qword ptr [rand] movsxd rcx,eax mov qword ptr [rsp+38h],rcx use_rock(d1);lea rcx,[d1] call dak::use_rock std::wcout << d1.rock;mov rbx,qword ptr [d1] mov rcx,qword ptr [std::wcout] mov rdx,rbx call qword ptr [operator<<] d1.rock += rand();call qword ptr [rand] movsxd rcx,eax add rbx,rcx use_rock(d1);lea rcx,[d1] mov qword ptr [d1],rbx call dak::use_rock std::wcout << d1.rock;mov rdx,qword ptr [d1] mov rcx,qword ptr [std::wcout] call qword ptr [operator<<] use_rock(d1);lea rcx,[d1] call dak::use_rock</code></pre><pre><code> d1[voc::rock] = rand();call qword ptr [rand] movsxd rcx,eax mov qword ptr [rsp+38h],rcx use_rock(d1);lea rcx,[d1] call dak::use_rock std::wcout << d1[voc::rock];lea rdx,[rsp+38h] mov rcx,qword ptr [std::wcout] call dak::operator<< d1[voc::rock] += rand();call qword ptr [rand] add eax,dword ptr [rsp+38h] movsxd rcx,eax mov qword ptr [rsp+38h],rcx use_rock(d1);lea rcx,[d1] call dak::use_rock std::wcout << d1[voc::rock];lea rdx,[rsp+38h] mov rcx,qword ptr [std::wcout] call dak::operator<< use_rock(d1);lea rcx,[d1] call dak::use_rock</code></pre><h2>Conclusion</h2><p>Nous nous sommes mis en route sur le terrain de golf, en explorant l’accès au dictionnaire et en essayant de voir jusqu’où nous pourrions descendre sur le parcours. Et là, nous sommes allés très bas !</p><p>Mais je vous sens tendu, confus et choqué.</p><p>C’est une parodie de design, une abomination ! Dériver d’une classe <code>dict</code> ? Dériveriez-vous d’un <code>std::vector</code>, d’une <code>std::map</code>, d’une <code>std::pair</code> ? Quel genre de programmeur respectable ferait cela ? Et je serais d’accord ! (Attendez, quoi ? Qui a dit ça ?) Non, non, non, non, je serais vraiment d’accord ! Je le serais, je le serais, je le serais, sauf que…</p><p>… voyez-vous, tout dans la vie est une question de perspective. Tout tient dans la façon de percevoir le monde. Et dans la programmation, la perception est souvent une question de noms. Les noms de types, les noms de fonctions, les noms de variables. Qu’est donc qu’un nom ? Les noms façonnent notre vision du monde et, à une échelle plus humble, nos designs. Alors… et si je vous disais que <code>dict</code> n’est pas le vrai nom de la classe ? Que se passerait-il si nous le renommions… <code>objet</code> ?</p><p>Ah, l’illumination finale ! Oui, maintenant il est logique de dériver d’<code>objet</code>. Maintenant, il est logique que nous ajoutions des éléments permanents fixes à un <code>objet</code> pour qu’il contienne des valeurs de type fixe ! Ce n’est même plus un design surprenant. C’est essentiellement la façon dont un langage comme Python fonctionne sous les couvertures. En Python, chaque objet de chaque classe n’est en fait qu’un dictionnaire de valeurs indexées par des noms. Et maintenant, vous pouvez le faire directement en C++.</p><p>C’est aussi très utile. Vous n’avez plus besoin d’écrire et de réécrire du code passe-partout pour chaque <code>structure</code> et chaque <code>classe</code>. Vous pouvez avoir une seule implémentation pour tous les types, pour des choses comme la sérialisation, l’annulation/rétablissement, la recherche de données, la connexion à des éléments de l’interface utilisateur et diverses autres activités que vous pouvez sûrement imaginer. Vous l’écrivez une fois pour la classe <del><code>objet</code></del> <code>dict</code>. Chaque sous-classe hérite de l’implémentation de l’objet et toutes les données sont toujours accessibles par simple itération sur des éléments ou par recherche de nom.</p><p>N’est-ce pas fantastique ? Alors, sommes-nous arrivés à un endroit qui méritait d’être vu ?</p>
<p><a href="https://www.figma.com">Figma</a> est une <a href="https://www.spiria.com/fr/services/developpement-axe-performance/developpement-applications-web/">application web</a> qui permet la création d’interfaces pour le web et le mobile. Disponible dans le navigateur, elle peut aussi être <a href="https://www.figma.com/downloads/">téléchargée</a> sous la forme d’une application standard. Comme elle fonctionne entièrement en ligne, elle nécessite bien sûr un accès à internet. Si vous ne connaissez pas encore Figma, ou hésitez encore à franchir le cap, voici 10 arguments pour vous convaincre de l’adopter :</p><h2>3 applications en 1</h2><p>Alors que nous utilisons souvent plusieurs applications au quotidien (Sketch, Invision, Zeplin…), Figma regroupe toutes les fonctions dont une équipe de production a besoin : conception, présentation, prototypage et inspection de code à elle toute seule. Petit plus non négligeable : l’utilisation est gratuite pour 3 projets et 2 éditeurs, avec toutes les fonctionnalités essentielles.</p><h2>Courbe d’apprentissage rapide</h2><p><img src="https://cdn.prod.website-files.com/67c06f07cfba9b0adb43e16c/68470c488ee2361c8aa4d103_courbe_apprentissage.webp" style="width: 100%; border-style:solid; border-width:1px;" alt="Figma UI." title="Figma UI."></p><p>Si vous êtes déjà familier avec Sketch, la prise en main de Figma ne nécessitera pas un temps d’apprentissage démesuré, compte tenu des nombreuses similarités de l’interface et des outils entre les deux applications.</p><h2>Travail collaboratif</h2><p><img src="https://cdn.prod.website-files.com/67c06f07cfba9b0adb43e16c/68470c4b407a89d812ce8548_collaboration_figma.webp" style="width: 100%; border-style:solid; border-width:1px;" alt="Figma UI." title="Figma UI."></p><p>La principale différence entre Figma et les autres outils de design réside dans le travail collaboratif. En d’autres termes, vous pouvez être plusieurs designers à travailler en même temps sur un seul et même fichier. Plus besoin de se partager des fichiers VXX, ou de “merger” des éléments dans un document final. Tout ce que vous faites est automatiquement sauvegardé et visualisable en temps réel. Cela peut cependant être un peu déroutant pour certains, car on appréhende d’être “observé” en train de travailler, mais il faut voir les bons côtés : la transparence et le partage facilitent la collaboration à tous les niveaux !</p><h2>Présentations et retours simplifiés</h2><p>Comme je le disais un peu plus haut, plus besoin d’exporter le design une fois le travail effectué : la présentation se fait dans l’outil, et il est possible aux personnes de votre équipe de laisser des commentaires directement sur les maquettes. Finis donc les exports d’écrans et le jonglage entre Sketch et Invision.</p><h2>Partage ciblé</h2><p>Vous avez la possibilité de partager un projet entier, une page, ou seulement un “artboard” via le partage au moyen d’un seul et unique hyperlien. Adieu aux indications laborieuses pour guider votre interlocuteur, il suffit de le mener directement là où vous le désirez !</p><h2>Flexibilité des composants</h2><p>Appelés symboles dans Sketch, les “components” de Figma sont beaucoup plus flexibles à l’utilisation. Alors que la gestion des propriétés de style d’un symbole peut vite être limitée dans Sketch, Figma traite chaque propriété de manière individuelle. Cela permet de modifier indépendamment les éléments, depuis le calque de chaque instance.</p><h2>Compatibilité</h2><p>Comme Figma est entièrement en ligne, n’importe quelle machine disposant d’un navigateur web peut partager, ouvrir ou éditer un fichier Figma. Alors que Sketch n’est disponible que sur Mac, Figma creuse ici un fossé considérable grâce à sa large accessibilité.</p><h2>Transfert au développeur facilité</h2><p><img src="https://cdn.prod.website-files.com/67c06f07cfba9b0adb43e16c/68470c4e014e9f307ab97433_transfert_developpeur.webp" style="width: 100%; border-style:solid; border-width:1px;" alt="Figma UI." title="Figma UI."></p><p>L’inspection des propriétés s’effectue à même l’outil, et on peut afficher les extraits de code pour n’importe quel élément sélectionné, aux formats CSS, iOS ou Android.</p><h2>Puissance des librairies partagées (<i>Team Libraries</i>)</h2><p>Si l’on souhaite créer un “Design System” au sein d’une entreprise, Figma se révèle être l’outil de prédilection. Une fois la librairie créée et partagée au sein de l’équipe, chaque personne peut avoir accès et récupérer les éléments dont elle a besoin, sans avoir à se soucier de savoir s’il s’agit de la bonne et dernière version. (Cette fonctionnalité n’est toutefois <a href="https://www.figma.com/pricing/">pas disponible</a> dans la version gratuite.)</p><h2>Prototypage épuré et intuitif</h2><div>
<p>Quand vous pouvez voir la lenteur, mesurer la lenteur, dénicher quelle partie est lente, vous devez tout de même trouver une solution. Dans cet article, je vais vous expliquer un cas où j’ai vu, mesuré et localisé un problème. J’ai ensuite réglé ce problème et je vais maintenant vous expliquer comment j’ai procédé.</p><p>Une première mise en garde. Je ne présenterai pas le genre de technique étonnante, de bas niveau, bien documentée et mathématiquement prouvée, comme celle de Daniel Lemire. Pour voir un exemple de ce type d’optimisation, allez voir par exemple : “<a href="https://lemire.me/blog/2018/05/03/how-fast-can-you-parse-json/">How fast can you parse JSON?</a>”.</p><p>Ici, nous ne comptons pas les cycles du CPU. Dans cet article, je parle uniquement des optimisations simples qu’un programmeur de logiciels moyen peut faire au quotidien.</p><h2>Voir le problème</h2><p>Le programme sur lequel je travaillais était un filtre pour les gros fichiers texte organisés en arbre. C’est-à-dire que l’indentation de chaque ligne dans le fichier représentait le niveau d’imbrication. Quand je parle de gros fichiers, je veux dire traiter couramment 100 Mo à 1 Go de données de journal. Ce programme a été écrit en C++.</p><p>La 1<sup>re</sup> approche a consisté à lire le texte dans un vecteur de wstring (std::vector<std::wstring>). La raison de ce choix de départ est basée sur des principes bien connus sur la façon de choisir un conteneur en C++. Le premier principe est le suivant :</p><p><i><b>Utilisez toujours un std::vector</b></i>.</p><p>(Le deuxième principe est “utilisez un vecteur trié” et le troisième est “êtes-vous vraiment sûr qu’un vecteur ne fera pas l’affaire ?”)</p><p>Il était maintenant évident, lors de tests avec des fichiers de grande taille, que la lecture et le filtrage d’un si grand vecteur de chaînes de caractères étaient lents. Lorsque votre chronomètre est suffisant pour savoir que la performance n’est pas au rendez-vous, vous pouvez commencer à jeter un coup d’œil.</p><h2>Mesurer le problème</h2><p>Heureusement, il est très facile de jeter un coup d’œil grâce à Visual Studio. Même l’édition communautaire est livrée avec un très bon profileur CPU. Juste sous le menu “Debug”, l’entrée “Performance Profiler…” (raccourci : Alt+F2) ouvrira une fenêtre avec votre cible de projet déjà sélectionnée pour le profilage. De là, il vous suffit de cliquer sur le bouton “Start” et votre programme s’exécutera sous le profileur CPU. Faites simplement l’opération que vous souhaitez mesurer et quittez. Mesure effectuée !</p><p>Voici à quoi ressemble la fenêtre du profileur lorsqu’il enregistre les activités de votre programme :</p><p><img src="https://cdn.prod.website-files.com/67c06f07cfba9b0adb43e16c/684707344f06d76dfc2d8040_profiler_1.webp" style="width: 100%; border-style:solid; border-width:1px;" alt="Profiler" title="Profiler"></p><h2>Localiser le problème</h2><p>Le profileur analysera les données et vous présentera une liste des fonctions où votre programme passe le plus de temps. Par défaut, cette liste est organisée en fonction du temps total du CPU, comme ceci :</p><p><img src="https://cdn.prod.website-files.com/67c06f07cfba9b0adb43e16c/6847073727510e29db895ad5_profiler_2.png" style="width: 100%; border-style:solid; border-width:1px;" alt="Profiler" title="Profiler"></p><p>Si cela vous donne une vue d’ensemble, cela signifie également que vous voyez beaucoup de données non pertinentes. Vous pouvez toujours trouver facilement la zone problématique en recherchant des sauts importants dans le pourcentage de temps passé. De ce cas-ci, il s’avère que beaucoup de temps est passé à copier des chaînes de texte et à allouer de la mémoire. Les allocations de mémoire proviennent des chaînes de texte et du redimensionnement du vecteur. Il y a également un temps important passé dans les entrées/sorties des fichiers lors de la lecture du texte.</p><p>Nous disposons maintenant de quelques emplacements, nous sommes donc en mesure de trouver une solution au problème de performance.</p><h2>Emprunter quelques trucs</h2><p>Une bonne idée pour optimiser est de connaître les astuces que d’autres ont utilisées. Une réalisation importante est que lors du filtrage, le texte lui-même ne change pas. Seul ce qui est conservé ou non change. Ceci signifie que nous pouvons emprunter quelques astuces aux langages fonctionnels :</p><ul> <li><b><i>Les constantes peuvent être partagées</i></b>.</li> <li><b><i>Éviter de déplacer les données</i></b>.</li> <li><b><i>Déléguer la gestion de la mémoire</i></b>.</li></ul><p>L’idée est donc de rendre le texte partageable, de l’extraire le plus directement possible du disque et de lui ôter la gestion de la mémoire dans laquelle il réside. Nous allons donc faire ce qui suit :</p><ol> <li><b><i>Les constantes peuvent être partagées</i></b> : lire les données du disque dans de grandes mémoires tampon de données non modifiables.</li> <li><b><i>Évitez de déplacer les données</i></b> : recherchez des lignes de texte dans ces tampons et gardez des pointeurs directement dans le tampon.</li> <li><b><i>Évitez de déplacer les données</i></b> : partagez ces tampons et ces lignes de texte dans le résultat du filtrage.</li> <li><b><i>Déléguer la gestion de la mémoire</i></b> : partager ces tampons lors de la copie du texte.</li></ol><p>En bref, nous sommes passés du code :</p><pre><code>struct VectorOfWStringTextHolder { using Line = std::wstring; std::vector<Line> Lines; };</code></pre><p>À ce code:</p><pre><code>struct VectorOfSharedBuffersTextHolder { using Buffer = vector<wchar_t>; using BufferPtr = shared_ptr<Buffer>; using Buffers = vector<BufferPtr>; Buffers TextBuffers; using Line = wchar_t *; std::vector<Line> Lines;</code></pre><p>L’idée ici est qu’en utilisant un vecteur de tampons partagés, les adresses des tampons ne changent jamais et peuvent être facilement partagées entre plusieurs instances.</p><p>Bien sûr, ces changements ont rendu le code plus complexe. La complexité peut cependant être cachée, car les tampons peuvent rester privés et seul un vecteur de lignes peut être exposé publiquement. Le code a été simplifié ici pour s’assurer que les benchmarks mesurent ce que nous voulons mesurer.</p><h2>Les résultats</h2><p>Oui, des benchmarks ! Après tout, il est inutile d’optimiser si vous ne pouvez pas vérifier l’amélioration. En général, il suffit de réutiliser le profileur CPU et de voir les nouveaux résultats. Mais pour cet article, je suis allé plus loin et j’ai extrait l’essentiel de l’ancien et du nouveau code et j’ai écrit un petit programme de référence qui charge un gros fichier et fait des copies partielles des lignes de texte pour imiter le filtrage.</p><p>L’avantage d’écrire un benchmark explicite est que vous pouvez placer les mesures de temps exactement là où vous le souhaitez. De cette façon, vous ne mesurez que ce qui est prévu. Avec le profilage du CPU, l’ensemble du programme est mesuré et il est plus difficile d’en extraire les données pertinentes.</p><p>Voici les résultats. (J’ai exclu les temps d’entrée/sortie, mais la lecture dans de grands tampons et l’analyse directe des tampons ont donné un gain similaire.)</p><table style="width:100%"> <tbody> <tr> <th>Format des données</th> <th>Durée</th> </tr> <tr> <td style="vertical-align: top;"><i>Vector of strings</i></td> <td style="vertical-align: top;">13,28 s.</td> </tr> <tr> <td style="vertical-align: top;"><i>Shared buffers of shared lines</i></td> <td style="vertical-align: top;">1,2 s.</td> </tr> </tbody></table><p>Comme on peut le voir, nous avons obtenu une accélération d’un facteur de plus de 10. (En fait, nous avons obtenu une amélioration encore plus importante sur les fichiers plus volumineux, car la réallocation d’un très grand vecteur est très coûteuse).</p><h2>Le code</h2><p>J’ai fourni le code montrant divers benchmarks et une autre approche utilisant std::deque. J’avais également fait quelques benchmarks dans une structure arborescente dont je n’ai pas parlé ici. (Le changement n’a pas amélioré les performances dans ce cas, mais il a permis d’éviter un autre problème sans rapport avec la profondeur de récursion et le débordement de pile lors de la destruction de structures profondément liées de pointeurs partagés).</p><p>Vous pouvez trouver le code <a href="https://github.com/pierrebai/FastTextContainer">sur GitHub</a>.</p><p>Notez que l’utilisation réelle de cette technique se trouvait dans mon projet de filtrage d’arbre de texte, également disponible sur GitHub. L’optimisation a été faite dans TextTree et la façon dont il contient les données de texte à travers un TextHolder. Il utilise également une astuce similaire pour pouvoir avoir des adresses stables pour ses nœuds d’arbre en utilisant le fait souvent négligé qu’un std ::deque n’invalide pas les pointeurs lorsqu’on ajouter des données. Le code se trouve <a href="https://github.com/pierrebai/TreeReader">ici</a>.</p>
<p>De plus, je voulais permettre de transférer les items entre plusieurs QlistWidget, via le glisser-déposer (<i>drag and drop</i>). Cela est facilement pris en charge dans le QListWidget standard. Le glisser-déposer permet de concevoir une interface utilisateur facile à utiliser et intuitive, et ça me semblait important à supporter.</p><p>Et pourtant, remplir ces deux conditions s’est avéré plus difficile que je ne l’avais prévu. Dans cet article, je vais survoler tous les obstacles que j’ai rencontrés et la solution finale, étonnamment simple, à tous ces problèmes.</p><h2>Premier essai</h2><p>La première approche naïve consiste à penser qu’il doit être possible d’ajouter simplement un QWidget contenant plusieurs sous-widgets dans un QListWidget. Il existe de nombreux exemples montrant une vue en liste contenant des cases à cocher. Ainsi, pour ajouter d’autres types de boutons, il faudrait simplement trouver la bonne fonction à appeler. Quelque chose doit être enterré dans la documentation Qt quelque part à ce sujet, n’est-ce pas ?</p><p>J’ai continué à fouiller dans la documentation de Qt, mais je n’ai jamais rien trouvé. Il s’avère que c’est tout simplement impossible.</p><p>Quand on y pense, il y a une raison pourquoi Qt ne permet pas de le faire. Le QListWidget peut contenir des milliers d’éléments dans une vue. Si chacun de ces éléments contenait plusieurs widgets, cela donnerait des milliers de widgets en même temps à l’écran. Étant donné que chaque widget fournit une interface riche, et donc beaucoup de données, ceci représente une charge très lourde. Au lieu de cela, Qt ne conserve que le strict minimum de données par élément dans la liste. Ce détail signifie que les widgets ne peuvent pas être placés directement dans une liste.</p><h2>Deuxième essai</h2><p>En cherchant dans la documentation de Qt, vous trouverez le concept de délégué d’item (QItemDelegate). C’est ainsi que Qt permet à l’usager de modifier les données d’un item dans une liste. Malheureusement, cette solution présente de nombreuses failles. L’interface utilisateur qui en résulte est non intuitive et difficile à découvrir, ce qui la rend inélégante.</p><p>L’utilisation d’un délégué est obscure, car les boutons ne sont pas visibles dans la liste. Pour faire apparaître les boutons, l’éditeur d’éléments doit être invoqué par l’utilisateur. L’utilisateur doit faire ce que Qt appelle une “action d’édition” : soit en appuyant sur F2, soit en double-cliquant. Ce ne sont pas des gestes qu’un utilisateur connaîtra. Il en résulte une interface utilisateur qui n’est pas intuitive ni facile à découvrir.</p><p>Il est également obscur, car tout cela nécessite que l’utilisateur sache déjà que l’item de la liste est modifiable…</p><p>Si seulement il y avait un moyen de montrer l’item en mode modifiable à tout moment…</p><h2>Troisième essai</h2><p>… mais il y en a un ! Le délégué d’item fournit une fonction de dessin qui peut être modifiée pour dessiner n’importe quoi. Mais comment dessiner n’importe quel autre widget ? Il y a en fait un moyen. Si vous regardez le code source pour savoir comment le widget de la liste standard peint la case à cocher, vous pouvez voir que Qt fournit des classes “style-option” pour dessiner les widgets. Mais si vous lisez la documentation, vous verrez qu’elle est très brève et plutôt incomplète. De plus, le support de toutes les fonctionnalités normales du widget, comme le survol et la sélection, nécessite beaucoup de code.</p><p>Et même si vous dessinez les widgets, ils ne sont toujours pas interactifs ! L’utilisateur doit toujours double-cliquer pour les rendre modifiables. Cela s’avère donc encore plus déroutant pour l’utilisateur.</p><p>Mais si cela ne suffisait pas, il y a encore un autre accroc. Le hic, c’est que les délégués ne peuvent être utilisés que par des modèles d’items (QAbstractItemModel) personnalisés. Vous ne pouvez pas utiliser un délégué avec un modèle d’items standard. Vous pourriez penser que ce n’est pas trop mal, que vous pourrez en créer un vous-même. Malheureusement, la mise en œuvre de votre propre modèle personnalisé n’est pas simple. Le problème est que Qt a des règles strictes sur la façon dont un modèle d’item doit se comporter. Il est difficile d’appliquer correctement toutes les règles, et tout écart entraîne un comportement étrange et des pépins très difficiles à diagnostiquer. Et ce, uniquement pour un modèle non éditable. Si vous voulez supporter le glisser-déposer, alors les règles sont encore plus complexes et impitoyables.</p><p>Le recours à un délégué entraîne donc l’écriture d’un grand nombre de lignes de codes dont la mise en œuvre et la maintenance sont très complexes. Il doit y avoir un meilleur moyen !</p><h2>Essai final</h2><p>Quelle est donc la bonne façon de mettre des widgets complexes dans une liste ? La réponse est d’une simplicité déconcertante : n’utilisez pas un widget de liste. Utilisez un widget simple. Oui, un simple QWidget.</p><p>Après tout, un QWidget peut contenir une liste arbitraire de sous-widgets. Bien entendu, vous devez alors ajouter la fonctionnalité standard d’une vue en liste par-dessus. Il faut supporter la sélection, le glisser-déposer et le défilement. Mais il s’avère que c’est beaucoup plus simple à écrire que les autres approches. Et, en prime, vous avez la garantie que le comportement de toutes les interfaces utilisateur que vous mettrez dans vos articles sera exactement le même que le comportement normal auquel l’utilisateur s’attend.</p><h2>La solution</h2><p>Ma solution au problème de la création d’un widget semblable à QListWidget pouvant contenir des widgets complexes est la suivante. Il y a quatre classes qui interagissent entre elles pour former la solution.</p><table style="width:100%"> <tbody> <tr> <th>Classe</th> <th>But</th> </tr> <tr> <td style="vertical-align: top;"><i>QWidgetListWidget</i></td> <td style="vertical-align: top;">Le widget qui contient les items.</td> </tr> <tr> <td style="vertical-align: top;"><i>QWidgetListItem</i></td> <td style="vertical-align: top;">Les éléments qui peuvent être mis dans la liste. Peut contenir un nombre quelconque de sous-widgets, de n’importe quel type.</td> </tr> <tr> <td style="vertical-align: top;"><i>QWidgetScrollListWidget</i></td> <td style="vertical-align: top;">Une enveloppe autour de QWidgetListWidget pour permettre le défilement.</td> </tr> <tr> <td style="vertical-align: top;"><i>QWidgetListMimeData</i></td> <td style="vertical-align: top;">Les données MIME utilisées pour supporter le glisser-déposer entre plusieurs QWidgetListWidget.</td> </tr> </tbody></table><h3>QWidgetListWidget</h3><p>C’est l’un des deux principaux points d’intérêt de la conception : le widget de liste. Cette vue de liste permet de sélectionner des éléments et de les faire glisser. Il fournit une interface simple, composée de quelques fonctions. Voici la déclaration en C++ de ces fonctions :</p><pre><code>// Créer une liste de widgets.QWidgetListWidget(ListModifiedCallbackFunction modifCallback, bool stretch, QBoxLayout::Direction dir, QWidget * parent);// Vérifiez si la liste est verticale ou horizontale.bool isVertical() const;// Enlever tous les éléments de la liste.void clear();// Ajouter un item.QWidgetListItem* addItem(QWidgetListItem* item, int index = -1);// Supprimer un élément.void removeItem(QWidgetListItem* item);// Récupérer tous les éléments conservés dans cette liste.std::vector<QWidgetListItem*> getItems(bool onlySelected = false) const;// Récupérer tous les éléments sélectionnés conservés dans cette liste.std::vector<QWidgetListItem*> getSelectedItems() const;</code></pre><h3>QWidgetLisItem</h3><p>C’est le deuxième point d’intérêt principal. C’est un élément qui peut être sélectionné et qui peut être cloné. Le clonage est utilisé lors du glisser-déposer pour copier un élément d’une liste à une autre. Voici l’interface complète en C++. Elle est assez courte :</p><pre><code>// Créer un item.QWidgetListItem(QWidget* parent);// Sélection.bool isSelected() const;void select(bool sel);// Clonage d’objets pour le glisser-déposer.virtual QWidgetListItem* clone() const;</code></pre><h3>QWidgetScrollListWidget</h3><p>Cette classe n’existe que pour que le défilement de la liste soit facultatif. Il peut sembler étrange de rendre le défilement optionnel, mais c’est assez pratique lorsque vous voulez intégrer la vue de la liste dans les éléments d’une autre vue de la liste. Toute l’interface C++ est simplement ceci :</p><pre><code>// Créer un widget défilant autour d’un autre widget.QWidgetScrollListWidget(QWidget * widget, QWidget* parent);</code></pre><h3>QWidgetListMimeData</h3><p>La dernière classe n’existe que pour le glisser-déposer. Vous ne devriez jamais avoir à l’utiliser directement. L’ensemble de son implémentation en C++ est la suivante :</p><pre><code>static constexpr char MimeType[] = "application/x-qwidget-list-item";QWidgetListItem* Widget = nullptr;QPoint HotSpot;</code></pre><h2>Le code</h2><p>L’intégralité de la mise en œuvre est <a href="https://github.com/pierrebai/QWidgetListWidget">disponible sur GitHub</a>.</p><p>Le code est accompagné d’un exemple d’application montrant comment utiliser les classes. Voir la description sur GitHub sur la façon de construire le projet.</p><p>Un exemple plus complexe peut être trouvé dans le projet TreeFilterApp. Il montre même comment placer des listes dans d’autres listes. Le code est également <a href="https://github.com/pierrebai/TreeReader">sur GitHub</a>.</p>
<p>Un jour ou l’autre, quelqu’un lira votre code et essaiera de comprendre quelle est sa finalité. Cette personne pourra même être vous-même… et il est bien possible que vous perdiez du temps à tenter de comprendre ce que vous avez écrit quelques mois plus tôt, parce que ce n’est plus très frais dans votre mémoire et parce que vous n’avez pas accordé suffisamment d’attention à la lisibilité.</p><p>J’ai eu l’occasion d’assister à une présentation sur les bonnes pratiques de rédaction de code faite par Jason McCreary (@<a href="https://twitter.com/gonedark">gonedark</a>). Si rien n’est en soi très révolutionnaire, c’est un ensemble de règles que j’ai trouvé intéressant de partager et qu’il me semble important de garder à l’esprit.</p><p>Jason propose une liste de 10 points à garder en tête pour que vous ou le programmeur suivant puisse comprendre facilement et intuitivement votre code. Pensez-y, si votre code est immédiatement compréhensible, il pourrait vous arriver de sauver la fin de semaine d’un collègue en support postproduction, ou celle d’un futur vous-même.</p><h2>Formater</h2><p>Il y a plein de normes et de possibilités. Il ne s’agit pas de débattre sur l’indentation par des tabulations ou par des espaces, ou encore des mérites comparés des styles Allman et K&R, mais plutôt de convenir d’une norme (par exemple <a href="https://www.php-fig.org/psr/psr-12/">PSR12</a>) et de s’y tenir. Les “CodeSniffer” et les environnements de développement (IDE) font très bien la détection automatique de violations d’une norme de codage définie et ils permettent de s’assurer de maintenir une base de code propre et cohérente. Soyez rigoureux et consistants.</p><h2>Code mort</h2><p>Le code est mort, effacez-le !!! Faites le ménage dans ces blocs commentés, ces variables inutilisées et ce code qui n’est jamais appelé. Voyez votre programme comme un arbre bien entretenu : il y a des moments où il faut couper le bois mort pour favoriser une croissance harmonieuse et éviter les accidents.</p><h2>Code imbriqué</h2><p>Si vous respectez le premier point et que votre indentation vous amène à commencer votre ligne en dehors des limites de l’écran, c’est un signe qu’il faut peut-être revoir votre approche. Évidemment les conditions imbriquées sont partie intégrante d’un code, mais, quitte à écrire des sous-fonctions, il faut garder en tête que le programmeur derrière vous n’a pas forcément le diagramme que vous aviez sous les yeux pour écrire vos conditions ! Démêlez le code imbriqué en utilisant des clauses de garde, des retours anticipés ou des aspects de la programmation fonctionnelle.</p><h2>Utiliser des <i>objects</i></h2><p>C’est une remarque un peu plus destinée aux programmeurs PHP, mais elle s’applique à bien d’autres langages. L’idée ici est de privilégier l’utilisation d’objets sur celle des tableaux. L’exemple le plus évident en PHP est l’utilisation de tableaux pour passer un nombre variable de variables.</p><h2>Gros blocs de code</h2><p>On le sait tous qu’une fonction de 500 lignes, c’est mal. Alors, n’en faites pas ! Jamais. Si vous traînez déjà un bloc de code atteignant une longueur critique, il est temps de le remanier en un bloc plus lisible et moins complexe.</p><h2>Dénomination</h2><p>“foo” est un nom de variable pour les exercices à l’école, pas un pour la vraie vie.</p><p>Si la fonction <code>getWeekReport</code> retourne un rapport pour un mois, c’est que ce n’est définitivement pas un bon nom.</p><p>Si la fonction <code>getReport</code> retourne uniquement un rapport pour une semaine, elle pourrait judicieusement s’appeler <code>getWeekReport</code>.</p><p>Si vous ne trouvez pas le bon nom tout de suite, continuez à coder et revenez-y plus tard. Ce ne doit pas être un bloquant et le nom parfait s’imposera de lui-même plus tard.</p><h2>Adieu les commentaires</h2><p>Voilà qui est un peu provocant, mais il faut en fait considérer les points suivants :</p><ol> <li>Les DocBlocks ne sont pas des commentaires ; on les aime et on en veut.</li> <li>Si vous avez besoin d’expliquer votre code avec du texte, c’est probablement que votre code est améliorable.</li> <li><code>$today = date(); // Set today date</code>. Ceci est un parfait exemple de commentaire non pertinent.</li> <li>Les commentaires ne sont pas interdits pour autant, par exemple s’ils servent à expliquer une règle d’affaires.</li> <li>On préfère de loin pas de commentaires du tout à des commentaires erronés !</li> <li>Au final, peu importe les commentaires, seul le code est exécuté. Seul le code compte vraiment.</li></ol><p>Mettez-vous donc au défi de réécrire le code pour qu’il n’ait pas besoin de commentaires.</p><h2>Valeurs de retour acceptables</h2><p>Un lecteur doit comprendre facilement ce que la fonction retourne. Certains préfèrent un seul retour dans la fonction. D’autres regroupent par type de retour (par exemple tous les <code>if … return true</code> au début, puis les <code>if return false</code> ensuite).</p><p>Idéalement, on doit éviter de pelleter dans le jardin du voisin les cas qui nous embêtent. Comme le <code>return null</code> qui implique que le cas <code>null</code> va probablement devoir être traité ailleurs.</p><h2>Règle des 3</h2><p>C’était nouveau pour moi et j’ai trouvé ce principe intéressant. Il s’illustre comme suit :</p><ul> <li>Si je vous demande ce qui vient après “2”, vous pouvez ne pas avoir de réponse. Ce peut être 3 ou 4, ou pourquoi pas 1 ou 2,1.</li> <li>Si je vous demande ce qui vient après “2, 4”, vous avez quelques idées, mais pas de certitude.</li> <li>Si je vous demande ce qui vient après “2, 4, 16”, vous pensez certainement à 256.</li></ul><p>C’est la règle des 3.</p><p>Dans le monde des programmeurs, cela signifie que votre code devrait suivre une logique. Il faut donc éviter les cas où votre code fait “2, 4, 6, 27” ! Votre code est peut-être juste et fait ce qu’il faut, mais c’est totalement contre-intuitif pour le lecteur.</p><p>Dans la même approche, si votre code fait “2, 4, <code>call function DonextStep</code>”, ça peut aussi nuire à la lisibilité de votre code. Cela implique de parfois devoir dupliquer votre code. Donc, oui, ça va à l’encontre du <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a>... ¯\_(ツ)_/¯</p><h2>Symétrie</h2><p>Pour garder ce concept simple, je l’illustrerai en disant que si on a deux fonctions <i>create</i> et <i>update</i>, on s’attend alors à ce qu’elles prennent le même type de paramètres et retournent le même type de variable.</p><pre><code>Function update (User user) : boolean successFunction create(User user) : boolean success</code></pre><p>Plutôt que :</p><pre><code>Function update (int userId, User user) : boolean successFunction create(Array[]) : User user</code></pre><p>Si vous souhaitez approfondir ces principes, Jason McCreary a publié <i>BaseCode</i>, un guide dans lequel il développe davantage les différents points et les illustre par de nombreux exemples pratiques (disponible pour 29 $ sur <a href="https://basecodefieldguide.com">son site</a>). Vous pouvez aussi regarder des <i>screencasts</i> sur <a href="https://www.youtube.com/watch?v=s9LwS6RFax0&list=PLmwAMIdrAmK7cjLLYrKppUhaR2ywTuKhm&index=1">sa chaîne YouTube</a>.</p><p>Bon code!</p>