Chez Access it, nous avons à cœur de concevoir des applications métier performantes dès leur conception. Cette démarche est rendue possible grâce à notre socle technologique robuste, couplé à la puissance et la flexibilité de la technologie .NET. En intégrant dès le départ des principes d’optimisation dans nos développements, nous garantissons à nos clients des performances accrues, une scalabilité sans faille et une réactivité optimale. Dans cet article, nous vous proposons de découvrir les meilleures pratiques et stratégies que nous appliquons pour maximiser l’efficacité de nos projets dès leur lancement.
En effet, en développement informatique, la performance des applications métier est essentielle pour plusieurs raisons :
- GreenOps : une application optimisée consomme moins de ressources (CPU/RAM), ce qui se traduit par une réduction de la consommation d’électricité.
💡 Dans un contexte de réchauffement climatique, cet enjeu écologique est plus pertinent que jamais. - FinOps : en diminuant l’utilisation des ressources, une application performante permet de réduire les coûts liés à l’infrastructure, car elle peut fonctionner sur des machines moins coûteuses.
💡Cela permet également d’allouer les ressources financières à d’autres initiatives stratégiques ou d’augmenter les marges bénéficiaires. - Expérience utilisateur : la lenteur d’une application peut frustrer les utilisateurs, au point de les pousser à se tourner vers des alternatives.
💡Par exemple, une augmentation de 500 ms dans le temps de réponse de Google entraîne une baisse de 20 % des recherches effectuées.
Un de nos clients nous a signalé que certaines pages étaient lentes à afficher, voire ne s’affichaient pas du tout. Après analyse, nous avons découvert que le problème venait d’une requête SQL nécessitant de nombreuses jointures pour obtenir le résultat souhaité. Bien que ces jointures soient indispensables et déjà optimisées avec les bons index, une explosion cartésienne due à la quantité de données à renvoyer causait des ralentissements.
Grâce à l’ORM EntityFramework, une simple ligne de code a tout changé : .AsSplitQuery(). Cette commande indique à l’ORM de diviser la requête SQL en plusieurs requêtes pour éviter l’explosion cartésienne.
🏆 Résultat : le temps de réponse est passé de 120 secondes à 6 secondes. C’est une nette amélioration, mais encore un peu longue pour nos utilisateurs. En créant des index spécifiques pour ces nouvelles requêtes, nous avons réduit le temps de réponse à moins de 500 millisecondes. Une véritable victoire !
Pour une application métier lourde développée pour un client, une fonctionnalité permet d’exporter des fichiers au format Zip. Initialement, les fichiers étaient petits et le code avait été optimisé pour une génération rapide en utilisant au maximum la RAM. Cependant, avec l’évolution du projet, les fichiers sont passés de quelques mégaoctets à plusieurs gigaoctets, provoquant des plantages de l’application. L’optimisation sur mesure initiale n’étant plus adaptée, nous avons dû générer les fichiers Zip directement sur le disque plutôt que dans la mémoire vive.
🏆 Résultat : cela a légèrement allongé le temps de traitement, mais a permis de ne plus consommer de mémoire vive, évitant ainsi les plantages !
Une de nos applications a connu une forte augmentation de son nombre d’utilisateurs, ce qui est toujours une bonne nouvelle. Cependant, cela a entraîné des problèmes de lenteur et des erreurs pendant les périodes de forte utilisation. Le problème ne venait pas de l’implémentation, mais d’un nombre d’appels trop important pour l’infrastructure du client.
Avant de penser à revoir l’infrastructure, ce qui aurait engendré des coûts élevés, nous avons cherché une solution logicielle. Nous avons remarqué que de nombreux appels étaient communs à tous les utilisateurs, notamment pour la récupération de données (contenus, images) identiques pour tout le monde. La solution a été de mettre en place un système de cache pour limiter le nombre d’appels et réduire la charge CPU du serveur en utilisant davantage la RAM. Nous avons mis en cache les contenus et images pour une durée moyenne de 5 minutes, et mis en place du micro-caching (5 secondes) pour tous les appels non critiques.
🏆 Le résultat a été tellement satisfaisant que l’infrastructure a pu être conservée sans engendrer de coûts supplémentaires, permettant d’atteindre plusieurs milliers de requêtes par minute sans problème.
Chez tous nos clients, nous mettons en place des processus de déploiement continu pour garantir des livraisons rapides et fiables. Cependant, selon le projet, les différentes étapes de préparation du package à déployer peuvent devenir longues. Les principales causes sont les analyses de code, les tests, la compilation et la création des images Docker pour les différents projets. Pour certains de nos clients, où la rapidité des déploiements est cruciale, nous avons mis en œuvre plusieurs optimisations :
- Parallélisation des étapes : traiter chaque projet simultanément plutôt que successivement.
- Création d’agents/runners dédiés : utiliser une configuration robuste pour des compilations rapides.
- Mise en cache des dépendances : charger plus rapidement les dépendances lors des prochains déploiements.
- Création d’images Docker de base : inclure déjà les dépendances dans les images de base, de sorte que seul le projet doit être ajouté.
🏆 Résultat : chez l’un de nos clients, où les déploiements complets prenaient près d’une heure, nous avons réussi à réduire ce temps à 8 minutes grâce à ces optimisations.
Dans le cadre d’un projet impliquant la gestion de documents (contrats, devis, fiches d’état, etc.), nous avons choisi Neo4j, une base de données orientée graphes réputée pour sa performance dans la gestion des relations complexes.
Contrairement aux bases relationnelles classiques, Neo4j organise les données sous forme de nœuds (entités) et de relations directement connectées. Cette structure permet d’exécuter des requêtes très rapides et optimisées pour le parcours de graphes. Par exemple, identifier tous les documents liés à un client devient quasiment instantané, même avec des volumes de données importants.
🏆 Résulat : ce choix s’est avéré stratégique : il a non seulement accéléré les recherches complexes, mais aussi simplifié la modélisation des relations entre entités. En outre, il garantit une évolutivité optimale, offrant ainsi une solution performante et intuitive pour la gestion documentaire.
L’optimisation des performances de l’application métier n’est pas un effort ponctuel, mais un processus continu. Qu’il s’agisse d’améliorer la rapidité d’une application, de réduire la consommation de ressources ou d’augmenter la satisfaction des utilisateurs, chaque optimisation compte et contribue à l’excellence globale de votre produit.
Cependant, il est essentiel de garder en tête que l’optimisation doit toujours être guidée par des priorités claires et mesurables. Sans un équilibre judicieux entre performances, maintenabilité et coût, on risque de tomber dans le piège de l’optimisation prématurée.
Avec une approche méthodique et centrée sur les besoins réels de nos utilisateurs, nous transformons les défis de performance en opportunités pour dépasser les attentes et bâtir des solutions robustes et efficaces.