Theodo

Développer avec vous des produits ingénieux & durables.

Bedrijfstype

Klein -of middelgroot bedrijf


Sector

IT-consulting/IT


Hoofdkantoor

48 boulevard des Batignolles, 75017, Paris

Nieuws (13)

  • Anders

    How user-centric product design helped me craft a great product from afar

    This summer, I had the unique opportunity to work on a project in Costa Rica. For the first time in my career, I found myself literally an ocean away from my users. This geographical distance presented new challenges and forced me to double my efforts to truly understand my customers. Despite the physical separation, it was crucial to stay connected and empathetic to their needs and experiences. I’m going to share the insights I gathered along the way and especially how Karen, one of my testers quickly became the core persona of my product. Enhancing User Experience : In today's competitive tech landscape, the user experience (UX) has become a critical differentiator for successful products. As a product manager, my goal is to create products that not only meet market needs but also deliver a seamless and delightful user experience. I had a lot of doubts regarding my project for a Costa Rican bank. I’ve never been there, and I can’t say I’m entirely familiar with Costa Rican culture. I had no idea what the uses for mobile or computer devices were, what was premium or not in people’s perceptions, whether my customers had easy access to the required documents, and so on. It was crucial to get all those answers in order to have higher user satisfaction, increased retention, and robust word-of-mouth referrals. On the other hand, I knew that a poor UX would most certainly result in user frustration, churn, and a tarnished brand reputation. Creating a good user experience begins with understanding your users' needs, preferences, and pain points. And for that, a few methods helped me gather and incorporating user feedback into my product design process, here are my favorites : User interviews : Conducting direct interviews and surveys allows you to gather qualitative insights into user behavior, motivations, and challenges. Open-ended questions can reveal deep insights that quantitative data alone might miss. Personally, I tend to speak a lot—and quickly—so being comfortable with silences was initially challenging. But I learned that letting users fill the silence often led to the most surprising insights. I remember asking, “How do you find this screen?” and then not saying anything after the customer responded, “Cool.” They soon jumped in with, “Though, I’m not sure I understand this...” — revealing that the screen was, in fact, far from “cool.” Interviews for instance helped me break a significant misconception I had: I assumed people would prefer using a computer for their administrative tasks. It turned out that most of my users actually preferred using their phones, even for complex forms, because it felt more convenient and immediate. Usability testing : I once conducted a peculiar test with Karen : she had to upload her ID in a digital form. Instead of opening her documents’ file on her phone, she went to her car and searched for her wallet (which she couldn’t find) in order to take a picture of it. Usability tests can expose assumptions, like users’ instinct to take new photos rather than uploading existing files, which I hadn’t considered. You’ll find fascinating to see other people use what you’ve been working on, you often fail to see what is intuitive or not when you’ve had your nose on prototypes for weeks. Analytics and user behavior data : Analyzing user behavior data helps identify patterns and trends in how users engage with your product. Tools like Google Analytics, Hotjar, can provide valuable insights into user interactions, drop-off points, and feature usage. Customer feedback : It's essential to have a system in place to collect, analyze, and act on this feedback promptly. Your customers often leave comments when something frustrates them. If you are working on an app, Theodo Apps created an amazing tool for you : Argos Chat 2.0 analyzes and compares user reviews on App Store and Google Play. Once I gathered a deep understanding of my users, my next step was to translate these insights into actionable design strategies. I couldn’t just do all the things the customers asked for and had to prioritize. ⚖️ To do this, I made a list of all the features identified for my product and sorted them based on the value they would deliver relative to the time and effort required. Features that provided the most immediate value to users were prioritized first, while lower-impact or “bonus” features were set aside for later. For instance, one of our stakeholders wanted us to develop a chatbot for assistance. However, we managed to convince them that this feature was over-engineered for our initial release. Through user interviews, we discovered that customers feel chatbots take too long to provide answers and rarely deliver the information they need. By using this evidence, we were able to focus on higher-value features that would better meet user expectations. Prioritization is just the beginning. It’s then vital to keep a user-centric attitude throughout the entire project, not just at the start. Here are my two key principles for creating a customer-centric product design : 💭 Empathy-driven design : I tried to put myself in my users' shoes : when writing specifications for the tech team, I always start by asking, ‘What would Karen do in that situation?’ and try to connect the features to the added value for her. Understanding their context, emotions, and goals can guide you in designing products that truly speaks to them. Empathy maps and user personas are useful tools to visualize and communicate user needs within your team. 🔁 Iterative design and prototyping : I adopted an iterative approach to design, in which we continuously test and refine our product based on user feedback. For instance, we had some doubts regarding the UI of the product, it’s hard to know what is or isn’t seen as “chic” or “premium” in someone’s perception. We ran some tests and showed screens to customers and collected their feedback. What we thought was ‘very demure, very mindful’ was perceived as ‘sad,’ so we incorporated more color and images in the final design. Rapid prototyping allows you to experiment with different design solutions and gather user input early and often. Users and colleagues usually love to be involved and to co-build the product. The risk of isolated product development This being said, if you’re thinking, “My boss won’t let me disturb his clients that much”, keep reading. One of the most critical mistakes product teams can make is developing a product in isolation. While the intent of the stakeholders might be to perfect the product before revealing it to the world—or the competition 😱, this approach can be detrimental to its success. When you design a product without user feedback, you risk creating something that might be technically brilliant but fails to meet the actual needs of your users. Without iterative testing and validation, you might end up investing significant time and resources into features that users don’t need or understand and won’t use (ever heard of the Google Cemetery ?). The best products are the result of continuous learning and adaptation. By involving users early, before the product is fully formed, you gain invaluable insights that can guide your decisions, and ultimately create a product that resonates deeply with your audience. This lean approach also mitigates the risk of a disastrous launch by ensuring that your product evolves in alignment with user expectations and needs. Here are some tips to convince your stakeholders to use your users : Highlight the risks of skipping user involvement Present customer-centric success stories (like Apple or Amazon) Propose low-Risk, low-cost experiments (like using internal testing or restricted pilot with NDA) Share Data-driven argument I’ve faced this challenge firsthand. My stakeholders were adamant about keeping our project secret, afraid that talking to users would tip off the competition. So, I had to find creative ways to gather insights. The trick we found was to leverage company employees. Knowing that my stakeholders were not the typical end users for our product, I asked them to put me in contact with the agent field. I interviewed bank agents who worked directly with customers every day. I also asked about their personal banking habits to get a broader sense of user expectations. This approach allowed us to gather meaningful feedback while keeping the project confidential. Conclusion My experience working on a project abroad highlighted the importance of staying connected to your users, like Karen, no matter the distance. Embracing a user-centric design approach isn’t just about data and feedback—it’s about respecting users’ realities and crafting solutions that feel natural to them. More importantly, user-centric product design isn’t just a phase but a continuous commitment. As product managers, we have a duty to champion empathy and iteration. At Theodo, we learn to always put our users at the heart of our design process, ensuring that the interactions they have with our products is positive and impactful. And you, what steps are you taking to make your designs more user-centered? Article rédigé par Mathilde Lecuyer

  • Anders

    Comment bêta-tester son produit pour assurer son adoption ?

    En octobre dernier, en tant que Lead PM pour Bpifrance, j’ai contribué à la mise en production d’un nouveau parcours visant à optimiser le temps des collaborateurs sur la banque en ligne. Concrètement, nous avons automatisé jusqu’à 6 étapes, permettant un gain de temps moyen de 1h15 par acte de gestion. Notre démarche : dérisquer l’adoption de notre produit en lançant un pilote auprès de 20 collaborateurs sur plusieurs mois. Un succès apparemment ? Pas du tout ! Après 7 mois et 12 actes de gestion validés sur notre plateforme, on reçoit un NO-GO des responsables qui prolongent le pilote de 3 mois. Grosse déception… On a cherché à comprendre d’où venaient nos erreurs ; pendant le cadrage ? Le déroulé ? La généralisation ? Réponse : les 3 mon capitaine ! On en a profité pour capitaliser sur nos apprentissages en identifiant des points de contrôles pour le futur. Ça commence par la mise en place du pilote : Optez pour un pilote à chaque mise en service de fonctionnalités ou de parcours qui génère des changements significatifs dans le quotidien des utilisateurs, Appliquez un pilote aux produits permettant de cibler spécifiquement les utilisateurs destinés à tester, et envisagez l'utilisation de "feature flags" d'un point de vue technique. Et dans quel but ? Pour tester en avant-première des parcours ou des fonctionnalités clés avant leur déploiement à grande échelle, Rassembler des retours d'utilisateurs afin de comprendre leurs préférences et les obstacles potentiels alimentera un ensemble d'améliorations potentielles. Obtenir le soutien de promoteurs qui convaincront les autres des avantages de la fonctionnalité.   1. Cadrage Notre première erreur a été de n’avoir défini que des objectifs quantitatifs sans repères temporels. En leur absence, il était difficile pour nous de mesurer la progression et l'efficacité du pilote au fil du temps, mais aussi d’être réactifs pour corriger des points bloquants pour les utilisateurs avant la généralisation. Avoir une durée limitée permet de faire un point d’étape et de se reposer les bonnes questions. Définir et valider des objectifs quantitatifs et qualitatifs avant le démarrage du pilote est essentiel. Dans notre cas, nous avions des signaux contradictoires : un objectif quantitatif atteint mais un NPS des collaborateurs négatif. Sauf que le NPS n’était pas identifié comme un de nos objectifs ce qui ne nous a pas alerté sur le risque d’adoption de notre parcours. Notre dernière erreur sur la phase de cadrage a été de ne pas suffisamment impliquer les managers d’équipes qui étaient pourtant décisionnaires. La clé c’est de valider au départ avec les décisionnaires des conditions qui permettront la généralisation du pilote. Comment ? Avec un Kick-Off au début du pilote pour valider le déroulé, et des points d’échanges dédiés pour partager les avancements et capter leurs préférences.   2. Déroulé La 2ème étape du processus implique de recueillir des retours pertinents pendant la durée du pilote afin d’améliorer le produit. L'un des points clés est de se rendre sur le terrain, profitant de toutes les occasions pour rencontrer les utilisateurs et observer leur interaction avec notre produit. Malheureusement, nous avions lancé des sessions d’interviews au début, et une fois l’objectif atteint mais jamais pendant le déroulé. Nous nous sommes retrouvés à la fin du pilote avec une montagne de retours à prendre en compte qui bloquait la généralisation. La disponibilité des collaborateurs et le quotidien des équipes produit vont par définition toujours vous pousser à déprioriser l’animation du pilote par rapport au reste. Nous recommandons donc de prévoir des points de passage dans les agendas dès le cadrage pour éviter cette situation. Lors des analyses qualitatives, nous n’avions pas creusé pourquoi nous avions un NPS négatif car le volume de répondant était tellement faible que nous pensions qu’il n’était pas représentatif. Mais si ces NPS sont là c’est justement pour capter les signaux faibles ! Si pas de répondants, c’est peut être que votre parcours n’est pas utilisé OU qu’il y a autre chose qui se cache. Il faut toujours définir plusieurs indicateurs de santé et interroger les répondants aux NPS qu’ils soient positifs ou négatifs. C’est grâce à cela que nous creusons les vrais sujets.   3. Généralisation Ce qui nous a manqué ici a été énoncé plus haut : la connaissance de nos décideurs et la validation des conditions qui permettent de généraliser en amont. Si toutes les étapes précédentes ont bien été réalisées, un sponsorship d’un décideur sera facilement atteignable. Pour clore une phase pilote, il est important pour les sponsors : de se projeter sur la suite en ayant une roadmap claire des évolutions à venir, d’avoir des résultats à communiquer, et surtout de voir le gain et la valeur qu’on apporte grâce à notre parcours. Un pilote permet aussi de valider les points clés à mettre en valeur pendant la généralisation et de préparer le go-to-market de notre fonctionnalité.   4. Résultats Nous avons retravaillé notre pilote et appliqué les points de contrôle ci-dessus. Après 3 mois d’améliorations, de co-construction et d’échanges avec les équipes et les parties prenantes ; nous avons mis en production 6 nouvelles fonctionnalités dont une qui a fait gagner 15 minutes de temps de traitement par acte aux collaborateurs, nous avons reçu beaucoup de retours positifs des décideurs, des collaborateurs et parties prenantes, nous sommes passés de 12 à 125 actes de gestion traités. Il nous reste encore beaucoup de choses à améliorer sur le produit pour atteindre une adoption généralisée, mais grâce à ce pilote nous savons désormais sur quoi concentrer nos efforts.   Grâce à ce REX, j’ai pu découvrir quelques pistes pour construire un bon pilote. Que ce soit en phase de cadrage, pendant le déroulé ou à la fin du pilote vous aurez remarqué que le dénominateur commun est l’écoute de vos utilisateurs mais aussi la validation au départ des conditions qui permettent de décider de la généralisation. Et après chaque écoute, partager ses insights pour déterminer ce que nous devons prioriser. Bon courage pour vos pilotes ! Articlé rédigé par Sixtine Legrand

  • Anders

    La méthode OKR, la solution miracle des PM pour prioriser ?

    En novembre dernier, mon équipe et moi nous sommes retrouvés face à un dilemme, alors que nous travaillions sur la roadmap de fin d’année : les deux objectifs de notre produit, hausse des comptes créés et hausse des rendez-vous pris, initialement alignés, s’opposaient alors frontalement. Il fallait choisir, mais nous n’arrivions pas à prioriser, car nous manquions d’éléments tangibles. Nous manquions d’un outil nous permettant de prioriser de façon rationnelle. Il nous fallait des objectifs chiffrés, court-termes. J’ai donc pris la décision de définir des OKR : Objectives Key Results. Je connaissais la méthode, mais la mettre en place ne fut pas si aisé. Dans ce retour d’expérience, je vous partagerai : Quelques conseils sur comment définir des OKR, Les raisons pour lesquelles je recommande cette méthode, Les limites de cette méthode pour mon cas d’usage précis. Contexte : Un site avec à la fois un espace connecté et déconnecté Je travaille sur le site bpifrance-creation.fr, site de référence en matière de création d’entreprises, qui dispose à la fois d’un espace déconnecté et d’un espace connecté : le Pass Créa. Sur l’espace déconnecté, les utilisateurs ont accès à des ressources sur l’entrepreneuriat, des outils et surtout la fonctionnalité Être Accompagné, une sorte de Doctolib des réseaux d’aide à l’entrepreneuriat, soit un système de mise en relation et de prise de rendez-vous avec des experts de la création d’entreprise. Se créer unPassCréa permet d’accéder à un espace sécurisé et gratuit, proposant un parcours de création personnalisé, un business plan en ligne, des modèles de pitch deck, un coffre-fort… Les objectifs du projet étaient les suivants : Augmenter le nombre de comptes Pass créa, Augmenter le nombre de rendez-vous pris via Être accompagné. Problème : Augmenter les comptes créés ou augmenter les rendez-vous pris, that is the question Pour la fin d’année, nous avions décidé d’insister sur la création de Pass, et de faire en sorte que la fonctionnalité Être Accompagné, qui est accessible à tous les utilisateurs, serve à convertir les utilisateurs. Avec ces indications, ma recommandation était la suivante : s’inspirer de Doctolib justement, et rendre la création de Pass obligatoire pour la prise de rendez-vous en ligne. Mais cette proposition amenait un risque : faire diminuer le nombre de rendez-vous pris. Dans ces conditions, nos deux objectifs entraient en contradiction. Comment trancher ? Contre-mesure : Définir des OKR pour aligner tout le monde et pouvoir prioriser plus facilement. Ce qui nous empêchait de trancher, c’est que les objectifs du Produit (Augmenter le nombre de rendez-vous pris via Être Accompagné, Augmenter le nombre de comptes créés) étaient trop lointains et non chiffrés. J’avais le sentiment que définir des objectifs produits chiffrés, avec un horizon de temps, allait créer une dynamique positive sur le projet et nous aiderait dans nos prises de décision quotidiennes. Si je sais que je dois augmenter de 20% les Pass créés et de 5% la prise de rendez-vous, alors la solution proposée est potentiellement crédible et je suis prêt à prendre le risque. Lorsque l’on est Product manager, il n’est pas toujours évident d’être sûr de la valeur de ce qu’on développe. Avoir des objectifs chiffrés, à court ou moyen terme, permet de s’assurer que tous les développements choisis vont dans ce sens. Si tel n'est pas le cas, il nous faut alors justifier notre décision, ce qui initie des discussions intéressantes. La méthode OKR permet justement de mettre les objectifs définis par l'entreprise au centre des équipes. Elle doit permettre de faire le lien entre des objectifs business macros, et des résultats clés, plus micros, qui facilitent la prise de décision au quotidien. Voici mon retour d’expérience sur la mise en place d’OKR : ETAPE 1 : Définir les objectifs business La première étape consiste à définir les objectifs business. On est parfois tellement concentré sur l’utilisateur qu’on en oublie la viabilité du produit. Il faut remettre le business au centre des préoccupations. Nous avons donc mis à plat les objectifs business définis par Bpifrance pour le site bpifrance-creation.fr, car même s’il est totalement gratuit et sert une mission d’intérêt général, ses performances peuvent tout de même être objectivées. Donc peu importe votre produit, pas d’excuse à ce niveau là. Concernant notre produit, les objectifs business sont les suivants : Augmenter la notoriété de Bpifrance Augmenter le nombre d’entrepreneurs accompagnés par des réseaux d’aide à l’entrepreneuriat afin d’augmenter la longévité des entreprises ETAPE 2 : Définir les objectifs produits La seconde étape consiste à définir les objectifs produits, c'est-à-dire les objectifs que doit atteindre le produit pour répondre aux objectifs business. Voici le résultat de notre réflexion : Augmenter la notoriété de Bpifrance    a) Augmenter le nombre de visites sur la partie déconnectée    b) Augmenter l’utilisation de la partie connectée (car plus ils sont engagés, plus ils se souviendront du soutien de Bpifrance) Augmenter le nombre d’entrepreneurs accompagnés par des réseaux d’aide à l’entrepreneuriat    a) Augmenter le nombre de rendez-vous pris Donc nous avons 3 objectifs produits : Augmenter le nombre de visites sur la partie déconnectée Augmenter l’utilisation de la partie connectée Augmenter le nombre de rendez-vous pris 💡 NB : On peut chiffrer ou non ses objectifs produits et business, la réponse varie selon les articles que j’ai pu trouver sur internet. Il me semble toutefois que dans une organisation idéale, tous les objectifs sont chiffrés. Cela va dépendre de votre maturité en termes de Data Management, car plus on a de chiffres plus il est difficile de tous les suivre. De notre côté nous avons fait le choix de ne pas les chiffrer pour notre première itération. ETAPE 3 : Définir les key results La dernière étape, c’est de définir les Key Results (les résultats clés), c’est-à-dire les sous-objectifs, chiffrés, qui une fois atteints vont permettre d’atteindre l’objectif produit. Cela demande une réflexion approfondie sur les différents leviers actionnables, ce qui dépend donc beaucoup du produit en lui-même. Par exemple : si l’objectif est d’augmenter le chiffre d'affaires d’un site e-commerce de 10% sur les 3 prochains mois, les résultats clés peuvent être d’augmenter la valeur moyenne du panier de 8%, et le nombre d’achat de 5%. Si les 2 résultats clefs sont atteints, l’objectif est atteint, et même dépassé. Choisir ses key results n’est pas facile car il y a autant de résultats clés possibles qu’il y a de leviers différents pour atteindre son objectif. Il n’y a pas de nombre de résultats clés obligatoires mais il ne vaut mieux pas dépasser 3 par objectifs. Par exemple : Pour augmenter le chiffre d’affaire d’un site e-commerce de 10%, on pourrait choisir d’augmenter à la fois : La valeur moyenne du panier Le nombre d’achats réalisés Le taux de conversion de la page de paiement Le nombre d’achat mensuel par compte utilisateur Comment choisir alors ? L’organisation de l’équipe Le site bpifrance-creation.fr est géré par différentes équipes appartenant à différentes directions. Définir les OKR du site était l’occasion de les aligner à un niveau plus opérationnel. Ainsi les équipes travaillent ensemble pour atteindre un objectif commun, tandis que chacune est responsabilisée en étant autonome pour atteindre son résultat clé. Ainsi, pour atteindre notre objectif de hausse du nombre de rendez-vous pris, nous avons défini un résultat clé sur le nombre de vue sur le formulaire (ie le flux entrant) et un résultat clé sur le taux de conversion du formulaire. L'équipe qui s’occupe de l’amont du formulaire a un objectif d’augmenter les redirections vers “Être accompagné” tandis que l’équipe qui s’occupe du formulaire a pour objectif d’améliorer son taux de conversion. De la même façon, si nous avions eu plusieurs équipes qui s’occupaient chacune d’une partie du formulaire, nous aurions fixé un résultat clé pour chaque partie. La meilleure opportunité de croissance Si l’objectif est d’augmenter le nombre de rendez-vous pris sur le site, on peut agir sur le nombre de prospects entrant dans le formulaire de prise de rendez-vous, sur le taux de conversion du formulaire, ou sur le taux de conversion de la page de prise de rendez-vous. Si le taux de conversion du formulaire est de 90% et celui de la page de prise de rendez-vous de 50%, alors on peut faire le choix que pour la période à venir, le résultat clé soit d’atteindre un taux de conversion de la page de prise de rendez-vous de 70%. Le trimestre suivant, on pourra changer de Résultat clé, car on aura suffisamment progressé sur la page de prise de rendez-vous. 💡 Le choix des Résultats clés est une étape importante de la mise en place des OKR. Ils vont influer grandement sur la roadmap des mois à venir. C’est au Product Manager de les choisir en fonction de ses convictions et de l’organisation de l’équipe. ETAPE 4 : CHIFFRER Après avoir choisi les leviers sur lesquels nous souhaitions agir, nous avons chiffré les résultats clés. Il y a deux bénéfices à cela : Définir notre ambition : si je ne veux pas seulement augmenter de 10% le taux de conversion du formulaire, mais le doubler, cela va nécessiter un effort plus important et nécessitera de déprioriser d’autres développements Déclencher des discussions intéressantes : si une équipe n’atteint pas son résultat clé, ou à l’inverse si elle l’atteint mais que cela n’influe pas sur l’objectif, on peut en apprendre plus sur notre produit en discutant du choix du résultat clé, du chiffre fixé, de l’organisation de l’équipe etc. Dans la théorie des OKR, il faut fixer des objectifs et résultats clés ambitieux et être satisfait si on ne les atteint qu’à 70%. De notre côté, nous avons fait le choix de définir des résultats clés atteignables afin d’embarquer les équipes dans cette nouvelle méthode. Le résultat :   Mes apprentissages : Je recommande vivement la méthode OKR Définir des OKR a permis de déclencher des discussions très intéressantes sur les objectifs business et produits, et de prendre de la hauteur par rapport aux sujets opérationnels du quotidien. Maintenant que nous sommes alignés sur ces objectifs, à chaque nouvelle fonctionnalité que nous développons, nous nous alignons sur le résultat clé sur lequel elle influe. S’il n’y en a pas, alors c’est que cette fonctionnalité n’est pas prioritaire. Au quotidien, avoir un objectif chiffré à atteindre permet de garder l’équipe motivée, car elle constate l’avancée par rapport à l’objectif, et la précision des résultats clefs permet de voir un impact direct entre ses développements et le résultat clé. Attention toutefois, c’est un travail à recommencer régulièrement Les OKR sont un travail itératif. Il faut régulièrement se fixer de nouveaux résultats clefs, les grandes organisations techs le font de manière trimestrielle. Cela permet d’avoir des objectifs court-termes sur lesquels on a de la visibilité et de concentrer ses efforts (à la manière des sprints en méthode Scrum). De plus, on peut changer les résultats clés sur lesquels on se concentre en fonction de l’évolution de notre produit, ou des objectifs business. Par exemple, nous réfléchissions récemment à réaliser un développement, mais il n’influait sur aucun de nos résultats clés. Nous nous sommes alors rendus compte qu’il y avait eu une évolution sur les objectifs business qui rendait légitime ce nouveau développement. Nous allons donc retravailler sur nos OKR. 💡 Il ne faut donc pas avoir peur de se lancer ! C’est un travail vertueux qui permet de rediscuter de la raison d‘être de son produit. Conclusion Une fois que nous avons défini les OKR de bpifrance-creation.fr pour le premier trimestre 2024, sommes-nous en capacité de répondre avec assurance à la question suivante : ”Devrions-nous rendre la création de compte nécessaire à la prise de rendez-vous ?” Aujourd’hui non. Rendre obligatoire la création de compte pour prendre rendez-vous risque toujours de faire baisser le nombre de rendez-vous pris, d’une manière que je ne sais pas quantifier, or notre objectif reste de faire augmenter les deux. Pour répondre à cette question, il faut réfléchir à ce que cette tension entre nos deux objectifs indique de ces derniers. Sur Doctolib, la création de compte est obligatoire car elle garantit la sécurité des échanges d’informations personnelles et sert l’objectif principal qui est de digitaliser la relation entre l’utilisateur et le médecin. De plus, au moment où l’utilisateur doit créer son compte, il a déjà trouvé le médecin qu’il lui faut et l’horaire de son rendez-vous, il a donc déjà pris conscience de la valeur de ce que lui apporte Doctolib et est prêt à faire l’effort de créer son compte pour obtenir ce rendez-vous. Sur Youtube, la création d’un compte n’est pas obligatoire pour visionner des vidéos, car un utilisateur ne peut pas réaliser le plaisir que peut lui apporter les vidéos youtube s’il n’en a pas déjà visionné. Avoir un compte est donc un Nice to have pour l’utilisateur, elle va lui permettre d’accéder à des fonctionnalités plus avancées. La question de la création de compte est donc plus complexe à résoudre et n’est pas simplement une histoire d’objectifs chiffrés … A suivre ! Article rédigé parThibaut Geron

  • Anders

    La recette du Big Hack

    Et si vous pouviez commander un menu chez McDonald’s pour 1 centime ? Ou encore vous faire livrer la commande d’un autre utilisateur ? C’est ce qu’a réussi Eaton Zveare sur le site de McDonald’s Inde dans le cadre d’un programme de bug bounty. Ce type de programme, mis en place par certaines entreprises, récompense les chercheurs en cybersécurité qui découvrent et leur signalent des failles. Seule l’application utilisée dans la moitié sud-ouest de l’Inde était concernée par ces vulnérabilités, et, sauf preuve du contraire, il n’a jamais été possible de les exploiter en France. ⚙️ Un peu de contexte De nombreuses failles ont été découvertes, nous allons seulement en aborder une dans cette newsletter. Grâce à cette vulnérabilité, il était possible de changer le prix d’une commande avant de payer. Pour l’exploiter, le chercheur commence par ajouter plusieurs produits à son panier, pour un total de ₹5681 (~62€). Au moment de confirmer la commande et avant de passer au paiement, le navigateur envoie une requête "POST" sur la route "/order". Celle-ci contient tous les détails de la commande. Notamment, le montant total de la commande (dans le champ "amount"). Puisque le champ "amount" est présent dans la requête, le chercheur essaie de le modifier en rejouant l’appel à la route "POST /order". L’attaque échoue, parce que, sur cette route spécifique, un mécanisme de signature empêche la modification du payload. Cependant, une autre route attire l’attention du chercheur. La route "PUT /cart/:cartId" existe pour modifier l’entité “Cart” (le panier). C’est cette route qui est appelée lorsqu’un produit est ajouté au panier par exemple. Lorsque le navigateur appelle cette route, il reçoit une réponse du serveur avec le format suivant : Cette réponse semble inclure tous les champs de l’entité Cart, et on y retrouve certains champs qui étaient présents dans le payload de la requête, tels que la quantité des articles. Et, ici aussi, on retrouve le prix (gross_price). On peut donc supposer que ce champ fait partie de l’entité Cart également. Serait-il possible de le modifier lui aussi ? Le chercheur tente alors d’appeler cette route PUT en passant un prix de 1 rupee dans le champ "gross_price". Et contre toute attente, la requête fonctionne : Le chercheur réussit donc à payer et à valider sa commande (désormais de seulement 1 rupee, soit environ 0.11€). Étant un hacker éthique, il l’annule après ses tests. 🕵️ Explication de la faille Cette faille, appelée “Mass Assignment” survient souvent lorsqu’il y a un couplage entre les champs attendus pour une requête HTTP et les entités métiers (telles qu’elles sont stockées dans la base de données). Prenons l’exemple d’une application dans laquelle existe une entité “Order”. Imaginons que les développeurs ont prévu une fonctionnalité de mise à jour de la date de livraison. Dans la requête en question, seul le champ deliveryDate est normalement présent. Si les développeurs valident uniquement que l’utilisateur a le droit de modifier une commande, sans vérifier les champs qui ont effectivement été modifiés, on a un bon exemple de Mass Assignment. Un attaquant peut donc modifier plusieurs champs de la base de données auxquels il n’est pas censé avoir accès. 🛡️️ Comment se protéger Une bonne pratique est de séparer l’entité de la base de données des objets sérialisés pour les requêtes et les réponses (appelées DTO pour Data Transfer Object). Ainsi, pour une fonctionnalité de modification de date uniquement, le serveur va ignorer ou va renvoyer une erreur à la présence de tout champ non spécifié par les développeurs. Dans certains langages, la possibilité de modifier ou non un champ via l’API peut être mis comme propriété du champ. C’est le cas de NestJS par exemple avec les propriétés "whitelist" et "forbidNonWhitelisted". Une autre solution serait de recalculer le prix de la commande dans le back au moment du paiement à partir des prix des articles. 🏹 Pour aller plus loin Vous pourrez trouver plus d'informations et de ressources sur cette faille ici : Articles explicant les failles sur le système de mcdonald inde : https://eaton-works.com/2024/12/19/mcdelivery-india-hack https://techcrunch.com/2024/12/19/bugs-in-a-major-mcdonalds-india-delivery-system-exposed-sensitive-customer-data/ https://www.techradar.com/pro/security/mcdonalds-delivery-customers-put-at-risk-by-possible-data-breach Explication de la faille mass assignment : https://owasp.org/API-Security/editions/2023/en/0xa3-broken-object-property-level-authorization/ Comment se protéger : https://docs.nestjs.com/techniques/validation Article rédigé parGhali El Alaoui El Abdellaoui

  • Anders

    Les Observables en 2025 : Guide de Plomberie Moderne

    Découvrez pourquoi les Observables restent indispensables à l'ère des Signals, et maîtrisez leurs concepts clés (subscribe, pipe, switchMap) pour une gestion efficace des flux de données en JavaScript, illustrés par des exemples pratiques. "Les Signals sont là, est-ce que ça vaut encore le coup de comprendre les Observables ?" Cette question, je l'entends souvent. Et la réponse est simple : AB-SO-LU-MENT. Avec les Signals, on peut aussi le faire ! La syntaxe est différente, mais chaque approche a ses avantages. Les Observables brillent particulièrement quand on doit jongler avec des flux d'événements et des transformations complexes. Si vous n’êtes pas convaincus, je vous invite à lire cet article de mon collègue Léo. Pourquoi parler plomberie en 2025 ? Quand j'étais petite, je voulais devenir plombier. OK, c'est faux. Mais aujourd'hui, je suis un peu plombière de temps en temps. D'abord pour déboucher mon évier (merci la coloc), mais surtout quand je manipule des Observables. Si vous pensez que les Observables sont juste une façon compliquée de faire des callbacks, laissez-moi vous montrer pourquoi ils restent indispensables en 2025. Manuel du Plombier Observable : Les Outils Essentiels Imaginez un observable comme un flux d'eau ou plutôt de glaçons dans un tuyau. Il peut émettre une série de valeurs au fil du temps, telles que des clics de souris, des réponses de serveur, ou même des mises à jour en temps réel. La question qu’on se pose c’est comment correctement récupérer les glaçons qui sont dans notre tuyau ? Plic ploc, d’abord, on commence par créer la plomberie. C’est le moment où vous définissez un flux observable, par exemple en utilisant of, fromEvent, ou interval. Le robinet est en place, mais rien ne coule encore. subscribe : Le Point de Consommation Splash ! Avec subscribe, vous tournez la poignée et l’eau commence à couler. Le subscribe est comme un évier où l'eau finit par se retrouver. Il est le point de terminaison de votre flux d'observables. Mais plus important, il “ouvre le flux”. Sans subscribe on ne commence jamais l’écoute. Lorsque vous vous abonnez à un observable, vous commencez à recevoir les données qu'il émet. Sans évier, on n’ouvre pas le robinet ! Mais attention, un subscribe sans unsubscribe, c'est comme partir en vacances en laissant le robinet ouvert. Sauf qu'au lieu d'une facture d'eau salée, vous aurez droit à des memory leaks et des bugs mystérieux à 2h du matin. Le pipe : Le Tuyau de Connexion Le pipe, c'est le tuyau magique qui transforme votre eau boueuse en eau potable. Le pipe permet de connecter différents opérateurs pour transformer ou filtrer les données d'un observable avant qu'elles n'atteignent votre application. tap : L'Inspection du Flux Quand vous voulez observer ce qui se passe dans le flux d'observable sans le modifier, tap est votre outil. Comme un regard qui permet d'inspecter les données sans les altérer, tap vous permet d'effectuer des actions secondaires, telles que le déclenchement d'effets secondaires non liés à la transformation des données elles-mêmes. map : La Transformation du Flux L'opérateur map agit comme un mutation qui transforme chaque goutte d'eau (ou donnée) passant à travers. Par exemple, si vous recevez une liste d'objets et que vous souhaitez extraire une propriété spécifique de chaque objet, map vous permet de transformer chaque élément de la liste en cette propriété spécifique. switchMap : La Réorganisation du Flux Voyez ça comme une bouche d’évacuation suivie d’un autre robinet. Quand les glaçons arrivent, ils rentrent dans le premier tuyau. Si d’autres premiers glaçons arrivent, le contenu actuel est vidangé. C'est particulièrement utile quand votre utilisateur clique comme un possédé sur le bouton "Rafraîchir". Au lieu d'avoir 42 requêtes qui se battent en duel, switchMap fait le ménage : seule la dernière requête survit. Les autres ? Direct à la benne ! 💡  mergeMap : Laisse toutes les requêtes se poursuivre et traite chaque résultat indépendamment, ce qui est utile lorsque chaque action (comme un clic) doit être traitée, même si elles se chevauchent. combineLatest : La Fusion de Flux Synchronisés L'opérateur combineLatest est comme un collecteur qui rassemble plusieurs flux d'eau et les synchronise pour former un seul flux combiné. Cet opérateur attend que chaque observable ait émis au moins une valeur, puis il combine les dernières valeurs émises de chaque observable en une seule émission. Imaginez que vous avez plusieurs tuyaux qui amènent chacun un glaçon de couleur différente : combineLatest vous permettrait de créer un glaçon multicolore à partir de tous ces tuyaux. C'est utile, par exemple, lorsque vous voulez synchroniser plusieurs sources de données avant de procéder à une action. take : La Limitation du Flux screeeech Soit le réservoir est vide (complétion), soit vous criez "STOP !" avec unsubscribe ou take. Dans tous les cas, on range les outils, on nettoie le chantier avec finalize, et on s'assure qu'il n'y a pas de fuite sous l'évier ! take, c'est comme ces minuteurs de douche économes : "Tu veux 3 valeurs ? Tu en auras 3, pas une de plus !" C'est le champion des économies d'eau... euh, de données. Par exemple, vous pouvez utiliser take(3) pour ne traiter que les trois premières réponses d'une série de requêtes HTTP. Le Cousin takeUntil Si take est le minuteur de douche, takeUntil est le détecteur de mouvement qui coupe l'eau quand vous sortez de la salle de bain. Les petits cousins Il existe d’autres opérateurs comme takeUntil. Par exemple le nouveau takeUntilDestroy de Angular 16 (cf cet article). D’autres sont à explorer dans cet article de notre blog ! finalize : Le Nettoyage du Flux Le finalize est le processus de fermeture du robinet et de nettoyage après avoir utilisé le flux d'eau. Cet opérateur vous permet d'exécuter du code de nettoyage ou des actions finales une fois que l'observable a complété ou a été annulé. Les fuites mémoire (Ou comment j'ai inondé mon app) Erreur #1 : Le Subscribe Oublié Erreur #2 : L'Oubli du Nettoyage La Check-list du Bon Plombier Observable Finalement, les Observables, c'est comme la plomberie : quand c'est bien fait, personne n'y pense. Quand c'est mal fait, ça se remarque rapidement.Finalement, un bon plombier n'est pas celui qui répare les fuites, c'est celui qui les évite. Je vous laisse avec une petite check-list du bon plombier observable ✅ Toujours utiliser takeUntil ou gérer manuellement vos subscriptions ✅ Préférer les opérateurs comme take(1) pour les one-shot ✅ Utiliser catchError pour gérer les erreurs (les fuites, c'est jamais joli) ✅ Penser switchMap pour les requêtes qui s'annulent ✅ Ne pas oublier de compléter vos Subjects dans ngOnDestroy Article rédigé par Laura Pedenaud

  • Anders

    Tech Radar mobile

    Inspiré du retour d’expérience de notre quotidien et co-construit par notre comité de contenu composé de 13 experts, notre Tech Radar est le premier à présenter un focus 100% mobile. Découvrez notre troisième édition ! Téléchargez le 3ème volume de notre Tech Radar Retrouvez l'avis de nos experts sur les techniques, plateformes, outils, langages et frameworks associés aux principales technologies mobiles que nous utilisons au quotidien chez Theodo Apps : React Native, Flutter et Native.

  • Anders

    Migration d’une application iOS/Android vers Kotlin Multiplatform : Méthodologie et étapes clés

    L’intérêt principal de cette migration ? Migrer du natif vers le multiplateforme, c’est avant tout réduire les coûts et le lead time pour livrer de nouvelles fonctionnalités. Maintenant, pourquoi choisir une migration vers KMP plutôt que Flutter ou React Native ? Car elle peut être réalisée par étapes, en migrant une couche applicative ou une fonctionnalité à la fois, limitant ainsi les risques et facilitant l’intégration. J’ai moi-même participé à ce genre de migration. Dans ce premier article, je vous explique la méthodologie suivie. 🚀 Dans un deuxième article, je partagerai un retour d’expérience basé sur l’application concrète de cette méthodologie. 🔍 0. Identifier les différences entre les plateformes Avant de débuter la migration, il est crucial d’identifier les écarts entre les versions iOS et Android de votre application. La migration KMP offre l’opportunité d’unifier certaines de ces différences de comportement, si cela s’avère pertinent. Lister toutes les différences fonctionnelles entre les deux applications. Déterminer si elles sont intentionnelles ou non. Pour chaque différence non souhaitée, définir une version unifiée à adopter dans l’architecture KMP. ➡️ Pourquoi cette étape est essentielle ? Elle évite la création d’une implémentation KMP trop spécifique à Android et garantit que les avantages de la version iOS ne soient pas perdus. Il existe aussi des différences d’implémentation, ce qui est normal puisque iOS et Android ont chacun leurs spécificités. Pour les différences d’architecture, par contre, notez-les : cela vous aidera à estimer la difficulté de la migration progressive par couche. Plus les couches d’architecture sont différentes, plus la migration par couche sera complexe côté iOS. 🛠 1. Préparer le projet Android à la migration Avant de commencer, il est impératif d’effectuer certaines mises à jour : Assurez-vous d’avoir des versions récentes de Kotlin, KSP et Gradle pour bénéficier des dernières optimisations et éviter les incompatibilités. Certaines bibliothèques tierces utilisées sur Android (Koin, Room, Coil, etc.) sont utilisables sur KMP. Mettez-les à jour avant de démarrer. Jetpack Compose évolue rapidement, une mise à jour permet d’exploiter les dernières améliorations (si migration de la vue). ➡️ L’objectif est d’assurer une transition fluide sans surprises techniques bloquantes. 🔄 2. Créer le projet multiplateforme Plusieurs solutions s’offrent à vous ; elles sont détaillées sur le site de KMP. Je vous conseille la solution suivante, plus simple pour la maintenance du projet migré : Transformez l’un des répertoires Git (Android/iOS) en un répertoire commun contenant les deux applications Android et iOS ainsi que le futur code partagé. Cette solution nécessite une manipulation pour conserver l’historique Git des deux projets (par exemple avec des sous-modules Git). Cette solution a ses limitations. Pour aller plus loin, vous pouvez consulter cet article de TouchLab (un leader sur KMP) qui parle de leur outil Gitportal. 👁️ 3. Trouver la fonctionnalité la plus facile à migrer La migration doit se faire par petites étapes. Commencez par une fonctionnalité isolée, non centrale, une fonctionnalité feuille ou périphérique, pour minimiser les risques. ❓Comment trouver une fonctionnalité feuille ? Si votre application est constituée de flux, regardez du côté des fins de flux ou des flux secondaires. Si votre application comporte une barre de navigation en bas, choisissez l’onglet le moins lié aux fonctionnalités principales. 📦 4. Migrer la couche modèle d’une fonctionnalité 🔹 Pourquoi commencer par la couche modèle ? C’est la couche qui contient normalement le moins de dépendances à des librairies externes. Et donc le moins de code spécifique à une platforme. 🟦 Comment attaquer la couche modèle ? Convertir autant de code que possible en utilisant des API Kotlin pures plutôt que des API spécifiques à Java ou Android (par exemple, remplacer java.util.UUID par kotlin.uuid.Uuid). Ceci s’applique à la migration de tous les modules. C’est ici tout le cœur de la migration Android → KMP : vous remplacez du code spécifique à la JVM et au SDK Android par du code compatible KMP, compilable sur toutes les plateformes. Dans le module commun multiplateforme, créez le module model de votre fonctionnalité en dupliquant les classes de votre code Android tout en tenant compte des éventuelles différences avec iOS.La couche modèle est la plus simple à migrer, car elle n’a pas (ou peu) de dépendances externes. C’est le cœur de votre application et la couche qui présente généralement le moins de différences entre les plateformes. Utilisez votre module multiplateforme pour déplacer les sous-parties quand c’est possible, en faisant des commits de taille correcte. Dans votre code Android et iOS, remplacez les imports des anciennes classes model par ceux des classes du module commun. Si vous utilisez le même package dans le code KMP que sur Android, vous éviterez cette étape et limiterez au maximum les retouches. 🔄 5. Migrer les modules transverses Après avoir migré la couche modèle avec succès, on pourrait être tenté de passer sur les couches suivantes. Cependant, les couches suivantes auront probablement besoin de vos modules transverses. Par exemple, la couche data de votre fonctionnalité a besoin du module qui crée le client HTTP. Vous aurez aussi besoin de votre logger, des analytics, des fonctions utils et même de votre design system à un moment. Il serait donc intéressant de migrer ces modules transverses d'abord. Toutefois, il peut être difficile de se rendre compte si l'on a besoin de migrer tout un module ou seulement une partie liée à la feature que l'on migre. Il est donc recommandé de continuer les étapes de migrations suivantes en revenant aux modules transverses dès que nécessaire. 🔗 6. Migrer la couche Data de la même fonctionnalité La couche Data gère les appels réseau, les accès aux bases de données et les manipulations de fichiers. Elle est étroitement liée à la logique métier. Migrez chaque partie de cette couche une par une. Choisissez une bibliothèque KMP pour les appels réseau et la base de données. Migrez vos classes de la couche Data en utilisant les bibliothèques KMP. Créez des adaptateurs pour convertir les données réactives communes en données réactives spécifiques à Android ou iOS. En effet, votre couche de logique métier va demander des données réactives à votre couche data. C'est donc votre couche métier qui va utiliser ces adaptateurs. Vous aurez plus de facilité si vous utilisez déjà les coroutines ou Kotlin Flow plutot que Rx et les Livedata. Dans le cas où vos données interagissent avec celles d’autres fonctionnalités, trois choix s'offrent à vous : Créer des composants spécifiques pour assurer les interactions avec les données dans toutes les fonctionnalités. Revoir le choix de la fonctionnalité migrée en premier et opter pour une fonctionnalité avec moins de dépendances. Migrer les données des autres fonctionnalités en même temps si cela reste gérable. 🏗 7. Migrer la couche métier de la même fonctionnalité La partie logique métier contient les règles spécifiques à votre application. Cette couche, proche de la couche modèle, inclut souvent des fonctions qui récupèrent, mettent à jour ou suppriment des données. Elle peut être fortement liée à des bibliothèques externes comme Rx ou LiveData pour rendre les données réactives.Elle communique avec la couche Data pour récupérer les données et les transformer. Pour migrer cette couche, déplacez vos adaptateurs de code réactif pour les utiliser dans la couche présentation plutôt que dans la couche métier. En faisant cela, vous allez conformer votre couche métier aux librairies de réactivités Kotlin (coroutines, flow). 🖼 8. Migrer la couche présentation de la même fonctionnalité Cette couche, qui fait appel à la logique métier pour nourrir les vues, est souvent la moins bien architecturée. En effet, le cœur d’une application mobile étant d’organiser l’affichage des données de réagir aux interactions de l’utilisateur, c’est par ici que passe la plupart du code. Par ailleurs c’est la couche qui communique avec les vues, on y retrouve donc souvent du code très (trop ?) proche de la plateforme.Soyez très attentif, c'est ici que vous risquez le plus d'avoir des régressions, complétez vos TUs au besoin. 🎯 Stratégie recommandée Identifier les parties trop liées aux frameworks et les adapter. Vérifier chaque modification pour éviter les régressions. Supprimer les adaptateurs de l’étape 5, s’ils ne sont plus nécessaires. 🎨 9. Migrer la vue de la même fonctionnalité Si vous souhaitez partager la vue entre les plateformes avec Compose Multiplatform, c’est le moment de le faire. Dupliquez les vues Android en réimplémentant les éléments spécifiques à Compose pour Android. Compose Multiplatform étant très proche de Compose pour Android, les modifications nécessaires seront limitées. Une fois que tous les éléments spécifiques à Android seront écartés, votre code Compose sera utilisable sur iOS. En migrant également les vues, vous limiterez considérablement la communication entre le code KMP et le code Swift. Bien que la promesse de KMP soit la facilité de communication entre le code commun et spécifique, il est toujours plus simple de ne pas avoir à le faire. ✅ 10. Finaliser la migration À cette étape, la plupart du travail est fait. Il ne reste que quelques éléments spécifiques aux plateformes comme la navigation ou certaines intégrations natives.. Finalisez ces migrations progressivement, sans précipitation. 🤔 Faut-il migrer progressivement iOS ? Dans cette stratégie progressive, le code commun est conçu pour s’adapter à iOS, ce qui permet de ne pas bloquer le développement de l’application iOS tout en s’assurant que l’API du code commun est bien adaptée à cette plateforme. Plus le code des plateformes est différent dans son architecture, ses composants, ses noms, ses comportements et sa logique, moins la migration progressive pour iOS est intéressante. Cette stratégie peut devenir chronophage et une approche moins progressive pourrait être plus adaptée. On peut se limiter par exemple à une migration progressive feature par feature. Conclusion Cette première partie détaille une méthodologie structurée pour migrer progressivement une application mobile vers Kotlin Multiplatform. Plus votre code Android sera loin de l’univers Android et Java et proche de Kotlin, plus la migration sera facile. Plus votre architecture et les interfaces entre les couches seront identiques sur Android et iOS, plus vous aurez l’avantage de migration progressive par couche sur iOS. Dans la deuxième partie, nous partagerons un retour d’expérience sur l’application concrète de ces étapes, avec les défis rencontrés et les enseignements tirés. 📌 Restez connectés pour la suite ! 🚀

  • Anders

    Tech Radar Cloud

    Ce Tech radar regroupe une cinquantaine de technologies Cloud et DevOps éprouvées par les experts de Theodo Cloud durant plus de 4 ans de projets. Téléchargez le 2ème volume de notre Tech Radar Cloud Retrouvez dans ce tech radar notre avis d'experts sur des technologies cloud et DevOps. Nous avons testé ces +50 technologies lors de projets pour vous donner l'avis le plus objectif qui soit et les avons répartis en 4 cadrans : Résilience, Opérabilité, Sécurité et Empowering !