Bonjour.

cela fait quelques temps que je me pose une question sur MVC dans Sencha.

Comment définir une appli MVC qui comporte un grand nombre de controlleur sans tout charger au lancement de l'appli ?

telque sencha l'a défini une Appli MVC déclare ses controlleurs qui eux même déclarent les vues, les modèles et les datastores qu'ils utilisent.

du coup lorsqu'on lance l'appli les requires en cascade chargent tout le code.
sur une petite appli ou sur une appli sur internet c'est peut être mieux ainsi.

mais sur une grosse appli sur un intranet on a plus intérêt à ne charger que le necéssaire et le reste venant en fonction des besoins.

le problème est alors le suivant.
ne pas déclarer les controlleurs systématiquement et permettre de les charger au besoin.

pour résoudre ce pb de façon cohérente et sans avoir trop de boulot à faire je suis partit de l'exemple descktop fourni par sencha.

c'est typiquement le genre de chose ou on n'a pas envie que toutes les "application" présente sur le bureau virtuel soient chargé au démarrage.

le bureau est fait de modules, chaque module est en soit une mini appli. j'ai d'abord pensé en faire de vrais applies MVC sandboxé. mais cette approche n'était pas généralisable à autre chose qu'un bureau.
de plus le bureau lui-même n'était pas MVC.

j'ai donc regardé comment il fonctionnait et je suis partie de l'idée d'avoir une appli MVC qui suporte la notion de module comme le bureau. au démarrage l'appli charge les modules mais ne les exécute pas.
les controlleurs des modules étant chargé lors de leur première exécution.

la methode Ext.Application est particulièrement hermétique et je suis partie de la classe qu'elle instancie. pour définir ce qui serait le ceur de mon système.
Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
Ext.define('Ext.ux.desktop.System', {
    extend: 'Ext.app.Application',
 
    constructor: function() {
    	var config = arguments[0]||{name: 'MySys'};
    	var modules = Ext.Array.from(config.modules) || [];
    	config.requires = Ext.Array.from(config.requires) || [];
 
    	config.modFolder = config.modFolder || 'modules';
    	config.desktopClass = config.name + '.module.' + config.desktopClass || config.name + '.module.Desktop';
 
    	Ext.Loader.setPath(config.name + '.module', config.modFolder);
 
    	config.requires.push(config.desktopClass);
 
    	Ext.Array.each(modules, function(module) {
    		this.requires.push( this.name + '.module.' + module);
 
    	},config);
    	this.callParent(arguments);
    },
 
    getDesktopModuleClassName: function(name){
        return this.name + '.module.' + name;
    },
 
    launch : function() {
        Ext.create(this.desktopClass, this);
    }
});
sont fonctionnement est semblable à Application. pour tout les nom de modules présent dans le Système il définit un nom de classe et l'ajoute au requires.

l'usage est le suivant
Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Ext.onReady(function() {
	new Ext.ux.desktop.System({
        name : 'MyDesktop',
 
        modules:[
           'SystemStatus',
           'VideoWindow',
           'Grid',
           'Tab',
           'Users',
           'Notepad',
           'BogusMenuModule',
           'BogusModule'
        ],
 
        desktopClass: 'Desktop'
 
    });
});
vous reconnaitrez les modules de l'exemple desktop.
dans Application il faut définir une méthode launch qui desfini le viewport de l'appli et assure le démarrage.
tel que je l'ai défini cette possibilité reste possible mais l'attribut desktopClass permet d'instancier un module qui assurera le démarage de l'application (du bureau dans mon exemple)

ce premier module définit l'IHM de l'application et propose à l'utilisateur divers moyen de lancer un module. les modules ne font que définir des éléments d'IHM permettant leur lancement.
ils référence comme une Application un ou des controlleurs et proposent une méthode run
Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*!
 * Ext JS Library 4.0
 * Copyright(c) 2006-2011 Sencha Inc.
 * licensing@sencha.com
 * http://www.sencha.com/license
 */
 
Ext.define('MyDesktop.module.Users', {
    extend: 'Ext.ux.desktop.Application',
 
    controllers: ['Users'],
 
    id:'users-win',
    name: 'Users Manager',
    smallIcon: 'user-kid',
    largIcon:'accordion-shortcut',
 
    launcher: true,
    shortcut: true,
    quickStart: true,
 
 
    windowCfg: {
        id: 'user-win',
        width: 500,
        height: 300,
        animCollapse: false,
        constrainHeader: true,
        bodyBorder: true,
        border: false,
        layout: 'fit',
 
        items: [{
            xtype: 'userlist'
        }]
   }
});
il s'agit ici de l'intégration du tutoriel MVC UsersManager de Sencha, dans une fenêtre du bureau.
la partit intérésante est dans la méthode run de Ext.ux.desktop.Application (classe crée pour la circonstance). elle contient un appel à loadControllers
Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
    loadControlers: function() {
    	if (!this.controllersOk) {
        	Ext.Array.each(this.controllers, function(controller) {
                controllerName=this.app.system.getModuleClassName(controller, 'controller');
                var controller = this.app.system.getController(controllerName);
                    controller.init(this.app);
        	}, this);
        	this.controllersOk = true;
    	}
 
    },
la solution à mon problème se trouve dans ces trois lignes
Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
var controller = this.app.system.getController(controllerName);
    controller.init(this.app);
}, this);
je récupère une référence au système et je lui demande le controlleur Ext va alors charger les vues, stores et modèles associés. l'application pour le reste est exactement comme tout autre appli MVC.

faire un cas particulier c'est bien en faire plusieurs ça permet de voir les difficultes.
l'exemple Dsktop de sencha n'est pas toujours bien structuré. ainsi il définit un membre launcher dans dans le module qui est utilisé par le startMenu et qui appelle la création de la fenêtre en passant en parametre le launcher. pour les quickStart et shortcut les techniques sont différentes du coup impossible de faire comme le BogusMenuModule pour pur produire plusieurs shortcut le desktop ne sait pas les différencier. j'ai donc corrigé ce petit problème et j'ai entrepris de passer les modules défini par l'exemple en MVC. chose qui ses fait en quelques heures. (principalement pour corriger ces incohérences) J'ai tout de même voulu conserver la possibiliter de mixer des modules MVC avec d'autre qui ne le sont pas.

cela faisait longtemps que je pensais à ce problème et j'avais envisagé diverses voies, sans jamais asser à l'acte. trops de chose à produire et trop éloigné de la solution MVC de Sencha.

lorsque cette idée à germé hier je m'y suis mis et en 5 heures j'avais un bureau MVC fonctionnel contenant le tuto UserManager. 5 heures plus trad les modules de l'exemple sont passé en MVC et le fonctionnement du bureau à été rendu plus cohérent. le code de l'exemple Sencha très peut modifié : les modules on un launcher un shortcut et un quickStart qui fonctionne comme pour le launcher d'origine avec un handler fourni par le module (run) les code fignolé (pas assez commenté) et j'ai simulé un login et une gestion de session.

pour ajouter un module au bureau:
  1. Developper une Appli MVC comme dans le tuto Sencha.
  2. Créer un module sur le modèle de Users
  3. Relancer le bureau


A+JYT
Ps: je vais documenter mon code et je vous le proposerais.