Singleton, chargement de multiples applications Flex (SWF) et loaderContext
98% du temps, je vous dirais que la création de Singletons dans votre application est une mauvaise pratique, à éviter (par expérience). Bon, il reste 2%, tout premièrement car le framework Flex utilise lui-même des Singletons (chaque application est un singleton, mais aussi PopUpManager, DragManager, CursorManager & co). Et parfois, ils peuvent vous sauver la mise pour éviter de mettre en branle des techniques de sioux pour arriver à ses fins.
C'est ce qui m'est arrivé hier pendant mes développements dans une situation assez spéciale que l'on ne rencontre pas tous les jours.
Le contexte.
Je développe actuellement une administration pour un SIG Web qui consiste en une série d'applications Flex. Ces applications sont indépendantes dans leur fonctionnement et sont chargées par une application-mère qui consiste simplement en un TabNavigator contenant des SWFLoader.
Un petit schéma pour expliquer la situation:
La contrainte
Ces applications communiquent toutes avec un seul et même serveur baptisé Aigle. Ce serveur ne peut, par utilisateur, ne recevoir qu'une seule requête à la fois et c'est ici la contrainte qui nous intéresse. Si le serveur reçoit 2 requêtes du même utilisateur, la 2 sera mise en attente pendant un certain temps. Si la sous-application 1 fait une requête assez longue et que l'on bascule sur un autre onglet pour faire quelque chose qui va envoyer un autre requête, on tombera donc sur ce problème.
Le système d'envoi de requêtes en 2 mots
Pour envoyer des requêtes au serveur, j'utilise un Singleton (oui, c'est le dernier) nommé "RequestManager". Celui-ci s'occupe d'envoyer les requêtes au serveur à la chaine. Quand on tente d'envoyer une requête, on va simplement alimenter une pile de requête qui se dépile lorsque l'on reçoit le retour d'une requête. On a donc une FIFO (si je ne m'abuse) qui me permet de ne pas me heurter à la contrainte imposée par le serveur.
La classe RequestManager se trouve dans une librairie, utilisée par tous les projets.
Première approche, chargement simple des SWF applicatifs avec SWFLoader
Dans un premier temps, j'ai tenté de simplement créer des new SWFLoader et de faire un load(pluginPath.swf). Dans ce cas-là, chaque SWF est dans une "sandbox" locale. Il n'y a aucun partage de classe, chaque SWF est une entité bien distincte. Si on charge 6 sous-applications, on aura donc 6 instances bien distinctes de RequestManager (ce sont des Singletons par rapport à chaque SWF).
Flex Modules – Introduction aux Modules Flex
Quand on parle de Modules Flex, on parle de fichiers SWF qui peuvent être chargés et déchargés par une application. Ils ne peuvent pas être lancés indépendamment d'une application, mais plusieurs applications peuvent se partager des modules.
Les Modules permettent de séparer votre application en plusieurs parties. L'application principale (aussi appelée la coquille/shell), peut dynamiquement charger les modules dont elle a besoin, quand elle en a besoin. Elle n'a pas besoin de charger tous les modules au démarrage. En fait, elle n'a même pas besoin de charger aucun module si l'utilisateur ne les utilise pas. Quand l'application n'a plus besoin d'un module, il peut le décharger pour libérer de la mémoire et des ressources.
Les applications modulaires ont les avantages suivants:
- Un temps d'initialisation de l'application plus court
- Un temps de téléchargement initial plus court (SWF principal plus léger)
- Une meilleure encapsulation des différents aspects de votre application. Par exemple, une fonctionnalité de "reporting" peut être séparée en un module sur lequel vous pouvez travailler de manière indépendante.
Ce que les modules peuvent apporter à votre application Flex
Un module est un type spécial de SWF pouvant être chargé de manière dynamique qui contient une Class Factory nommée IFlexModuleFactory. Cela permet à une application de charger du code à l'exécution et de créer les instances de classe sans que l'implémentation de la class soit liée à l'application principale.
Les modules sont similaires aux RSLs (Runtime Shared Library) en un sens car ils séparent le code de celui application dans un fichier SWF séparé. Les modules sont bien plus flexibles que les RSLs car ils peuvent être chargés et déchargés à l'exécution, et compilés sans l'application.
Les applications lourdes (en terme de poids) avec différent chemins-utilisateur et une application "portail" sont généralement de bons candidats à l'utilisation des modules.
Par exemple, prenez une grosse société d'assurance ayant une application qui contient des centaines d'écrans, pour l'assurance vie, l'assurance auto, l'assurance santé, l'assurance dentaire, etc.
En utilisant une approche traditionnelle RIA, vous allez créer une application monolithique (en un seul bloc) avec un arbre de classes MXML. L'utilisation mémoire et le temps de chargement de l'application seraient significatifs, et la taille du fichier SWF grandirait à chaque ajout de fonctionnalités.
Cependant, à l'utilisation de cette application, les utilisateurs ne vont accéder qu'à un sous-ensemble de ces écrans. En faisant un regroupement (refactor) des écrans en petits groupes de modules chargés à la demande, vous pouvez améliorer les performances de votre application principale et réduire l'utilisation mémoire. De plus, quand l'application sera séparée en modules, la productivité des développeurs sera meilleure, grâce à une meilleure encapsulation de l'architecture. Quand vous allez relancer un build de l'application, les développeurs n'auront qu'à recompiler une simple module au lieu de l'application entière.






