Blogue
Savoir-faire et technologie
Histoires, idées et perspectives sur la stratégie, la technologie et les solutions d’affaires.

Articles à la une

Nouvelles
5 min de lecture
Annonce : Spiria est certifiée SOC 2 Type 2
<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>

Stratégie
5 min de lecture
Temps et matériel ou forfaitaire, que choisir ?
<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;"><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/11800/process-fr.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/11800/process-fr.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/11800/process-fr.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/11800/process-fr.webp" style="width: 60%; border: none;" alt="Un cycle projet type." title="Un cycle projet type."></source></source></source></picture></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><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/11800/strategies-fr.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/11800/strategies-fr.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/11800/strategies-fr.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/11800/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)."></source></source></source></picture></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.

Coin des développeurs
5 min de lecture
C++ hypothétique : des qualificateurs extensibles
<p>C++ a accès à un riche ensemble d’outils pour concevoir des types et créer ce vocabulaire. Son système de types est ouvert et permet au programmeur de définir de nouveaux types selon ses besoins. Pourtant, il y a un aspect qui demeure fermé : les qualificateurs de type.</p><p>C++ nous offre deux qualificateurs de type : <code>const</code> et <code>volatile</code><sup><a href="#footnotes">(1)</a></sup>. Ils permettent de donner un sens supplémentaire à un type existant, sans avoir à créer un type séparé à la main. Le qualificateur <code>const</code> est bien sûr le plus utilisé. S’il n’existait pas, il serait fastidieux de devoir reproduire son comportement pour chaque type que nous créons. Sans lui, C++ serait beaucoup moins expressif et il serait plus difficile de l’utiliser pour programmer. Et pourtant, ce pouvoir expressif se limite à ces deux qualificateurs. Il y a un décalage entre leur utilité et notre incapacité à en créer de nouveaux.</p><h2>Qualificateurs définis par l’utilisateur</h2><p>Ce que j’aimerais voir dans C++ est la possibilité pour le programmeur de définir ses propres qualificateurs. Je vais vous donner quelques exemples de ce qui peut être réalisé avec des qualificateurs définis par l’utilisateur, mais décrivons d’abord comment ils fonctionneraient. C’est très simple, vraiment. Ils fonctionneraient exactement comme <code>const</code> et <code>volatile</code>. C’est à dire :</p><ul> <li>La capacité de qualifier un type ou une fonction membre.</li> <li>Une équivalence unidirectionnelle automatique et optionnelle pourrait être déclarée, similaire à la manière dont on passe un pointeur non-<code>const</code> à une fonction qui prend un pointeur <code>const</code>.</li> <li>La possibilité d’une conversion forcée entre le type qualifié et le type non qualifié à l’aide d’un <code>const_cast</code><sup><a href="#footnotes">(2)</a></sup>.</li></ul><p>Je ne veux pas me concentrer sur les détails d’une syntaxe fictive. Je crois que ce n’est pas très important et tout le monde pourrait proposer quelque chose. Je vais juste montrer une possibilité en utilisant un nouveau mot-clé <code>typequal</code> :</p><pre><code>typequal NewQualifier;typequal NewQualifier auto qualified;typequal NewQualifier auto non-qualified;typequal NewQualifier invalid;typequal NewQualifier invalid auto qualified;</code></pre><p>Chacun de ces exemples créerait un qualificateur nommé <code>NewQualifier</code>. La variante « <code>auto qualified</code> » indique que le qualificateur peut être ajouté silencieusement à un type quand il est affecté à une variable, comme fonctionne le qualificateur <code>const</code>. La variante « <code>auto non-qualified</code> » permet la conversion automatique inverse. Qu’en est-il de la variante « <code>invalid</code> » ? Celle-ci déclare que les données avec le qualificateur ne sont pas accessibles. Comme vous le verrez, c’est une fonctionnalité utile à avoir.</p><h2>Les bénéfices</h2><p>Maintenant, je voudrais vous convaincre de l’utilité de cette fonctionnalité. Essayons de résoudre quelques problèmes qui causent de vrais bogues dans de vrais programmes.</p><h3>1. Pointeurs Null</h3><p>Commençons par les pointeurs <code>null</code>. Le déréférencement des pointeurs <code>null</code> est une source majeure de bogues. Avoir des pointeurs « nullables » est souvent décrié comme une erreur majeure dans la conception du langage. Mais le vrai problème n’est pas en soi le pointeur <code>null</code>, mais en fait que le langage ne nous empêche pas d’utiliser un pointeur <code>null</code>. Corrigeons ça :</p><pre><code>typequal maybe invalid;</code></pre><p>Voilà. Désormais, chaque fonction qui produit un pointeur doit produire un pointeur avec le type sous-jacent agrémenté du qualificateur <code>maybe</code>. Comme c’est un qualificateur de marquage invalide, le langage ne nous permettra pas d’utiliser les données. Une fois que vous avez testé pour <code>null</code>, vous pouvez faire le « <code>const_cast</code> » pour supprimer le qualificateur <code>maybe</code>. Bien sûr, il serait bien plus pratique si le langage supportait nativement un tel qualificateur, de sorte que les fonctions intégrées prendraient et donneraient des pointeurs déjà qualifiés.</p><h3>2. Données non-validées</h3><p>Des qualificateurs similaires peuvent être utilisés pour décrire différents états de données. Deux exemples qui reviennent souvent dans le code seraient :</p><pre><code>typequal invalidated invalid auto qualified;typequal tainted invalid auto qualified;</code></pre><p>Le premier pourrait être utilisé pour marquer les données quand elles n’ont pas encore été validées en regard d’une contrainte souhaitée. Souvent, un groupe de fonctions posera de telles contraintes sur ses entrées. En s’assurant par design que le point d’entrée prenne des données <code>invalidated</code> et les fonctions internes qui prennent des données non qualifiées, nous pouvons nous assurer que les fonctions internes ne peuvent être appelées sans que les données soient validées.</p><p>La seconde est une idée empruntée à Perl : que les données <code>tainted</code> ne sont pas fiables. Le marqueur est similaire au <code>invalidated</code>, mais au lieu de simplement ne pas suivre certaines contraintes, les données doivent être traitées entièrement avec suspicion. En Perl, ces données <code>tainted</code> proviennent du Web, de courriels et d’autres sources non fiables. Des précautions supplémentaires doivent donc être prises lors de la validation de ces données.</p><h3>3. État des données</h3><p>Bien sûr, afin de refléter la progression d’un algorithme, un tel système de validation peut être étendu pour prendre en charge de multiples états. Il peut aussi refléter différents types de validation. Voici quelques idées :</p><pre><code>// Les données sont ordonnées.typequal sorted;// Ordonne un vecteur et retourne ce même vecteur avec le qualificateur.sorted vector<int>& sort(vector<int>& unsorted_vector);// Fait une recherche binaire sur un vecteur seulement s'il a été ordonné.bool find_in_data(const sorted vector<int>& sorted, int value);// Les données sont partagées entre des threads.// On créerait un verrou (Lock) sur un mutex prenant// ces données en argument et qui enlèverait le qualificateur.typequal shared invalid;// Quel système de coordonnées est utilisé en 3D.// Évite d'utiliser des points en coordonnées "locales"// dans un algorithme nécessitant des points "monde".typequal local;typequal world;typequal view;typequal screen;// Lors de l'application de la bonne matrice, les points// sont qualifiés avec le bon qualificateur de coordonnées.world vector& apply_world_matrix( local vector&, const local world matrix&);</code></pre><h2>Conclusion</h2><p>Mon objectif était de vous faire voir l’intérêt qu’il y aurait à ajouter des qualificateurs définis par l’utilisateur dans le langage C++. Comme je l’ai montré, avec les qualificateurs définis par l’utilisateur, nous ouvrons la porte à de nombreuses possibilités ayant de grands avantages :</p><ul> <li>Être plus expressif avec les types de données existants.</li> <li>Présenter clairement au lecteur du code quel est l’état des données.</li> <li>Suivre la progression de l’évolution des données.</li> <li>Permettre au compilateur de faire respecter diverses contraintes.</li> <li>Éviter les bogues liés à la transmission de données incorrectes aux fonctions.</li></ul><div><p><br> </p><hr><p><sup>(1) </sup>Il y a aussi les qualificateurs <code>restricted</code>, <code>register</code> et <code>auto</code>, mais ils ne fonctionnent pas comme <code>const</code> et <code>volatile</code>.</p><p><sup>(2) </sup>Bien qu’il serait plus élégant de le renommer en <code>qualifier_cast</code>.</p>

Coin des développeurs
5 min de lecture
C++ hypothétique : création facile de types
<p>Quand je regarde du code C++ classique, je vois beaucoup d’utilisations de types de base : <code>int</code>, <code>float</code>, <code>double</code>, <code>std::wstring</code>, <code>const char *</code> -- même s’ils sont utilisés dans chaque cas à des fins extrêmement différentes. Ils peuvent représenter une largeur ou une hauteur, une température, un seuil ou une limite.</p><p>La raison pour laquelle les programmeurs optent pour ces types simples est facile à expliquer : ils sont intégrés, ils ont beaucoup de fonctions de support, et leur comportement est bien connu. Mais il y a une autre raison derrière leur omniprésence : les langages de programmation rendent difficile la création d’un nouveau type avec suffisamment de fonctionnalités.</p><p>Et si ce n’était pas le cas ? Ce que je souhaiterais avoir en C++ est un moyen facile de créer un nouveau type à partir d’un type existant.</p><h2>La situation actuelle</h2><p>C++ possède l’instruction <code>typedef</code>, mais cela crée simplement un synonyme pour un type existant, et les deux sont interchangeables. Vous ne pouvez pas sans risque créer des types <code>Celsius</code> et <code>Fahrenheit</code> à partir d’un <code>double</code> avec un <code>typedef</code> car rien n’empêche d’additionner des <code>Celsius</code> avec des <code>Fahrenheit</code>.</p><p>En apparence, cette propriété de <code>typedef</code> semble utile. Si nous n’avons besoin que d’une version abrégée pour une déclaration de type long ou d’un nom sémantique pour un type, <code>typedef</code> est la solution. Mais est-ce vraiment le cas ? L’utilisation d’une version purement abrégée permet d’économiser des frappes, mais n’aide pas à la compréhension du code. D’autre part, donner un nom sémantique au <code>typedef</code>, par exemple <code>ListOfPeople</code>, aide à comprendre le code, mais n’empêche pas de lui attribuer une liste de noms de fichiers par erreur.</p><p>La manière courante d’éviter de telles erreurs de frappe est d’envelopper le type dans une classe. L’inconvénient, c’est qu’il faut redéclarer chaque fonction membre, ou recréer beaucoup d’opérateurs. Le fait que cette solution existe et qu’elle n’est que rarement utilisée devrait nous en dire long sur les embûches. Le code typique demeure parsemé d’<code>ints</code>, de <code>doubles</code> et de <code>typedef</code>, parce qu’ils sont faciles à créer.</p><h2>Création facile de types</h2><p>Ce dont nous avons besoin est quelque chose d’aussi simple qu’un <code>typedef</code> qui puisse vraiment créer un nouveau type. Appelons-le <code>typedecl</code>. Idéalement, il serait si simple à utiliser que les programmeurs l’utiliseraient par défaut. Il faut éliminer le plus possible d’obstacles à leur utilisation. Voici ce qu’un <code>typedecl</code> devrait pouvoir faire :</p><ol> <li>Créer un nouveau type.</li> <li>Autoriser une déclaration facile des valeurs littérales.</li> <li>Inclure automatiquement les fonctions internes.</li> <li>Pouvoir inclure facilement des fonctionnalités externes.</li></ol><h3>1. Créer un nouveau type</h3><p>Créer un nouveau type est facile. Il suffit d’en faire la définition de <code>typedecl</code> dans le langage C++. Avec un nouveau type, nous évitons les affectations accidentelles et permettons la surcharge des fonctions. En prenant notre exemple de <code>Celsius</code> et <code>Fahrenheit</code>, voici deux déclarations de fonctions qui ne pourraient pas être écrites côte à côte si ces types étaient un <code>typedef</code> :</p><pre><code>Celsius convert(Fahrenheit);Fahrenheit convert(Celsius);</code></pre><p>Bien que n’importe qui pourrait suggérer des noms de fonctions pour permettre à cela de fonctionner avec <code>typedef</code>, le fait d’être obligé de trouver un tel schéma et, plus important encore, d’avoir besoin de s’en inquiéter en premier lieu, souligne le problème de ne pas avoir un type unique pour chacun.</p><h3>2. Autoriser une déclaration facile des variables littérales</h3><p>Une déclaration facile des variables littérales est importante pour la facilité d’utilisation. Sans cela, ces <code>typedecl</code> ne seraient pas utilisés. Un peu de la façon dont un littéral numérique sera automatiquement et silencieusement typé comme un <code>int</code>, un <code>long</code> ou un <code>double</code> s’il correspond aux limites du type, <code>typedecl</code> devrait offrir le même comportement.</p><h3>3. Inclure les fonctions internes</h3><p>L’inclusion automatique des fonctions internes est encore une fois une réponse à notre but de rendre l’utilisation simple. Par exemple, avec les types numériques (<code>int</code>, <code>double</code>, …) nous ne voulons pas avoir à déclarer toutes les opérations possibles entre deux variables. Si c’est fastidieux, le <code>typedecl</code> ne sera pas utilisé, tout comme envelopper un entier dans une classe est rarement utilisé. Il devrait aussi en aller de même pour les types plus complexes qui pourraient servir de base à un <code>typdecl</code>. Par exemple, un <code>typedecl</code> basé sur un <code>std::string</code> devrait inclure ses fonctions membres, avec toutes les instances des paramètres <code>std::string</code> remplacées par le nouveau type.</p><h3>4. Inclure des fonctions externes</h3><p>La partie la plus difficile est la dernière : permettre d’inclure des fonctions externes au type. Une fois de plus, la facilité d’utilisation pour le programmeur aura une influence directe sur la fréquence d’utilisation. Il devrait être facile de cloner une fonction existante pour le nouveau type. Idéalement, il devrait être facile de cloner tout un groupe de fonctions. La syntaxe que je suggère est de réutiliser le même mot-clé, <code>typedecl</code>, avec un modificateur de clonage. Cela permettrait le clonage d’une ou plusieurs fonctions. Par exemple :</p><pre><code>typedecl Celsius clone std::abs;typedecl Celsius clone { std::abs; std::pow, ... }</code></pre><p>Idéalement, il devrait être facile de cloner aussi un espace de noms au complet :</p><pre><code>typedecl Celsius clone namespace std;</code></pre><p>Malheureusement, dans de nombreux cas, cette approche est trop large et aveugle. Idéalement, il faudrait ajouter l’équivalent d’un <code>namespace</code> en C++, sans création d’un identifiant supplémentaire lors de la programmation, mais en créant simplement un groupement sémantique. Par exemple, toutes les fonctions trigonométriques pourraient être regroupées sous une sémantique et toutes les fonctions d’entrées-sorties sous une autre. Voici à quoi pourrait ressembler cet aspect hypothétique du C++ :</p><pre><code>namespace std{ namespace semantic trig { double cos(double); double sin(double); } namespace semantic io { ostream& operator << (ostream&, double); // ... }}</code></pre><p>Avec cette fonctionnalité, la fonction <code>cos()</code> est toujours accessible directement dans le <code>namespace</code> <code>std</code>. L’utilisation du <code>namespace </code><code>trig</code> sémantique serait autorisé, mais facultatif. Le clonage de toutes les fonctions trigonométriques deviendrait simplement :</p><pre><code>typedecl Celsius clone namespace std::trig;</code></pre><p>Dans certains cas, il peut être utile de ne modifier que certains paramètres d’une fonction. Pour cela, nous pourrions emprunter la syntaxe d’un guide de déduction pour donner au compilateur une carte sur la façon dont la conversion automatique doit être faite. Par exemple :</p><pre><code>typedecl Celsius clone double std::pow(double, double) -> Celsius std::pow(Celsius, double);</code></pre><h2>Les bénéfices</h2><p>Maintenant, je vais montrer quelques exemples d’améliorations du code qui peuvent être apportées avec <code>typedecl</code>. Tout d’abord, cela peut contribuer à moins d’erreurs de codage lorsque les arguments d’une fonction sont mal placés :</p><pre><code>// Dans notre monde…void foo(){ int width = get_width(); int height = get_height(); bool stroked = should_stroke(); bool filled = should_fill(); // Cet appel est-il correct ? draw_rect(width, height, stroked, filled);}// Dans le C++ hypothétique...void foo(){ Width width = get_width(); Height height = get_height(); Stroked stroked = should_stroke(); Filled filled = should_fill(); // L’ordre des arguments est nécessairement correct. draw_rect(width, height, stroked, filled);}</code></pre><p>Deuxièmement, il permet de spécialiser la surcharge ou les <code>templates</code> en fonction de la sémantique d’un type plutôt que de son type purement mécanique. C’est beaucoup mieux qu’avec le <code>typedef</code>. Avec <code>typedef</code>, vous devez savoir quel est le type sous-jacent pour savoir si une surcharge ou une instanciation de <i>template</i> est vraiment différente. Si vous utilisez le <code>typedef</code> d’une librairie quelconque, vous devez l’envelopper dans une classe, avec tous les inconvénients de l’interfaçage. Par exemple, prenez le type <code>std::variant</code>. Il permet d’accéder à ses éléments par leur type, mais si deux éléments ont le même type, il y a ambiguïté. Avec <code>typedecl</code>, le fait de créer différents types fait disparaître ce problème.</p><h2>En conclusion</h2><p>Avec ces modifications apportées à C++, nous pourrions finalement nous débarrasser de nombreuses utilisations par défaut et paresse de types purement mécaniques. Il n’y aurait plus aucune raison d’utiliser dans le code de simples <code>int</code>, <code>double</code>, <code>std::string</code>, <code>std::map</code>, etc.. Nous pourrions programmer avec des types ayant du sens qui offriraient plus de sécurité car les créer serait suffisamment simple.</p>

Développement sur mesure
5 min de lecture
8 choses à savoir sur le développement logiciel
<h2>Un langage spécifique</h2><p>Comme c’est le cas pour de nombreux métiers, les professionnels de l’informatique ont leur langage. Des développeurs peuvent employer des mots ou faire appel à des notions que vous ne connaissez pas. N’hésitez pas à demander qu’on vous explique, il n’y a pas de honte à ça. Réclamez toujours des clarifications quand des choses vous paraissent obscures. C’est fondamental, car votre bonne compréhension est la condition de la qualité des échanges et d’une prise de décision bien éclairée. Les bons développeurs se feront un plaisir à vous rendre accessibles leurs savoirs et s’assureront de votre bonne compréhension des éléments clés.</p><h2>Expliquer votre métier</h2><p>Si les développeurs vous expliquent leur métier, il vous faut aussi bien expliquer le vôtre. Ne soyez pas avare en informations ; il est rare qu’un client en donne trop. Plus l’équipe connaît les spécificités de votre entreprise, de votre marché, de vos processus, plus elle a une bonne vue de vos attentes, de votre activité actuelle et de vos plans futurs, plus elle sera imprégnée de votre vision, mieux elle sera à même d’apporter la meilleure réponse à la problématique que vous souhaitez résoudre et mieux elle sera en mesure d’anticiper vos besoins futurs. Et on ne le rappellera jamais assez, une bonne communication bidirectionnelle est cruciale au succès d’un projet logiciel.</p><h2>Ça prend du temps</h2><p>La plupart des projets des logiciels prennent des semaines, souvent des mois à aboutir. Même avec une équipe étoffée, il y a des étapes incontournables qui prennent toujours du temps si on a à cœur la qualité du produit livré : planification, conception, développement, tests. Bien sûr, nous savons que vous aimeriez que votre logiciel vous soit livré le plus rapidement possible, que votre investissement puisse commencer à porter ses fruits dès que possible, mais il n’y a pas de solution magique, à moins de faire l’impasse sur des fonctionnalités ou sur la qualité. Si vos délais sont vraiment courts en raison de différents impératifs, peut-être faudra-il envisager de démarrer avec un <a href="https://www.spiria.com/fr/blogue/developpement-sur-mesure/le-pmv-la-strategie-gagnante-pour-etre-rapidement-sur-le-marche/">produit minimum viable</a> (MVP), c’est-à-dire un logiciel qui réponde juste aux exigences essentielles, et de reporter le développement de certaines fonctions à une version ultérieure.</p><h2>Ça ne prend pas que des programmeurs</h2><p>Le développement logiciel fait appel à une large palette de spécialistes qui n’écrivent pas, ou pas toujours, du code. C’est un travail d’équipe : analystes d’affaires, designers, créateurs d’interfaces, chefs de projets, Scrum Masters, analystes qualité, chargés du support, etc., sont autant de professionnels qui concourent à rendre votre logiciel exceptionnel. Certains accompagnent la totalité du projet, d’autres interviennent pour des phases précises.</p><h2>Les fonctionnalités ne font pas la qualité</h2><p>Se concentrer sur la quantité de fonctionnalités plutôt que sur la qualité de celles qui sont essentielles est faire fausse route. Il faut questionner l’existence de chaque fonction et la définition d’un produit minimum viable (MVP) vous aidera à ce que les efforts soient concentrés sur ce qui est vraiment important. En cours de développement ou après la livraison d’une première version, il est tout à fait courant de se rendre compte que certaines fonctions envisagées en début de projet sont en fait inutiles, et qu’on a bien fait de n’y perdre ni temps ni argent. Et a contrario, il est fréquent que les retours des premiers utilisateurs donnent de bonnes pistes sur la perfectibilité de certaines fonctions et la création d’autres que vous n’aviez pas imaginées et qui vous paraissent désormais aller de soi. Ce qui fait la <a href="https://www.spiria.com/fr/services/developpement-axe-performance/assurance-qualite-test-automatises/">qualité d’un logiciel</a> n’est pas le nombre de fonctionnalités, mais la satisfaction des utilisateurs. Celle-ci passe par la réponse à leurs besoins, par des interfaces conviviales et ergonomiques, par un logiciel exempt de bogues, etc., mais pas par l’accumulation de fonctionnalités dont certaines ne seront jamais utilisées. Ce genre d’accumulation ajoute aussi une couche de complexité qui risque de mettre en péril l’évolution harmonieuse du projet et le respect des délais. Vous économiserez de l’argent en faisant le choix d’un produit évolutif, avec améliorations incrémentales, plutôt que vouloir réaliser tout, tout de suite, et souvent mal.</p><h2>Vous en avez pour votre argent</h2><p>Il en va en matière de développement logiciel comme dans bien d’autres domaines. Si vous construisez une maison avec des matériaux bas de gamme, elle sera sans doute moins durable, et, au fil des années, sa valeur aura tendance à décliner et elle vous coûtera plus cher en entretien. Une étagère Ikea à 50 $, en panneaux de particules mélaminés, sera toujours moins solide et pérenne qu’une en bois massif à plusieurs centaines de dollars. On peut multiplier les exemples de la vie courante. Il y a toujours des conséquences à faire le choix du plus économique, à faire les choses à moitié ou encore à bâcler pour aller plus vite. Les économies immédiates se traduisent toujours par des coûts proportionnellement plus élevés sur le moyen et long terme. Aussi, si votre logiciel est amené à évoluer, il est essentiel de correctement investir sur la qualité de la première version qui servira de fondations aux suivantes. De solides fondations sont la garantie d’économies dans l’avenir.</p><h2>L’art du changement</h2><p>Il est quasiment impossible de tout planifier au départ, à moins d’un projet simple. Une multitude de facteurs font que peu de choses restent à jamais gravées dans le marbre et l’imprévisible fait intrinsèquement partie du processus de développement logiciel. Votre demande peut évoluer avec le temps, les conditions de votre marché ou les attentes de vos clients peuvent changer, vous pouvez devoir avancer le lancement pour des impératifs marketing, une fonctionnalité complexe peut exiger plus de temps que prévu, l’évolution des environnements logiciels peut exiger des adaptations, etc. Le développement d’un logiciel demande de garder l’esprit ouvert aux changements, car ceux-ci sont inéluctables. C’est pour cette raison que l’industrie logicielle a massivement adopté les méthodologies de l’Agilité qui permettent de gérer les changements de la manière la plus économique, sûre et flexible possible.</p><h2>Tout ne s’arrête pas à la livraison</h2><p>Pour le maintenir fonctionnel et efficace, un logiciel nécessite un entretien après sa livraison. On pourrait poursuivre avec l’analogie d’un bien immobilier, c’est similaire. En informatique, nous appelons ça le <a href="https://www.spiria.com/fr/services/developpement-axe-performance/support-maintenance/">support postproduction</a>. Et il est important de savoir dès le début du projet qui s’en chargera et combien ça coûtera, car il faudra des gens pour veiller sur votre logiciel et anticiper les écueils qu’il pourrait rencontrer. En plus de l’entretien courant, c’est-à-dire la résolution des problèmes qui vont inévitablement se produire avec, par exemple, les évolutions de votre parc matériel et logiciel, il y a aussi vos utilisateurs qui vont venir avec de nouvelles demandes auxquelles vous voudrez répondre. Bref, un logiciel continue à vivre après sa livraison et il faut bien le comprendre dès le départ.</p>

Développement sur mesure
5 min de lecture
Identifier le bon partenaire en développement logiciel
<h2>Comment identifier le bon partenaire en développement logiciel ?</h2><p><b>Vos interlocuteurs semblent sincèrement intéressés par votre projet.</b> Ils posent des questions pertinentes. Ils paraissent être tout de suite en mode solution. Si vous ressentez une absence d’enthousiasme, voire des réticences, ce n’est pas nécessairement qu’il s’agit d’une mauvaise entreprise, mais peut-être que vos interlocuteurs ne voient pas votre projet comme s’inscrivant bien dans ceux qu’ils ont l’habitude de traiter. Ils peuvent percevoir un problème de dimensionnement entre votre demande et leur offre. Il peut s’agir d’une question de budget, de savoir-faire, d’expérience, etc., et l’entreprise n’est donc probablement pas celle qui convient parfaitement à vos espérances.</p><p><b>Vos interlocuteurs sont proches de vous.</b> Trouvez si possible un prestataire local : rien ne remplace le contact humain direct pour juger de l’adéquation entre vos besoins et un offreur de services. Cherchez « développement logiciel + nom de votre ville » dans votre moteur de recherche favori. Vous pouvez même être plus spécifique avec des requêtes, par exemple « développement application web + ville ».</p><p><b>Vos interlocuteurs vous comprennent bien.</b> Parlent-ils votre langage, font-ils preuve d’intelligence d’affaires ? Évaluez la bonne comptabilité culturelle et la qualité de la communication. Le succès d’un projet logiciel repose beaucoup sur le fait que les deux parties s’entendent. Ce n’est pas tout d’avoir les meilleurs développeurs du monde, il faut aussi qu’ils saisissent exactement la nature de vos besoins. Votre partenaire doit être en mesure de bien comprendre votre métier, vos objectifs d’affaires, afin de transformer vos idées en logiciel efficace et performant.</p><p><b>Vos interlocuteurs sont d’attentifs pédagogues.</b> Ils prennent le temps de vous expliquer ce que vous ne comprenez pas et s’assurent de votre bonne compréhension. Ils ne vous noient pas dans une avalanche de termes dont vous ne saisissez pas la signification.</p><p><b>Vos interlocuteurs savent vous dire non.</b> Méfiez-vous de ceux qui répondent oui à tout sans discuter et privilégiez ceux qui vous expliquent que, non, tout n’est pas possible, ou encore : non, il serait préférable de faire autrement, d’adopter une stratégie différente pour garantir le succès. Choisissez celui qui peut vous ouvrir de nouveaux points de vue, de nouvelles perspectives pour votre projet. Bref, qui peut l’enrichir et qui ne se contente pas d’enregistrer vos requêtes.</p><p><b>Vos interlocuteurs maîtrisent plusieurs technologies.</b> Si vous n’avez pas un prérequis technique précis, optez pour un prestataire qui propose une raisonnablement large palette de technologies. Il sera probablement plus en mesure de vous conseiller les choix les plus pertinents pour votre projet, et éventuellement de vous donner des alternatives plus efficaces ou moins onéreuses.</p><p><b>Vos interlocuteurs offrent tous les services indispensables.</b> Que ce soit conseil en amont et service de support en aval, du design UX/UI ou de l’<a href="https://www.spiria.com/fr/services/developpement-axe-performance/assurance-qualite-test-automatises/">assurance qualité</a>, un développement logiciel réussi ne nécessite pas seulement un travail de développement pur et dur.</p><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2803/web-dev.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2803/web-dev.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2803/web-dev.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2803/web-dev.webp" style="width: 100%; border-style:solid; border-width:1px;" alt="Web development." title="Web development."></source></source></source></picture></p><p><b>Vos interlocuteurs offrent des méthodologies flexibles.</b> En cascade, Agile en saveur Scrum ou Kanban, mixte… il existe diverses méthodes pour conduire un projet logiciel. Le prestataire doit pouvoir vous proposer la méthode qui convient le mieux à votre projet, sa taille et ses objectifs, et ne pas vous enfermer dans un moule unique qui conviendrait à tous ses clients.</p><p><b>Vos interlocuteurs présentent des références crédibles.</b> Toute solide entreprise de développement montre sur son site web des exemples de réalisations. C’est une bonne manière de mesurer son expérience, la diversité ses projets et l’envergure de ses clients. Ne faites pas l’impasse sur une analyse approfondie du portfolio qu’ils présentent. Si vous avez un sérieux doute sur l’authenticité d’une référence, n’hésitez pas à vérifier, comme vous le feriez pour un candidat à l’embauche.</p><p><b>La compagnie de vos interlocuteurs est de taille comparable.</b> D’une manière générale, il vaut mieux être l’important client de votre prestataire pour avoir un traitement de choix. Si c’est une grosse multinationale et que vous êtes une entreprise modeste, il y a de sérieux risques qu’ils ne vous donnent pas toute l’attention requise. A contrario, si c’est une trop petite entreprise, elle n’est pas en mesure de vous offrir une palette complète de services et de vous accompagner dans votre croissance.</p><p><b>L’offre de vos interlocuteurs n’est pas au rabais.</b> En matière de développement, la politique du plus bas soumissionnaire n’est jamais conseillée. Lorsqu’il y a des écarts importants entre les soumissionnaires, c’est le plus souvent qu’au moins l’un d’entre eux n’a pas correctement compris les efforts de développement et/ou les défis techniques. N’hésitez pas à les questionner sur des points précis afin de tester la crédibilité de leur offre et de s’assurer qu’ils comprennent convenablement votre demande. Une proposition trop basse par rapport au marché est presque toujours la garantie d’un échec (objectifs de base non remplis, retards, dette technologique et pauvre qualité du code, etc.).</p><p><b>Vous avez envie de travailler avec vos interlocuteurs.</b> Oui, ça peut paraître un peu simple et idiot, mais cette affinité est une dimension essentielle, car le succès d’un projet logiciel, surtout s’il doit répondre à une problématique d’affaires complexe, repose sur une excellente collaboration tout au long du développement entre vous et votre fournisseur. Il faut donc que vous perceviez dès le départ si vous allez être capable de vous engager avec lui dans une coopération agréable et fructueuse. Pensez que vous allez être amené à travailler avec eux pendant plusieurs mois.</p>

Bonnes pratiques
5 min de lecture
Agile, un état d’esprit plus que des pratiques
<p>La première valeur du manifeste Agile est de privilégier les individus et leurs interactions plus que les processus et les outils. Dans les faits, ce sont le plus souvent les processus et des outils qui sont souverains.</p><p>L’Agilité est devenue un commerce, une industrie même, avec des entreprises spécialisées, des consultants, des vendeurs de logiciels, qui tous promettent monts et merveilles pour assurer leur propre bénéfice : adhère à notre méthode et ta productivité va augmenter considérablement. Et tout le monde de se dire Agile parce qu’ils utilisent les processus et les outils, la terminologie et les rituels. Il va sans dire qu’une pratique vidée de sa substance et de son esprit est nettement insuffisante.</p><blockquote style="text-align: center; font-size: 1.2em !important; font-style: italic;"><p>« Les individus et leurs interactions<br>plus que les processus et les outils. »</p></blockquote><p>Si nous vivons dans l’époque des « fausses nouvelles », nous sommes aussi, au niveau du développement logiciel, dans l’époque de la « fausse Agilité ». Avez-vous lu le Manifeste pour le développement Agile de logiciels ? Dans beaucoup d’équipes de développement, il y aura souvent bien peu de monde pour répondre positivement et encore moins sachant énoncer l’une des 4 valeurs ou l’un des 12 principes sous-jacents au Manifeste. Certaines entreprises s’annoncent Agile sans avoir le moindre rudiment de culture Agile. D’autres sont pleines de bonne volonté, mais s’enlisent dans le micromanagement et perdent de vue les objectifs ultimes. Elles n’ont pas au quotidien l’état d’esprit Agile. Certaines équipes sont lucides : « Oui, on pratique les sprints, les Daily. On met des points sur les Stories. On a un Scrum Master, qui est en fait un chef de projet. Ça ne va guère plus loin que ça. »</p><blockquote style="text-align: center; font-size: 1.2em; font-style: italic;"><p>« Notre plus haute priorité est de satisfaire le client<br>en livrant rapidement et régulièrement des fonctionnalités<br>à grande valeur ajoutée. »</p></blockquote><p>L’Agilité repose sur un état d’esprit qui se décrit en 4 valeurs et qui se définit dans 12 principes. C’est en quelque sorte une philosophie assortie de principes moraux. Elle se manifeste concrètement par un nombre infini de pratiques. L’Agilité n’est pas une boîte à outils comme XP où l’on pioche selon ses affinités. C’est une pensée globale qui préside aux pratiques. Ce sont des objectifs essentiels comme la satisfaction du client. Un client heureux n’a que faire que vous fassiez religieusement un stand-up de 15 minutes chaque jour. La question à se poser est : « Notre stand-up quotidien participe-t-il à l’atteinte de nos objectifs ? Est-il productif ou n’est-il qu’une perte de temps ? » Est-ce que l’équipe réfléchit aux moyens de devenir plus efficace, puis règle et modifie son comportement en conséquence (12<sup>e</sup> principe) ? Ou bien se contente-t-elle de suivre des rituels sans se poser de questions sur leur pertinence par rapport au projet et ne s’aventure-t-elle jamais à essayer de nouvelles manières de faire ? Est-ce que le Kanban ne serait pas plus approprié que des Sprints pour ce genre de projet ?</p><p>Voilà le genre de question qui exprime un vrai souci d’Agilité. Obéir aveuglément à des règles méthodologiques et des prescriptions n’est certainement pas démontrer que l’on sait s’adapter au changement plutôt que de suivre rigoureusement un plan (4<sup>e</sup> valeur du Manifeste, qui pourrait se résumer par le terme « pragmatisme »).</p><blockquote style="text-align: center; font-size: 1.2em; font-style: italic;"><p>« L’adaptation au changement<br>plus que le suivi d’un plan. »</p></blockquote><p>Faire rentrer les gens dans un moule, les faire se conformer à des pratiques sans questionnement plutôt que se concentrer sur le comment les gens pensent, interagissent et collaborent, ce n’est pas l’Agilité. Encore une fois, la première valeur du Manifeste et limpide, ce sont les individus et leurs interactions qui sont au cœur de la méthodologie, les outils et processus sont secondaires. Les seconds devant être toujours au service des premiers.</p><p>L’adaptation au changement est fondamentale à l’Agilité, c’est même l’origine de son nom et c’est ce qui est censé la rendre supérieure au cycle en cascade. Si les pratiques et outils sont constamment les mêmes, quels que soient les projets, leurs spécificités et envergures, ce n’est pas faire preuve d’adaptation, c’est faire preuve de rigidité. Plutôt que reproduire des méthodes qui ont fonctionné pour des équipes dans un certain contexte, il faut permettre à l’équipe de découvrir la méthode de travail qui fonctionne pour elle sur le problème sur lequel elle travaille. Ce qui revient à lui donner un certain degré de liberté par rapport à la norme. Le seul cadre à donner à la réflexion sur les pratiques est de toujours garder en vue l’ultime objectif, la plus haute priorité des principes du Manifeste : satisfaire le client, en livrant rapidement et régulièrement des fonctionnalités à grande valeur ajoutée. Et si sur un projet, la satisfaction du client n’est pas au rendez-vous, il y a lieu de s’interroger sur le bien-fondé des pratiques.</p><blockquote style="text-align: center; font-size: 1.2em; font-style: italic;"><p>« À intervalles réguliers, l’équipe réfléchit<br>aux moyens de devenir plus efficace,<br>puis règle et modifie son<br>comportement en conséquence. »</p></blockquote><p>Enfin, il faut que tous les membres d’une équipe Agile connaissent et comprennent le Manifeste Agile, qu’ils s’imprègnent de la philosophie. Il faut apprendre à le relire, à s’assurer de bien comprendre la finalité des préceptes et éventuellement discuter de certains points en équipes afin que tous puissent s’accorder sur une vision commune. Pensons que l’Agilité est avant tout une dynamique qu’il faut continuellement entretenir et réviser.</p>

Coin des développeurs
5 min de lecture
Construire une radio Web avec un Raspberry-PI
<div><p>Mélange de technologies passées et modernes, cette réalisation est née de l'achat, pour une poignée de dollars lors d'une journée vide-grenier, d'un superbe cabinet (entièrement vide) d’un poste de radio Emerson de 1933.</p><p>Ainsi, après quelques petits travaux de restoration, nous voila prêts pour l'installation d'un Raspberry-pi ultra-moderne !!</p><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200847.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200847.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200847.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2672/20151011_200847.jpg" alt="decorative"></source></source></source></picture></p><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200855.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200855.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200855.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2672/20151011_200855.jpg" alt="decorative"></source></source></source></picture></p><h2>1. La liste de courses</h2><ul> <li><a href="https://www.raspberrypi.org/products/model-a-plus/">Un rapsberry-PI model A+</a></li> <li>Une carte SD</li> <li>Un dongle WiFi USB</li> <li>Un interrupteur circulaire 12 positions</li> <li>Un potentiomètre 10K équipé d'un interrupteur</li> <li>Une alimentation 5V 500mA</li> <li>Un KIT Amplificateur basse fréquence</li></ul><h2>2. Le schéma</h2><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/radio_schamatic.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/radio_schamatic.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/radio_schamatic.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2672/radio_schamatic.webp" alt="decorative"></source></source></source></picture></p><p>La sortie audio du Raspberry-Pi est branchée sur l'entrée d'un petit amplificateur tolérant une alimentation de 3 à 16V et le réseau est transporté par un dongle WiFi.</p><p>On notera que :</p><ul> <li>L'amplicateur n'est pas branché directement au 5V (sous peine d'entendre du bruit issu du CPU). Un petit régulateur (<a href="https://www.fairchildsemi.com/datasheets/LM/LM7805.pdf">LM7805</a> ajusté à 4V) et un condensateur de 250uF en sortie permettront de filtrer proprement la ligne.</li> <li>Le potentiomètre (P2) permettant de régler le gain, est également équipé d'un interrupteur qui nous permettra de couper mécaniquement l'alimentation lorsque l'on tourne le bouton à son mimimum.</li> <li>"Ready Indicator" est une LED simplement branchée sur un GPIO qui nous servira pour indiquer si le réseau WiFI est disponible.</li> <li>L'interrupteur rotatif (P1) est branché sur 12 GPIOs qui ont la particularité d'être configurés par défaut en PULL-DOWN sur le Raspberry-PI.</li></ul><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/untitled.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/untitled.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/untitled.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2672/untitled.webp" alt="decorative"></source></source></source></picture></p><h2>3. Montage</h2><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200635.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200635.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200635.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2672/20151011_200635.jpg" alt="decorative"></source></source></source></picture></p><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200832.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200832.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2672/20151011_200832.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2672/20151011_200832.webp" alt="decorative"></source></source></source></picture></p><h2>4. Le logiciel</h2><h3>4.1 Installation de Raspbian (wheezy)</h3><p>Image disponible <a href="https://www.raspberrypi.org/downloads/raspbian/">ici</a>.</p><p>Instructions pour l'installation <a href="http://https://www.raspberrypi.org/documentation/installation/installing-images/">ici</a>.</p><p>Configuration du Wifi <a href="https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md">là</a>.</p><h3>4.2 Installation de mpc/mpc (webradio player)</h3><pre><code>sudo apt-get install mpd mpc</code></pre><p>la liste des commandes mpc est disponible via :</p><pre><code>mpc help</code></pre><p>plus d'info disponible ici : <a href="http://www.musicpd.org/doc/user/">http://www.musicpd.org/doc/user/</a></p><p>On notera en particulier :</p><p>Pour ajouter une webradio à la playlist :</p><pre><code>mpc add </code></pre><p>Exemples :</p><pre><code>mpc add http://www.radiofeeds.co.uk/bbcradio1.pls # BBCmpc add http:... # Radio Canada</code></pre><p>Pour ajouter un mp3 (apres l'avoir copié dans le bon répertoire de la carte SD) :</p><pre><code>mpc updatempc add </code></pre><h3>4.3 Réalisation d'un script pour la séléction de la station de radio</h3><p>Le principe consiste a réaliser un « deamon unix » qui sonde les gpios, afin d'associer les positions du bouton de sélection des stations (P1) à une position de lecture dans la playlist.</p><pre><code>#!/bin/sh### BEGIN INIT INFO# Provides: radio_ctl.sh# Required-Start:# Required-Stop:# Default-Start: S# Default-Stop:# Short-Description: Connect GPIO to mpc playlist# Description: Connect GPIO to mpc playlist### END INIT INFOdaemon_NAME="radio_ctl.sh"export PIDFILE=/tmp/radio_ctlPATH="/sbin:/bin:/usr/sbin:/usr/bin"#install#---------#sudo cp radio_ctl.sh /etc/init.d/. && sudo chmod a+x /etc/init.d/radio_ctl.sh#sudo update-rc.d radio_ctl.sh defaults#to uninstall#---------#sudo update-rc.d -f radio_ctl.sh remove. /lib/lsb/init-functionsd_start () { V=0 VOLD=0 echo 23 > /sys/class/gpio/export echo 24 > /sys/class/gpio/export echo 25 > /sys/class/gpio/export echo 12 > /sys/class/gpio/export echo 13 > /sys/class/gpio/export echo 26 > /sys/class/gpio/export echo 19 > /sys/class/gpio/export echo 21 > /sys/class/gpio/export echo 20 > /sys/class/gpio/export echo 22 > /sys/class/gpio/export echo 27 > /sys/class/gpio/export echo 17 > /sys/class/gpio/export while [ true ] do [ `cat /sys/class/gpio/gpio23/value` = "1" ] && V=1 [ `cat /sys/class/gpio/gpio24/value` = "1" ] && V=2 [ `cat /sys/class/gpio/gpio25/value` = "1" ] && V=3 [ `cat /sys/class/gpio/gpio12/value` = "1" ] && V=4 [ `cat /sys/class/gpio/gpio13/value` = "1" ] && V=5 [ `cat /sys/class/gpio/gpio26/value` = "1" ] && V=6 [ `cat /sys/class/gpio/gpio19/value` = "1" ] && V=7 [ `cat /sys/class/gpio/gpio21/value` = "1" ] && V=8 [ `cat /sys/class/gpio/gpio20/value` = "1" ] && V=9 [ `cat /sys/class/gpio/gpio22/value` = "1" ] && V=10 [ `cat /sys/class/gpio/gpio27/value` = "1" ] && V=11 [ `cat /sys/class/gpio/gpio17/value` = "1" ] && V=12 if [ $VOLD != $V ]; then VOLD=$V mpc play $V [ $V = 1 ] && echo "station 1" [ $V = 2 ] && echo "station 2" [ $V = 3 ] && echo "station 3" [ $V = 4 ] && echo "station 4" [ $V = 5 ] && echo "station 5" [ $V = 6 ] && echo "station 6" [ $V = 7 ] && echo "station 7" [ $V = 8 ] && echo "station 8" [ $V = 9 ] && echo "station 9" [ $V = 10 ] && echo "station 10" [ $V = 11 ] && echo "station 11" [ $V = 12 ] && echo "station 12" fi sleep 0.1 done}d_stop () { if [ -e $PIDFILE ]; then kill `cat $PIDFILE` rm -f $PIDFILE fi}case "$1" in start) if [ -e $PIDFILE ]; then log_daemon_msg "Daemon $daemon_NAME already running" log_end_msg $? else log_daemon_msg "Starting system $daemon_NAME Daemon" log_end_msg $? d_start & echo $! > $PIDFILE fi ;; stop) if [ -e $PIDFILE ]; then log_daemon_msg "Stopping system $daemon_NAME Daemon" log_end_msg $? d_stop fi ;; restart|reload|force-reload) d_stop d_start ;; force-stop) d_stop killall -q $daemon_NAME || true sleep 2 killall -q -9 $daemon_NAME || true ;; status) status_of_proc "$daemon_NAME" && exit 0 || exit $? ;; *) echo "Usage: /etc/init.d/$daemon_NAME {start|stop|force-stop|restart|reload|force-reload|status}" exit 1 ;;esacexit 0</code></pre><p>Mea-culpa : Ce script bash, n'est clairement pas des plus efficace (pooling aux 10ms des GPIO) mais il a le mérite d'être simple et d'avoir été écrit très rapidement.</p><h3>4.4 Réalisation d'un script pour allumer une LED lorsque le réseau WiFi est disponible</h3><pre><code>#!/bin/sh### BEGIN INIT INFO# Provides: wlan_led.sh# Required-Start:# Required-Stop:# Default-Start: S# Default-Stop:# Short-Description: led on if router answer to ping# Description: led on if router answer to ping### END INIT INFOdaemon_NAME="wlan_led.sh"export PIDFILE=/tmp/wlan_ledPATH="/sbin:/bin:/usr/sbin:/usr/bin"#install#---------#sudo cp wlan_led.sh /etc/init.d/. && sudo chmod a+x /etc/init.d/wlan_led.sh#sudo update-rc.d wlan_led.sh defaults#to uninstall#---------#sudo update-rc.d -f wlan_led.sh remove. /lib/lsb/init-functionsd_start () { echo 18 > /sys/class/gpio/export echo out > /sys/class/gpio/gpio18/direction while [ true ] do ping -t1 -w1 -c1 192.168.1.1 > /dev/null if [ $? = "0" ]; then echo 1 > /sys/class/gpio/gpio18/value else echo 0 > /sys/class/gpio/gpio18/value fi sleep 10 done}d_stop () { if [ -e $PIDFILE ]; then kill `cat $PIDFILE` rm -f $PIDFILE fi}case "$1" in start) if [ -e $PIDFILE ]; then log_daemon_msg "Daemon $daemon_NAME already running" log_end_msg $? else log_daemon_msg "Starting system $daemon_NAME Daemon" log_end_msg $? d_start & echo $! > $PIDFILE fi ;; stop) if [ -e $PIDFILE ]; then log_daemon_msg "Stopping system $daemon_NAME Daemon" log_end_msg $? d_stop fi ;; restart|reload|force-reload) d_stop d_start ;; force-stop) d_stop killall -q $daemon_NAME || true sleep 2 killall -q -9 $daemon_NAME || true ;; status) status_of_proc "$daemon_NAME" && exit 0 || exit $? ;; *) echo "Usage: /etc/init.d/$daemon_NAME {start|stop|force-stop|restart|reload|force-reload|status}" exit 1 ;;esacexit 0</code></pre><p>Là encore, un script Quick'n Dirty, qui allume une led lorsque le routeur Wifi (ici 192.168.1.1) réponds à un ping.</p><p>Le test est effectué toutes les 10 secondes.</p><h2>5 Conclusion</h2><p>Voici une courte vidéo qui montre le résultat.</p><div>

Dévelopement mobile
5 min de lecture
Comment livrer de la qualité ?
<div><h2>Architecture en équipe</h2><p>Notre équipe avait grandi rapidement. Nous devions apprendre la logique d’affaire du client et respecter des contraintes de temps. Dans ces circonstances, il fut facile d’accumuler une dette technologique. Avec le temps, on sentait que cela devenait un obstacle et que nous devions s'attaquer à ce problème avant qu’il ne devienne plus sérieux. Nous devions trouver un moyen pour coordonner plusieurs équipes pour les faire avancer dans une direction commune. C’est ainsi que débutèrent nos <em>architecture grooming</em>.</p><p>Cet atelier de travail se passe quelques jours avant le début d’un nouveau sprint. L’équipe de développeur se rassemble et regarde le contenu du prochain sprint en équipe. Chacune des <em>stories</em> sera lue et expliquée à l’équipe pour s’assurer qu’elle comprenne bien son objectif. Ensuite, l’équipe s’interroge sur les besoins architecturaux. Quels seront les défis techniques ? Quelle partie pourra être faite en une composante réutilisable ? Avons-nous le temps de retravailler le code pour effacer une dette technologique, et quelle solution pouvons-nous implémenter dans le temps disponible ? Une fois ces questions répondues, le travail à faire sera clair pour chaque membre de l’équipe. Les solutions techniques trouvées proviendront du savoir commun de l’équipe, ce qui donnera des solutions solides.</p><p>Pour que le travail soit bien coordonné entre les équipes, notre <em>Architecture Owner</em> participera à l’atelier de travail de chacune des équipes. Son rôle est de conseiller les équipes et de s’assurer que la vision architecturale du projet est respectée. Mais cela reste le rôle de l’équipe de trouver les solutions. L’<em>Architecture Owner</em> devra aussi faire le pont entre les équipes. Il devra communiquer et expliquer au besoin les solutions que les autres équipes mettront en place durant le prochain sprint.</p><p>Finalement, à la suite de la revue du sprint avec le <em>Product Owner</em>, nous faisons une revue architecturale. Le travail technique sera présenté à l’<em>Architecture Owner</em> et aux autres équipes. Nous présentons les composantes réutilisables qui ont été créées, les <em>patterns</em> qui ont été introduits et tous les autres renseignements techniques pertinents à transmettre.</p><p>Avec ces nouvelles <em>ceremonies</em>, l’équipe est plus consciente du travail architectural et des défis techniques du système; autant ceux qui ont été réalisés que ceux qui sont à venir.</p><h2>Assurance qualité par les pairs</h2><p>Il n’est jamais agréable qu’une <em>story</em> complétée soit rouverte par l’équipe d’assurance qualité, et nous trouvions problématique quand cela arrivait trop souvent. De plus la <em>story</em> rouverte pouvait dater d’un sprint précédent parce que l’équipe d’assurance qualité était débordée de travail jusque là. Notre solution à cette situation fut d’introduire l’assurance qualité par les pairs.</p><p>Quand un développeur a terminé sa <em>story</em>, que la revue de code a été acceptée et qu’il a fait les tests nécessaires, mais avant qu’il ne pousse ses changements dans le code source, il devra les donner à un autre développeur. Ce second développeur devra compiler les changements sur son poste. Cela évite que la compilation du code source ne soit brisée par les changements, que ce soit par un fichier qui ait été oublié d’être ajouté au code de développement, ou bien qu’une configuration du poste de développement ne soit pas conforme à celle de la machine de compilation. Une fois que la compilation a réussi, le second développeur teste la <em>story</em> pour s’assurer qu’il n’y a ni défectuosité ni oubli au niveau de la logique d’affaires. Quand le second développeur est satisfait, alors seulement la branche de développement pourra être versée au code source.</p><p>Avec cette étape supplémentaire, beaucoup des problèmes qui auraient été rendus visibles par la machine de compilation automatisée ou par l’équipe d’assurance qualité sont trouvés par le second développeur. Ces problèmes sont trouvés et réglés plus rapidement et la confiance de l’équipe face à une <em>story</em> terminée est accrue.</p><h2>Séance d’assurance qualité en équipe</h2><p>Il est difficile d’être satisfait, en tant qu’équipe, du travail livré lorsque la revue du sprint semble se transformer en séance de débogage. Mais une <em>story</em> livrée lors de la première semaine d’un sprint peut parfois être impactée par des modifications faites vers la fin de celui-ci. C’est pourquoi nous avons introduit les séances d’assurance qualité en équipe. </p><p>Nous avions débuté ces séances de travail à la veille d’une livraison, pour tester de façon intensive tout ce qui avait été fait comme travail. À chaque fois qu’on faisait une telle séance durant un sprint, le nombre de défectuosités ou de règles d’affaires non respectées était en hausse par rapport aux autres sprints. En introduisant cette séance à la fin de chaque sprint, à deux jours de la revue, nous pouvons bien voir le travail accompli et les problèmes qui auraient pu nous échapper durant le sprint. Le jour suivant, nous prenons le temps de faire les correctifs que l’on peut faire. Si un problème majeur a été trouvé dans une <em>story</em> et que l’équipe considère inacceptable de la livrer telle quelle, la <em>story</em> peut être sortie du code source et les correctifs devront être apportés en début du prochain sprint. Cela peut retarder sa livraison, mais nous nous assurons que la qualité y soit.</p><p>Cela permet à l’équipe de ne pas avoir de mauvaise surprise durant la revue et aussi de hausser la confiance face au travail qui a été exécuté. Une séance en équipe permet aussi une meilleure communication et compréhension de ce que les autres développeurs ont exécuté comme travail dans le sprint.</p><h2>Un processus lourd ?</h2><p>Nous considérons que chacune de nos équipes est composée de personnes raisonnables et qui ont assez de jugement pour savoir quand il est possible de sauter une étape. Notre méthodologie est un guide et non une structure rigide. Corriger une faute de syntaxe ne demande pas le même effort que de réécrire la logique du coeur du système. Nos équipes sont dévouées dans leur travail et elles ne veulent pas remettre à nos clients un livrable de mauvaise qualité. Donc nous conservons une flexibilité au niveau du processus. Un membre de l’équipe peut en tout temps ne pas faire une étape s’il juge qu’il est raisonnable de l'omettre. Ceci évite de ralentir le développement inutilement.</p><p>Malgré cela, depuis la mise en place de ces étapes dans notre méthodologie de travail, nous nous sommes interrogés sur le temps que cela implique. Est-ce un processus trop lourd et trop coûteux ?</p><p>Ce que nous avons constaté est que la vélocité de chacune des équipes s’en trouve affectée et que le travail prend un peu plus de temps. Par contre, la qualité s’en trouve grandement améliorée. La période de stabilisation qui se passe avant une livraison a été de beaucoup raccourcie et les équipes ont un plus grand niveau de confiance face aux livrables.</p><p>Après la livraison, le client trouve moins de défectuosités, et la gravité et l’impact de ces problèmes sont moindres, évitant de devoir faire des livraisons rapides pour des correctifs d’urgence.</p><p>Il est plus facile de prédire l’effort nécessaire à faire pendant le développement de la livraison. Nous réduisons la quantité de travail à faire pour la livraison et l'après-livraison. Une plus grande qualité de code rend le travail plus facile, facilitant le travail des équipes et l’évaluation des nouvelles fonctionnalités.</p><p>Au final, l’équipe et le client sont confiants face au livrable qui est remis. Aussi les évaluations sont plus près de la réalité et il y aura moins d’effort de maintenance après une livraison.</p>

Culture
5 min de lecture
Compter les sans-abri de Montréal
<div><p>C’est par un soir de printemps particulièrement agréable qu’une poignée de volontaires s’est réunie afin de participer à la seconde édition de Je Compte Montréal, exercice de dénombrement des sans-abri sur l’île de Montréal. L’activité organisée par le MMFIM, soit le Mouvement pour mettre fin à l’itinérance à Montréal, en était à sa seconde édition.</p><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2524/count-montreal-02.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2524/count-montreal-02.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2524/count-montreal-02.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2524/count-montreal-02.webp" alt="Équipe Spiria." title="Équipe Spiria."></source></source></source></picture></p><p>Le point de ralliement attribué à notre groupe était au 1440 de la rue Stanley, dans l’immeuble du YMCA Centre-ville. Une armée de bénévoles s’y activait à recevoir les autres bénévoles, chefs d’équipe et équipiers.</p><p>L’organisation avait tout prévu et c’est dans un désordre organisé que nous nous sommes réunis autour d’une table à imaginer comment notre groupe allions arpenter la zone qui nous avait été assignée. Notre objectif : répertorier toutes les personnes sans-abri se trouvant dans le quadrilatère délimité par les rues Mansfield, Sainte-Catherine, Jeanne-Mance et le boulevard René-Levesque, en plein centre-ville.</p><p>À première vue, cette tache nous apparaissait herculéenne et c’est avec nervosité et un peu d’appréhension que notre petit groupe se dirigea vers Jeanne-Mance, l’extrémité est de notre zone. La méthodologie de ratissage semblait au point. Nous allions partir du point le plus éloigné du YMCA et revenir en abordant les passants. L’art d’accoster des inconnus sur la rue n’est pas chose innée chez l’humain moyen et nous avons dû faire preuve de courage pour attaquer la tâche.</p><p>Mais qu’est-ce qu’un itinérant ? Est-ce que ce gars sur le banc avec son cellulaire et sa valise défraîchie en est un ? Ou cet autre qui nous regarde nerveusement du coin de l’œil et semble s’éloigner gentiment ? Ce couple qui s’embrasse sur le banc de parc avec sacs à dos et grosses bières — peut-être qu’ils sont en fugue… ou encore de simples touristes.</p><p>Nous devions arpenter les rues, ruelles, allées de la ville entre 20 et 23 heures, mais dès 19 heures, nous étions déjà assis à la place des Festivals à discuter de comment nous allions faire et à observer les passants.</p><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2524/count-montreal-02b.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2524/count-montreal-02b.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2524/count-montreal-02b.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2524/count-montreal-02b.webp" alt="Équipe Spiria." title="Équipe Spiria."></source></source></source></picture></p><p>C’est avec une certaine fébrilité et une énergie contagieuse que nous avons commencé les entretiens. Ce n’est pas facile d’aborder un itinérant — surtout que dans plus de la moitié des cas, il refuse de nous parler, se sauve ou nous demande de nous éloigner.</p><p>Nous devions leur remettre une carte cadeau de cinq dollars après avoir terminé l’entretien. Peut-être que nous aurions eu plus de chance si on leur avait fait miroiter une récompense en retour de quelques minutes de leur temps. Le questionnaire tenait sur trois feuilles, une vingtaine de questions, parfois avec sous questions dépendant de la réponse. Qu’elles soient en lien avec le lieu de résidence, la période sans logis ou les séjours en milieu hospitalier ou centre d’aide — chacune des questions devait avoir une réponse. Certaines questions demandaient une réponse entre plusieurs, d’autres permettaient de faire plusieurs choix. C’était un questionnaire difficile à utiliser et un support numérique comme une tablette aurait pu aider dans notre tâche. Les questions les plus difficiles à demander avaient trait au genre et à l’orientation sexuelle. Aucune question ne portait sur l’utilisation de drogues.</p><p>L’inconfort engendré par les rencontres avec des itinérants s’est rapidement transformé en énergie et c’est avec beaucoup d’entrain que le groupe de six Spiriens s’est souvent scindé en deux groupes — rarement composés des mêmes personnes — et s’est affairé à la tâche.</p><p>De retour à l’extrémité ouest de notre zone, nous avons décidé de refaire un tour de territoire, histoire de voir si la faune citadine avait changé. Quelle ne fut pas notre surprise en se rendant compte que les rues qui nous semblaient si confortables et sûres se sont métamorphosées en lieu de rencontre d’une foule urbaine d’un autre genre… et ce, dès la fermeture des magasins.</p><p>Autant les itinérants étaient d’une rareté à notre premier passage, nous étions dorénavant la minorité visible dans la soupe urbaine de Sainte-Catherine. Itinérants avec toutes leurs possessions dans un sac à dos, accompagnés de leur chien en laisse, exclus de la société en mal d’amour ou en quête d’un fix. L’atmosphère s’échauffait malgré la fraîcheur qui s’installait.</p><p>La soirée tirait à sa fin et c’est avec une fatigue bien sentie, les pieds douloureux, que nous avons décidé de mettre un terme à notre enquête. C’est à ce moment que j’ai appris que l’un de nous allait probablement dormir sur le plancher du bureau dans son sac de couchage… Ça m’a fait sourire, mais je sais que ce n’est pas une situation permanente.</p><p>Je tiens à remercier les personnes courageuses et sensibles qui ont décidé de m’accompagner dans l’aventure du dénombrement des sans-abri de Montréal, Isabelle, Guy, Jean, Stéphane et Cyril. Je tiens aussi à remercier Spiria qui aide et rend possible ce genre d’initiative.</p><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2524/count-montreal-03.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2524/count-montreal-03.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2524/count-montreal-03.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2524/count-montreal-03.webp" alt="Je compte MTL 2018." title="Je compte MTL 2018."></source></source></source></picture></p><h2>Pour conclure sur une note personnelle.</h2><p>Pour ma part, ce qui m’a le plus marqué en étant confronté à l’itinérance est la diversité des visages qu’on y retrouve, des vies trop souvent perturbées par la maladie mentale, une jeunesse troublée par un environnement toxique et les passages en foyer d’accueil, les effets pernicieux des moyens pris pour échapper à la douleur tant physique qu’émotive.</p><p>Bref, il semble ne pas y avoir qu’une cause à l’itinérance… chaque histoire est différente et une solution miracle pour remédier à toutes les itinérances est sans doute une utopie. Je perçois que les mouvements tels que celui qui nous a animés la semaine passée peuvent aider à mettre des visages sur le problème, tenter d’en cerner les traits, mais cela ne demeure qu’un outil pour prendre le pouls de la situation… Il reste à voir s’il y aura des actions concrètes qui en découleront.</p><p>Je ne pourrai plus, je crois, rester impassible face à la misère humaine causée par l’itinérance. Que faire, si ce n’est d’être parfois à l’écoute de l’autre… L’itinérant est un être humain, trop souvent amoché, qui tente souvent par des moyens du bord de trouver la paix.</p>

Stratégie
5 min de lecture
Les coûts des systèmes hérités
<div><h2>Des technos qui ne veulent pas mourir</h2><p>Aussi incroyable cela peut-il paraître, de grandes entreprises et institutions ont encore des programmes vitaux en COBOL qui tournent sur des ordinateurs centraux (mainframes). Les développeurs de ces programmes sont probablement déjà morts, le code spaghetti est peu ou pas documenté, mais ça fonctionne toujours. De vénérables responsables IT vous diront que ce sont des systèmes très sûrs, vous expliquant que ce sont souvent des ordinateurs peu exposés à l’internet et qu’aucun hacker ne connaît COBOL. Même si la sécurité par l’obscurité n’est pas reconnue comme la meilleure, on veut bien croire qu’il y a peu de pirates inspirés par le langage et les systèmes d’exploitation associés comme z/VSE, z/OS et VME. COBOL est en effet un langage de 1959 qui est en état de mort cérébrale depuis le bogue de l’an 2000. Les programmes sont monolithiques et ont des capacités d’évolution proches de zéro. C’est horriblement coûteux à maintenir et d’un avenir très incertain, ne serait-ce que parce que les bons programmeurs COBOL, qui sont parmi les mieux payés de tous les professionnels du développement, se font vieux et qu’il n’y a aucune relève (à ma connaissance, aucun jeune ne rêve de devenir coboliste et la discipline n’est de toute façon plus enseignée).</p><h2>Des systèmes antiques</h2><p>En juin 2015, le bureau de gestion du personnel fédéral américain (Office of Personnel Management) s’est vu voler des données touchant plus de 20 millions d’anciens et actuels employés sous contrat avec le gouvernement fédéral. L’enquête a révélé que le logiciel de l’ordinateur central qui héberge la base de données, vieux de 30 ans, était écrit en COBOL et qu’il était « techniquement trop obsolète pour chiffrer les renseignements personnels ». Comme quoi ces systèmes antiques posent bel et bien des problèmes de sécurité…</p><p>En 2016, on apprenait grâce au Government Accountability Office, organisme chargé du contrôle des comptes publics du budget fédéral des États-Unis, que l’un des plus vieux investissements fédéraux en IT encore en fonctionnement était le <i>Système automatisé de commandement et de contrôle stratégique</i> (SACCS) destiné à coordonner les fonctions opérationnelles des forces nucléaires. Ce système tourne encore sur des ordinateurs IBM <i>Series/1</i> des années 70 et le stockage se fait sur des disquettes 8 pouces.</p><p>En avril 2018, le site web des impôts fédéraux (IRS) est tombé en panne le dernier jour de déclaration des revenus. Le problème était que le fichier maître individuel (<i>Individual Master File</i>), le système qui stocke toutes les informations fiscales des citoyens, ne répondait plus aux requêtes. Ce système, composé de 20 millions de lignes de code assembleur, a été développé quand John F. Kennedy était président. Les autorités prévoient de le remplacer en 2022, après plus de 55 années de service, mais comme Donald Trump a amputé le budget de l’IRS de 239 millions de dollars, rien n’est moins sûr.</p><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2570/ibm-360.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2570/ibm-360.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2570/ibm-360.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2570/ibm-360.jpg" alt="IBM System/360." title="IBM System/360."></source></source></source></picture></p><p>Ordinateur central IBM System/360 au centre informatique des Jeux olympiques d’hiver de Grenoble, janvier 1968. Photo Ron Kroon/Anefo. Archives nationales néerlandaises.</p><h2>Les coûts des systèmes hérités</h2><p>Entretenir des systèmes de plus de 20 ans, voire de plus d’un demi-siècle, coûte de plus en plus cher. Les spécialistes de COBOL ou Fortran, les vétérans capables d’écrire en assembleur et les ingénieurs maîtrisant les vieux mainframes sont des gens de plus en plus rares, donc de plus en plus demandés et de plus en plus coûteux. La maintenance des plateformes matérielles, dont parfois le constructeur a disparu depuis longtemps, relève aussi du défi dont les solutions sont toujours onéreuses.</p><p>Ces systèmes sont généralement vitaux pour les entreprises (c’est ainsi souvent la raison pour laquelle ils sont maintenus coûte que coûte), et la moindre panne peut donc avoir des effets douloureux. Quand le vieux système informatique de gestion des réservations de la compagnie aérienne Delta a crashé en 2016, c’est toute sa flotte d’avion qui a été clouée au sol et ça lui a coûté plus de 150 millions de dollars. Des millions qui auraient sans doute mieux été investis dans la modernisation, la redondance et la sécurisation de son infrastructure. Une mésaventure du même genre s’était produite en 2004 chez Comair, une filiale de Delta. Le logiciel d’affectation des équipages, programmé en Fortran (alors que personne ne maîtrisait ce langage au service IT de Comair), s’était bloqué en raison d’une limitation inconnue de toute personne travaillant dans la compagnie. 3 900 vols durent être annulés et près de 200 000 passagers restèrent bloqués en pleine période de Noël. Le vieux logiciel était limité à 32 000 changements d’affectations par mois. Cette limite n’avait jusqu’alors jamais été atteinte, mais une tempête de neige historique les 22 et 23 décembre avait entraîné des modifications inhabituellement nombreuses. La limite atteinte, le logiciel s’est bloqué de lui-même le 25 décembre. Après ce ratage monumental, le président de Comair, Randy Rademacher, fut poussé à la démission en janvier. Le remplacement du système <i>legacy</i> par un logiciel de Sabre Airline Solutions avait été approuvé en 2003, mais fin 2004, il n’avait toujours pas eu lieu. C’était le dernier système qui fonctionnait encore sur l’ancienne plateforme IBM AIX de la compagnie aérienne (toutes les autres applications fonctionnaient sous HP Unix). Les conséquences négatives sur l’image de marque de l’entreprise furent importantes et durables.</p><p>Aussi, avec un système obsolète, la moindre modification fonctionnelle ou intégration avec un autre système plus moderne demande un temps exagéré, quand elle est possible, ce qui n’est pas toujours le cas. Ces systèmes sont souvent peu ou pas évolutifs, ce qui oblige d’y accoler d’autres couches technologiques pour répondre à la demande. Le résultat est alors en un système encore plus complexe et donc fragile. Il est en outre fréquent que ces systèmes aient des vulnérabilités en raison de technologies dépassées ou de manque de support.</p><p>Il faut également voir que tous les coûts ne sont pas directement inscrits dans la comptabilité. Comment chiffrer la perte de l’agilité, de la capacité de changer et de s’adapter à un contexte en perpétuel changement ? Comment évaluer le manque de compétitivité ? Que coûtent les données stratégiques qu’on ne peut pas obtenir parce que le système est incapable de les extraire ? Combien de points de croissance perdus ? De clients insatisfaits qui partent voir la concurrence ? Etc.</p><p>La plus grande partie du budget fédéral américain dédié aux technologies (80 milliards de dollars) est consacré au maintien de systèmes hérités. Les agences fédérales emploient encore plus de 1 000 développeurs en COBOL et 600 en Fortran. Quand une entreprise consacre 60 à 80 % de son budget IT dans la maintenance de systèmes hérités, elle le fait au détriment de l’innovation et du futur. Il reste en effet peu de temps et d’argent à faire autre chose que poser des rustines plutôt que de préparer l’avenir. Et on ne peut parler de modernisation quand on commence à bâtir un système de remplacement, ce qui est souvent une opération lourde et complexe, toujours longue. La modernisation effective ne se fait qu’au moment où l’on débranche le vieux système. Quand on ne peut consacrer que 20 % de son budget IT aux efforts de modernisation, cela prend encore plus de temps… Bref, avec des systèmes obsolètes, on s’enferme dans un cercle vicieux.</p><p>Souvent, la bonne décision est d’investir massivement pour pouvoir débrancher rapidement un système qui survit sous perfusion. En matière d’IT, même si cela fait un peu peur et que le risque zéro n’existe pas, il est parfois plus que temps de sortir la hache. Le retour sur investissement se fera inévitablement, au moins sur le moyen/long terme. D’autre part, il faut bien savoir que les systèmes modernes sont conçus avec un meilleur souci de l’évolutivité et sont plus modulaires, ce qui rendra plus facile et moins onéreux de les maintenir au goût du jour ou de leur faire effectuer une transition technologique.</p><p>—</p>

Coin des développeurs
5 min de lecture
Partage de données entre processus dans Windows : tube nommé et mémoire partagée
<div><p>Les données partagées sont un moyen de communication rapide entre les processus parent et enfant. Suivant la taille des données partagées, vous pouvez choisir le tube nommé (<i xml:lang="en" lang="en">named pipe</i>) ou la mémoire partagée nommée (<i xml:lang="en" lang="en">named shared memory</i>). Les exemples suivants illustrent les deux possibilités, et montrent comment utiliser les objets d’événement (<i xml:lang="en" lang="en">event objects</i>) pour synchroniser lecture et écriture de données entre les processus.</p> <p>Supposons le scénario où le processus parent envoie une quantité modeste de données au processus enfant, et que, partant de ces données, le processus enfant produit un grand bloc de données à renvoyer au processus parent.</p><h2>1. Pour partager une petite quantité de données : le tube nommé</h2><p>Le tube est une partie de la mémoire partagée que les processus utilisent pour communiquer. Le tube nommé, qui peut être à sens unique ou bidirectionnel (à deux voies), offre aux processus à la fois des services de lecture et d’écriture.</p> <p>Pour envoyer des données du processus parent au processus enfant, le parent crée le fichier de tube avec un nom, puis il écrit les données dans ce fichier. Pour recevoir ces données, le processus enfant ouvre le fichier tube en utilisant le même nom, et lit les données.</p><p>Mais à quel moment le processus enfant lit-il les données ? Nous pouvons utiliser les objets d’événement pour synchroniser la lecture et l’écriture entre les processus. Deux objets d’événement, <i>eventToChild</i> et <i>eventFromChild</i>, sont créés dans le processus parent. Ce dernier utilise <i>eventToChild</i> pour notifier le processus enfant que les données vont être envoyées, tandis que le processus enfant utilise <i>eventFromChild</i> pour informer le processus parent.</p><p>Voici le code pour le processus parent :</p><pre><code>char* pipeName =” \\\\.\\pipe\\”;char* eventToChildName = “event_to_child”;char* eventFromChildName = “event_from_child”;//Création, dénomination du tube nomméHandle namedPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX +FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_MESSAGE + PIPE_WAIT + PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, 100, 100, 100, nullptr);//Création de eventToChild, eventSecurity étant le pointeur//vers la structure SECURITY_ATTRIBUTES. Handle eventToChild = CreateEvent(&eventSecurity, false, false, eventToChildName );//Création du eventFromChild utilisé par le processus enfant//pour notifier le processus parentHandle eventFromChild = CreateEvent(&eventSecurity,false, false, eventFromChildName );//Notification du processus enfantif (!SetEvent(eventToChild)) return; //Écriture des données dans le tube nomméDWORD writtenSize;if (!WriteFile(namedPipe, data, sizeof(data), & writtenSize, nullptr) || writtenSize!= sizeof(data)) return; </code></pre> <p>Maintenant, voyons le processus enfant : il crée également un descripteur (<i>handle</i>) de tube nommé, “hPipe”, et ouvre <i>eventToChild</i> et <i>eventFromChild</i> sur la base des mêmes noms d’événements. Après avoir attendu le signal d’un <i>eventToChild</i> du processus parent, le processus enfant lit les données du fichier de tube nommé :</p><pre><code>//Attente d'événement en provenance du parentDWORD wait = WaitForSingleObject( eventToChild, INFINITE );if(wait != WAIT_OBJECT_0 ){ //Traitement de code d'erreur}//Lecture continue des données du tubebool res = false;while (1) { res = ReadFile( hPipe, lpBuffer, nNumberOfBytesToRead, & lpNumberOfBytesRead, nullptr) ; if( !res ) break; }</code></pre> <h2>2. Pour partager une grande quantité de données : la mémoire partagée nommée</h2><p>Après la lecture des données du tube nommé, supposons que le processus enfant génère en retour un grand bloc de données à partager avec le processus parent. Le meilleur moyen de gérer cela est de créer un objet de mappage de fichier, mapper l’objet fichier dans l’espace mémoire, informer le processus parent du descripteur de fichier mappé et de la taille des données, puis transférer les données dans la mémoire tampon mappée pour que le parent les lise. Le processus parent localise le secteur de mémoire en utilisant le descripteur de fichier mappé et la taille du tampon, qui sont écrits dans le tube nommé, pour lire directement les données dans la mémoire tampon mappée.</p><p>Voici le code pour le processus enfant :</p><pre><code>Handle hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, bufferSize, nullptr); if ( hMapFile == nullptr) return; //Mappage du fichier en mémoire LPSTR mappedBuffer = (LPSTR) MapViewOfFile( hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0 );//Informer le parent pour qu'il reçoive le descripteur et la taille du tampon (!SetEvent( eventFromChild)) return;//Après notification, écrire les données dans le tube nomméDWORD buffer[2];buffer[0] = (DWORD)hMapFile;buffer[1] = bufferSize;if (WriteFile(hPipe, buffer, sizeof buffer, &written, NULL ) || ( written != sizeof buffer ) )) return;//Ici, nous pouvons attendre que le parent retourne un message //confirmant qu'il a été notifié et qu'il est prêt à lire les données//Vider le tamponmemcpy(destination, mappedBuffer, bufferSize);…</code></pre> <p>Autrement, après avoir reçu de l’enfant l’indicateur de fichier mappé “childhMapFile” et la taille du tampon, le processus parent peut utiliser la fonction “DuplicateHandle()” pour dupliquer le descripteur “hMapFile”, et alors mapper le fichier dans la mémoire du processus courant. Voici le code :</p><pre><code>if ( DuplicateHandle( childProcess, childhMapFile, currentProcess, & hMapFile, 0, false, DUPLICATE_SAME_ACCESS ) ) // map the file into our process memory LPSTR hMappedBuffer = (LPSTR) MapViewOfFile( hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);}</code></pre> <h2>3. Conclusion</h2><p>Les données partagées sont pour les processus l’une des façons de communiquer. Le tube nommé et la mémoire partagée sont utilisés dans différentes circonstances. Les deux processus accèdent au même tube nommé par son nom, et à la mémoire partagée par le descripteur de fichier mappé. L’utilisation appropriée des objets d’événements et de fonctions d’attente pour contrôler les moments de lecture et d’écriture des données, assureront la synchronisation des processus.</p>

Coin des développeurs
5 min de lecture
Développer pour HoloLens de Microsoft
<div class="videoWrapper"><iframe src="https://www.youtube-nocookie.com/embed/1W4JeEPe_fQ?rel=0&showinfo=0" width="300" height="150" allowfullscreen="allowfullscreen"></iframe></div> <p>Le choix de Microsoft de faire équipe avec Unity a vraiment beaucoup simplifié la vie des développeurs sur Hololens. Si vous avez déjà quelques connaissances de Unity, vous pouvez progresser très rapidement.</p> <p>Il y a cependant quelques surprises pour les non-initiés aux applications de réalité augmentée ou virtuelle. Nombre des obstacles que nous avons surmontés lors de la création de cette démo étaient liés à l’interface utilisateur. Elle nécessite en effet une approche très différente de celle des applications Unity traditionnelles.</p> <p>Grâce à la nature multiplateforme de Unity, la plupart des autres fonctionnalités, comme la physique, l’animation et l’éclairage, ne nécessitent pas de modifications spécifiques pour Hololens</p> <p>Il y a quelques étapes à passer pour avoir vraiment votre application Unity sur le périphérique Hololens : exporter la solution Visual Studio à partir de Unity, compiler la solution Visual Studio et déployer l’application résultante vers l’émulateur ou le périphérique physique.</p> <p>Pour itérer rapidement lors du développement, nous avons créé une deuxième scène où nous avons utilisé un contrôleur de jeu à la première personne (<em>first-person controller</em>), un environnement de base avec des plans pour simuler une pièce, et un script d’entrée différent pour remplacer la fonctionnalité de regard (<em>gaze functionality</em>) qui n’est disponible que sur l’émulateur ou les lunettes Hololens.</p> <div> <div> <p><picture><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_debug_scene_2.400x0.webp" type="image/webp" media="(max-width: 599px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_debug_scene_2.760x0.webp" type="image/webp" media="(max-width: 999px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_debug_scene_2.1039x0.webp" type="image/webp" media="(min-width: 1000px)" /><img src="https://mirror.spiria.com/site/assets/files/2401/hl_debug_scene_2.webp" alt="decorative" /></picture><br /><em>Environnement simple</em></p> </div> <div> <p><picture><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_debug_scene.400x0.webp" type="image/webp" media="(max-width: 599px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_debug_scene.760x0.webp" type="image/webp" media="(max-width: 999px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_debug_scene.1039x0.webp" type="image/webp" media="(min-width: 1000px)" /><img src="https://mirror.spiria.com/site/assets/files/2401/hl_debug_scene.webp" alt="decorative" /></picture><br /><em>Vue rapprochée du cerveau</em></p> </div> </div> <h2>Problèmes d’interface utilisateur</h2> <h3>Le réticule, ou pointeur</h3> <p>Microsoft fournit d’excellents tutoriels pour débuter sur Hololens. Dans le “<a href="https://developer.microsoft.com/en-us/windows/holographic/holograms_101">tutoriel 101</a>”, des scripts sont par exemple fournis pour utiliser un pointeur spécial en forme de cylindre, pointeur qui s’oriente de façon perpendiculaire à la surface visée par l’utilisateur.</p> <p>Cela pourrait être utile pour certains types d’application, mais pour nos besoins, nous voulions un plus traditionnel curseur en superposition (overlay), qui reste fixe au centre de l’écran.</p> <div> <div> <p><picture><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_reticle.400x0.webp" type="image/webp" media="(max-width: 599px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_reticle.760x0.webp" type="image/webp" media="(max-width: 999px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_reticle.1039x0.webp" type="image/webp" media="(min-width: 1000px)" /><img src="https://mirror.spiria.com/site/assets/files/2401/hl_reticle.webp" alt="decorative" /></picture><br /><em>Pointeur dynamique</em></p> </div> <div> <p><picture><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_fixed_cursor_0.400x0.webp" type="image/webp" media="(max-width: 599px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_fixed_cursor_0.760x0.webp" type="image/webp" media="(max-width: 999px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_fixed_cursor_0.1039x0.webp" type="image/webp" media="(min-width: 1000px)" /><img src="https://mirror.spiria.com/site/assets/files/2401/hl_fixed_cursor_0.webp" alt="decorative" /></picture><br /><em>Pointeur fixe</em></p> </div> </div> <p>Bon, vous penseriez que ce n’est pas bien grave : “Utilisons une image d’interface Unity en mode superposition”. Malheureusement, on se rend vite compte que cet élément d’interface Unity en superposition n’apparaît tout simplement pas sur le périphérique.</p> <p>La deuxième tentative fut de placer un disque faisant face à l’utilisateur. Le disque était ajouté en tant que <em>game object</em> enfant de la caméra, de sorte qu’il reste toujours en face de l’utilisateur, peu importe où ce dernier regarde.</p> <p>C’est là que nous avons heurté ce qui est une fondamentale différence propre aux applications de réalité virtuelle et augmentée. L’effet visuel de cette solution est très inconfortable pour l’utilisateur. Imaginez une pièce de monnaie à une vingtaine de centimètres de vos yeux, et gardez la mise au point sur la pièce tout en regardant l’arrière-plan… Ça ne marche pas. Vous avez besoin que le disque soit assez éloigné pour éviter ce désagréable effet.</p> <p>L’étape suivante fut de déplacer le disque vers la position du RaycastHit. Le problème était alors que le disque rapetisse. La solution était donc d’éloigner suffisamment le disque et de mettre à l’échelle le disque en fonction de sa distance de la caméra, afin de conserver la taille perçue comme étant constante.</p> <pre><code>var headPosition = Camera.main.transform.position;var gazeDirection = Camera.main.transform.forward;RaycastHit hitInfo;if (Physics.Raycast(headPosition, gazeDirection, out hitInfo)){ Vector3 hitRay = hitInfo.point - headPosition; Vector3 headOffset = gazeDirection * distanceToObject; if (headOffset.sqrMagnitude > hitRay.sqrMagnitude) { headOffset = hitRay; } transform.position = headPosition + headOffset; float rayLength = headOffset.magnitude; transform.localScale = new Vector3(rayLength, rayLength, rayLength);}</code></pre> <h3>Bulles de texte</h3> <p>Le problème que nous avons ensuite rencontré était l’affichage de bulles de texte. Nous avons utilisé la même stratégie que pour le disque, car cela aurait été visuellement inconfortable d’avoir le texte en superposition directement en face de la caméra. Nous avons utilisé les coordonnées-monde pour les panneaux de l’interface utilisateur et le texte. La seule particularité est qu’ils ont un script qui met en œuvre un comportement d’affichage qui maintient ces objets (<em>game objects</em>) face à l’utilisateur en permanence.</p> <p>Ces bulles d’info pointent sur des régions du cerveau. Un simple <em>ramp object</em> du paquet standard <em>prototype</em> a été mis à l’échelle, aplati et positionné à 90 degrés près des panneaux de texte pour créer un effet de flèche. L’origine du <em>game object</em> contenant la flèche et le panneau de texte est placée à l’extrémité pointue ; cet objet est ensuite simplement déplacé vers la partie de cerveau correspondante avec un script.</p> <div> <div> <p><picture><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_info_bubble.400x0.webp" type="image/webp" media="(max-width: 599px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_info_bubble.760x0.webp" type="image/webp" media="(max-width: 999px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_info_bubble.1039x0.webp" type="image/webp" media="(min-width: 1000px)" /><img src="https://mirror.spiria.com/site/assets/files/2401/hl_info_bubble.webp" alt="decorative" /></picture><br /><em>Bulle de texte</em></p> </div> </div> <h3>Boutons</h3> <p>Nous avons trouvé une autre limitation avec le bouton d’interaction, qui est pourtant très facile à réaliser dans Unity. En fin de compte, nous avons dû gérer nos propres <em>focus events</em> pour changer l’état du bouton quand l’utilisateur le regarde. Microsoft fournit un script d’interaction Unity pour l’interface utilisateur <a href="http://forum.unity3d.com/threads/unity-ui-on-the-hololens.394629/">ici</a> ; il peut avoir son utilité si vous avez besoin de barres de défilement ou de curseurs dans votre application.</p> <p>Ainsi, l’interface utilisateur pour les applications virtuelles nécessite une approche bien différente, et après avoir lu un peu à ce sujet, je crois qu’il reste encore de nombreuses bonnes pratiques à découvrir dans ce domaine. Designers UX, vous avez tout un nouveau terrain à conquérir !</p> <h2>Rendu</h2> <p>Ensuite, discutons brièvement de l’ajout de transparence au modèle. Le problème ici est que le mode de transparence du <em>shader</em> tout usage (<em>standard shader</em>) de Unity cause des artefacts étranges sur Hololens. Cela est provoqué par les objets du cerveau qui se chevauchent au niveau de la profondeur. Voici le script de changement de mode de la transparence du <em>shader</em> général que j’avais essayé qui s’affichait correctement sur le PC de bureau.</p> <pre><code>private void EnableFadeMode(Material material){ material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); material.SetInt("_ZWrite", 0); material.DisableKeyword("_ALPHATEST_ON"); material.EnableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.renderQueue = 3000;}</code></pre> <p>Nous avons fini par utiliser l’ancien <em>shader</em> de transparence de <em>Unity</em> que nous avons ajouté au <em>package</em> de l’application. Les réglages de Unity pour faire ça sont bien cachés. Vous devez aller à <em>Edit -> Project Settings -> Graphics -> Always Included Shaders</em>. Lorsque des parties du cerveau s’estompent, on passe dynamiquement chaque matériau de son <em>shader</em> initial au <em>shader</em> de transparence.</p> <div> <div> <p><picture><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_standard_shader.400x0.webp" type="image/webp" media="(max-width: 599px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_standard_shader.760x0.webp" type="image/webp" media="(max-width: 999px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_standard_shader.1039x0.webp" type="image/webp" media="(min-width: 1000px)" /><img src="https://mirror.spiria.com/site/assets/files/2401/hl_standard_shader.webp" alt="decorative" /></picture><br /><em>Shader tout usage</em></p> </div> <div> <p><picture><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_legacy_shader.400x0.webp" type="image/webp" media="(max-width: 599px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_legacy_shader.760x0.webp" type="image/webp" media="(max-width: 999px)" /><source srcset="https://mirror.spiria.com/site/assets/files/2401/hl_legacy_shader.1039x0.webp" type="image/webp" media="(min-width: 1000px)" /><img src="https://mirror.spiria.com/site/assets/files/2401/hl_legacy_shader.webp" alt="decorative" /></picture><br /><em>Ancien shader</em></p> </div> </div> <h2>Performance</h2> <p>La performance est l’autre chose avec laquelle nous avons lutté. Le modèle du cerveau que nous avons utilisé, qui peut être divisé en plusieurs parties, a un maillage très détaillé. Nous avons quelque peu atténué ce problème en effectuant une première passe de réduction automatique de maillage (<em>automatic mesh reduction</em>). Nous n’avions pas le temps de refaire entièrement la topologie des objets, de sorte que ça nous laisse quelques heurts lors du déplacement autour du modèle de cerveau. Ce n’est pas qu’Hololens soit trop mollasson, mais ses capacités n’atteignent pas le niveau des cartes graphiques de PC de bureau.</p> <h2>Commandes vocales</h2> <p>C’est une caractéristique de la démo qui a été aisée à mettre en œuvre; tout fonctionnait sans surprise. En utilisant le script fourni dans le “<a href="https://developer.microsoft.com/en-us/windows/holographic/holograms_101">tutoriel 101</a>”, il suffit d’écrire la version texte de la commande et d’ajouter un <em>handler</em>.</p> <h2>Outils Unity et Visual Studio</h2> <p>Voici quelques solutions de contournement pour les quelques erreurs que nous avons rencontré dans Visual Studio :</p> <ol> <li>Il fallait relancer périodiquement Visual Studio pour prévenir l’erreur de déploiement <a href="http://stackoverflow.com/questions/36384375/dep0001-unexpected-error-1988945906-while-deploying-windows-uwp-app-to-phone">DEP0001</a>.</li> <li>Erreur de l’outil SerializationWeaver. Assurez-vous que le nom de votre projet Unity <a href="http://forums.hololens.com/discussion/874/solved-sudden-trouble-building-app-metafile-first-pass-dll-missing">ne contient pas d’espaces</a>.</li> </ol> <p>Aussi, avant de faire vos tests sur l’émulateur ou l’appareil HoloLens, assurez-vous de bien reproduire les configurations présentées dans le “<a href="https://developer.microsoft.com/en-us/windows/holographic/holograms_100">tutoriel 100</a>”. Certaines étapes sont omises dans le “<a href="https://developer.microsoft.com/en-us/windows/holographic/holograms_101">tutoriel 101</a>”. Ayant mal configuré un nouveau projet, nous avons été déçus de voir que notre application n’était pas lancée en mode plein écran.</p> <h2>Liens</h2> <p>Quelques liens d’intérêt :</p> <ul> <li><a href="http://www.gdcvault.com/play/1023652/Building-3-Dimensional-UI-for">Building 3-Dimensional UI for VR</a>.</li> <li><a href="https://www.packtpub.com/game-development/unity-virtual-reality-projects">Unity Virtual Reality Projects</a>.</li> </ul> <h2>Conclusion</h2> <p>J’espère que ces petits conseils vous aideront à outrepasser les quelques obstacles dans l’accès à cette technologie fascinante que Microsoft a mis à notre disposition.</p> <p>Bon codage!</p>

Bonnes pratiques
5 min de lecture
Méthodologies de design et de développement de logiciels réglementés
<div><p>Il en a résulté la nécessité de réglementer le développement de logiciels dans de nombreux domaines, tels que la médecine, l’énergie et la sécurité. Ces régulations ont tendance à être lentes à se faire et sont créées en réaction aux avancées technologiques. Contrairement à l’environnement réglementaire, les méthodologies de développement évoluent rapidement. Alors, comment pouvons-nous nous assurer que nous utilisons les meilleures méthodologies de développement logiciel, tout en créant un produit qui peut répondre aux exigences réglementaires ? Comment pouvons-nous imaginer une approche qui réponde avec efficacité aux lents changements de la réglementation et qui capitalise sur l’évolution rapide de la méthodologie de développement logiciel ?</p><h2>L’interaction entre les développeurs de logiciels et les organismes de réglementation</h2><p>L’objectif de la réglementation du développement logiciel est d’assurer la meilleure qualité possible du produit final tout en protégeant les utilisateurs. Pour ce faire, on établit des lignes directrices pour l’ensemble du processus de développement du produit — besoins, planification, conception, design, tests/vérifications et maintenance. Les règlements relatifs aux étapes de l’expression des besoins et du design aident l’organisme de réglementation à déterminer l’utilisation du produit et la meilleure façon de le tester. Ces étapes du développement entraînent la production de spécifications détaillées du produit. À partir de ces documents, les organismes de réglementation sont en mesure de déterminer les normes que le système doit respecter. Il en résulte généralement un processus de va-et-vient entre la partie chargée du développement et l’organisme de réglementation. Les étapes de tests et de vérifications comprennent des lignes directrices strictes. Cela permet aux organismes de réglementation de mieux s’assurer que votre système fonctionne comme décrit et qu’il répond aux exigences spécifiques. La dernière phase de la réglementation est la maintenance et la distribution du code — y compris la résolution de problèmes et la garantie d’une qualité constante. Bien que le code dans son ensemble ou les bibliothèques utilisées sont examinés, il y a beaucoup moins de lignes directrices associées à la façon dont le code devrait être écrit. C’est là que les développeurs doivent s’assurer que leur code est robuste, sécurisé et maintenable. </p><h2>Définir et comparer deux méthodologies pour le développement de logiciels</h2><p>Il y a deux méthodologies logicielles largement admises, en cascade et Agile, qui seront discutées dans ce billet de blogue. Chacune ayant ses propres avantages et inconvénients pour le développement de logiciels soumis à réglementation. </p><p>La <b>cascade</b> est une approche méthodique pour le développement de produits. Le modèle linéaire de cette méthodologie de développement logiciel permet une compréhension aisée des étapes. Dans la cascade, une fois que chaque tâche est achevée, l’étape suivante est amorcée. La première étape est la collecte des besoins, suivie du design, de la mise en œuvre, de la vérification et, enfin, de la maintenance. Pour des projets hautement définis et des besoins stables, la méthode en cascade est une excellente méthodologie de développement logiciel. Mais le format rigide de la méthodologie augmente le coût et allonge souvent le temps de développement — surtout dans les étapes ultérieures du cycle de développement du produit.</p><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-01.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-01.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-01.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-01.webp" alt="Méthode en cascade." title="Méthode en cascade."></source></source></source></picture></p><p>Comme d’autres méthodologies, celle-ci est assortie de certains compromis lorsqu’elle est utilisée pour élaborer des produits réglementés. La cascade répond aux exigences strictes en matière de documentation afin de s’assurer que le logiciel est conforme à la norme réglementaire. Dans une méthodologie en cascade pure, toute la documentation doit être créée et validée avant de passer à l’étape suivante. Bien que cette rigidité s’aligne sur celle de nombreux organismes de réglementation, elle n’a pas la souplesse nécessaire pour s’adapter rapidement aux changements. Posez-vous la question suivante : combien de fois un produit évolue-t-il entre le début et la fin de la production ? Cette approche linéaire du développement rend peu aisé l’ajout d’une caractéristique ou la modification de la portée d’un produit ou d’un projet. De nombreuses déviations par rapport à la direction originale coûtent du temps et de l’argent, car elles obligent les développeurs à revenir à l’étape des besoins ou à faire des correctifs et des « hacks » pour atteindre les résultats souhaités. Et cela s’ajoute à la dette technique que peut avoir un projet. Cette approche peut également conduire à du « code spaghetti » ; une situation où le “flux” d’un programme est embrouillé et sinueux. Les développeurs expérimentés savent qu’en ayant à faire de nombreux changements pour un projet soumis à un cadre réglementaire, les changements incrémentaux peuvent causer « code spaghetti », et si les inconvénients générés sont hors de la portée ce billet de blogue, on dira quand même qu’il faut vraiment l’éviter.</p><p><b>Agile</b> se concentre sur le développement du logiciel par itérations qui sont de petits incréments de nouvelles fonctionnalités. Les avantages de ce type de développement sont qu’il segmente le code en différentes portions, créant ainsi une base de code plus nette. L’autre avantage des petits ajouts incrémentiels est que chaque caractéristique peut être testée indépendamment. Agile ne fonctionne généralement pas pour des équipes plus grandes ou celles habituées à la méthodologie en cascade. Elle est particulièrement utile pour les étapes ultérieures du développement ainsi que pour les projets axés sur l’interface utilisateur.</p><p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-02.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-02.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-02.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-02.webp" alt="Méthode Agile." title="Méthode Agile."></source></source></source></picture></p> <p>Contrairement à la cascade, Agile offre beaucoup de souplesse et permet d’échelonner le projet en sprints. Ce qui rend Agile unique est sa flexibilité, ce qui autorise une méthodologie plus adaptable et plus efficace, qui produit des tâches distinctes qui segmentent également le code. Le design est fait pour chaque fonction et chacune peut être étendue/modifiée à presque n’importe quel moment puisque cette méthodologie vous oblige à créer une séparation entre chaque fonctionnalité. Cela a le potentiel de réduire la dette technique d’un projet spécifique. En raison de l’itération rapide du développement Agile, une partie de la documentation peut être remise à la dernière phase. Examiner avant chaque sprint la documentation et s’assurer que chaque document est mis à jour peut consommer beaucoup de temps. </p><h2>Développement de méthodes mixtes</h2><p>La cascade soutient les équipes dans la mesure où elles n’ont pas à vérifier en permanence si leur produit répond aux besoins et aux normes, car elles sont en mesure d’évaluer la conformité de leur design dès le début du développement. Le contrepoids est la rigidité du processus qui le rend lent à s’adapter et à être modifié pour répondre aux demandes des clients, des marchés et aux changements technologiques.</p><p>De son côté, Agile donne aux équipes la flexibilité nécessaire pour effectuer des changements et des modifications en cours de route, mais exige que les équipes évaluent activement si chaque changement incrémental répond aux normes réglementaires. </p><p>Comment pouvons-nous répondre à l’exigence selon laquelle le développement doit être correctement documenté tout en utilisant une stratégie de développement souple et flexible ? Nous pouvons combiner les deux méthodologies pour minimiser les frais généraux et assurer les meilleures pratiques de codage. </p><h2>Méthodologie hybride</h2><p>La meilleure approche est de commencer par définir les objectifs commerciaux et les requis techniques à l’aide de la méthode en cascade. Une fois que les besoins et les objectifs sont définis de façon générale et qu’ils sont établis conformément à la réglementation, ils peuvent être découpés en composantes système de haut niveau. Une fois que nous avons un besoin de haut niveau et un design, nous pouvons utiliser la méthodologie Agile pour développer les fonctionnalités spécifiques au projet. À la fin du projet, nous revenons à la méthode en cascade pour vérifier l’ensemble du système. </p> <p><picture><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-03.400x0.webp" media="(max-width: 599px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-03.760x0.webp" media="(max-width: 999px)"><source type="image/webp" srcset="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-03.1039x0.webp" media="(min-width: 1000px)"><img src="https://mirror.spiria.com/site/assets/files/2309/dev-methods-fr-03.webp" alt="Méthode hybride cascade+Agile." title="Méthode hybride cascade+Agile."></source></source></source></picture></p> <p>Dans la phase de l’élaboration des besoins à haut niveau et du design, nous voulons déterminer l’objectif commercial que nous voulons atteindre et les éléments de haut niveau qui devront être conçus pour l’atteindre. Étant donné que les fonctions individuelles ne sont pas importantes pour les considérations réglementaires à ce stade, il n’est pas nécessaire de les définir parfaitement. L’organisation réglementaire peut vouloir s’assurer que vous utilisez les bons boulons, les bonnes bibliothèques et les bonnes pratiques de codage, mais ils ne se soucient pas vraiment de la façon dont vous écrivez une boucle, par exemple, ou les tenants et aboutissants de la façon dont le système se met à jour. C’est là que nous devrions utiliser le développement Agile, car il garantira la plus haute qualité de code. Et le résultat de l’étape précédente a dû nous générer un stock de tâches qui seront traitées à l’aide de la méthodologie Agile. Différentes caractéristiques peuvent être ajoutées ultérieurement, mais il est important de les garder dans le cadre du projet. Si vous concevez un avion autonome, vous ne pouvez pas facilement changer les fondations et réaliser un bateau autonome. C’est-à-dire que même la flexibilité de la méthode Agile doit être limitée pour assurer un développement réussi et opportun. Une fois le produit développé, nous pouvons revenir à un modèle plus linéaire pour compléter la phase de vérification. </p><p>En combinant deux méthodologies de développement, nous pouvons créer une approche pour développer des logiciels sur des marchés hautement réglementés tout en limitant les risques spécifiques. Ces risques sont le temps et/ou la dette technique. Cette méthodologie de développement combiné peut également être utilisée pour les domaines moins réglementés. Atténuer les risques, développer des systèmes robustes et assurer le développement futur sont des choses sur lesquelles toute équipe de développement devrait se concentrer. C’est particulièrement vrai lorsqu’on considère la direction de l’innovation technologique qui fait que tout est interconnecté. De bonnes pratiques nous permettront de nous sentir plus en sécurité et de développer des systèmes plus robustes. </p><h2>L’importance de la méthodologie logicielle dans le monde d’aujourd’hui</h2><p>Récemment, nous avons publié un <a href="https://www.spiria.com/fr/blogue/iot-m2m-systemes-embarques/la-revolution-des-donnees">autre billet</a> de blogue qui souligne l’impact des données dans notre vie de tous les jours, et dans quelle mesure elles doivent être partagées avec les yeux omniscients de Google, Facebook et d’autres. Et comme il y est indiqué, « Une solide sécurité est la responsabilité de chaque développeur de logiciels et de produits, et devrait être prioritaire ». Cette affirmation est vraie pour de nombreux types de projets, et pas seulement pour les marchés réglementés. </p>