DEJA-VUE.NET RIA Architect. Flash Platform Consultant and Trainer

25May/0625

ActionStep (plugin View) / Pixlib (MVC FrontController + Remoting) SUSHI Service

El chef vuelve a la carga ^^. En el menú, Sushis y MVC "on steroids".

Montad vuestra aplicación en MVC. Una vez que el MVC ha subido bien, trufadlo con un FrontController. Espolvoread con una pizca de MovieClipHelpers. Regad finalmente la mezcla con, según el gusto y el humor, un ModelLocator y/o un ServiceLocator...

Pixlib Remoting SUSHI service ? Ya oigo decir a algunos: se nos dedica al reciclaje intensivo, el niño...

En este artículo voy a presentaros a una joya de Pixlib (hay tantas... es una verdadera cueva de Ali Baba !).
SUSHI service se basa en una receta aplicativa increíblemente potente y polivalente, basada en el pattern MVC. "Receta", ya que realmente se trata de ingredientes que son peustos a nuestra disposición. Según estos ingredientes y la inspiración podremos, por ejemplo, inflar nuestro MVC tradicional en MVC de multiples Models (ModelLocator), o bien como es el caso aquí, hacer subir el conjunto en "Super MVC" (FrontController et ServiceLocator).

sushiService.zip (197)

- La interfaz de usuario

Sigue siendo ActionStep (me hubiera gustado probar ASWing but no time):
Esta vez, los "forms" o "states" han sido reagrupados en un módulo swf autónomo cargado al vuelo en la Aplicación principal. Adoptar este diseño ha supuesto una nueva estrategia de instanciación.

- - "Un sistema totalmente genérico"

El añadido del FrontController, del MovieClipHelpers y de un ModelLocator (clase core.Model) al patrón MVC confiere a nuestra aplicación un grado de modularidad ejemplar. Lo esencial de este artículo lo consagraremos a la descripción de este "Super MVC".
Evocaré los puntos que, desde un punto de vista personal, me han parecido más pertinentes.

- El servicio Remoting

Se apoya en la versión alpha del paquete remoting Pixlib. Se despliega con gracia desde un Singleton ServiceLocator.

Nota:
El termino "estado" ha sido empleado para designar las diferentes views contenidas en views.swf. Por tanto, no ha de ser tomado en su sentido literal "de estado" de la aplicación (generalmente almacenado en un SharedObject, ValueObject, instancia de Memento u otra solución)

Comencemos con imágenes a fin de tomar rápidemente puntos de referencia:

La estructura del proyecto

Sushi service flp

Diagrama (casero) de la relación FrontController, MovieClipHelper, ServiceLocator & ModelLocator

Sushi Diagram

La interfaz de usuario en standalone

Desvinculada de la estructura de su huésped precedente (ARP), los diferentes "estados" de la aplicación (order, viewOrders y navigation) son de nuevos meras subclases de MovieClip desprovistas de toda funcionalidad de event dispatching.

Este nuevo perfil de "plugin" ha supuesto cambiar la manera de instanciar el contenedor de los diferentes "estados" de la interfaz. Importada al vuelo en un MovieClip (via GraphicLib), la UI debe ser preinstanciada sin depender de _root si deseamos poder conectarla en caliente como un plugin.

El truco ? empaquetar las clases et proceder a la instanciación con SWFMILL.

La primera etapa, pues: compilar la view

/**
* @mtasc -version 8 -swf "classes.swf" -header 390:270:60:FCFCFC -trust
*/

// Imports...

class org.actionstep.view.sushi.Application extends MovieClip
{
    // MovieClip linkage
    static var id = (id="__Packages.org.actionstep.view.sushi.Application")+(Object.registerClass(id,Application)?"":"");

    private var navigation : MovieClip;
    private var order : MovieClip;
    private var viewOrders : MovieClip;
    private var dataPreloader : MovieClip;

    function onLoad()
    {
        // ActionStep theming
        org.actionstep.ASTheme.setCurrent(new
        org.actionstep.themes.plastic.ASPlasticTheme());

        // Set the initial display state of the application
        setInitialDisplayState();

        // Views Instantiation (no FLA here)
        navigation = attachMovie(Navigation.id,"navigation", 1);
        viewOrders = attachMovie(ViewOrders.id,"viewOrders", 2);
        order = attachMovie(Order.id,"order", 3);
    }
    // ...
}

La segunda etapa: instanciar con SWFMILL

 <?xml version="1.0" encoding="iso-8859-1"?>
<movie version="8" width="390" height="270" framerate="60">
    <background color="#ffffff"/>
    <frame>
        <library>
            <clip id="Application" class="org.actionstep.view.sushi.Application" import="classes/classes.swf" />
        </library>
        <place id="Application" name="app" x="0" y="0" depth="1" />
    </frame>
</movie>

La inicialización MVC

La aplicación principal (Application.as) se lanza de forma convencional con main().
El modelo se instancia primero. Nuestra única vista, una subclase MovieClipHelper, se registra con el Modelo. El controlador, un Singleton y subclase de FrontController es finalemente inicializado. El controlador es el cemento de la aplicación. Es el quien va a asociar eventos e instancias de comandos.

private function _init() : Void
{
    var model : Model = new SUSHIExpert();
    model.addListener( new SUSHIListUI() );
    Controller.getInstance().init();
}

I. LAS VIEWS

Cargado de la View standalone

GraphicLib y Libstack, del cargado y multicargado inteligente.
A través de esas 2 implementaciones concretas de AbstractLib, nuestros assets se cargan y almacenan con un identificador de tipo String. En este caso, estos identificadores estan predefinidos bajo formas de constantes accesibles de forma estática desde sushi.uis.UIList. Esto nos permite una mejor trazabilidad del acoplado entre los assets y sus 'accesores'.

var gl : GraphicLib = new GraphicLib( this, 20 );
gl.setName( UIList.SUSHI_List );
gl.addEventListener( GraphicLib.onLoadInitEVENT, this, _init );
gl.load( "deploy/views.swf" );

o

var libs = new LibStack();
libs.enqueue(new GraphicLib(this, 20, false), UIList.SUSHI_List, "deploy/views.swf");
libs.addEventListener( LibStack.onLoadCompleteEVENT, this, _init );
libs.execute();

Les elementos están luego accesibles globalmente de varias formas:

- Desde el Singleton GraphicLibLocator:

var myView:MovieClip = GraphicLibLocator.getInstance().getGraphicLib( UIList.SUSHI_List ).getView();

- Desde una subclase MovieClipHelper:

// SUSHIListUI.as

class sushi.uis.SUSHIListUI
    extends MovieClipHelper
{
    public function SUSHIListUI ()
    {
        super( UIList.SUSHI_List );
    }
}

- Desde una subclase ViewHelper

import com.bourre.data.libs.GraphicLib;
import com.bourre.visual.ViewHelper;
import sushi.uis.UIList;

class sushi.uis.SUSHIListUI
    extends ViewHelper
{
    public function SUSHIListUI ( gl : GraphicLib )
    {
        super( gl.getView(), UIList.SUSHI_List );

        view.app.showDataPreloader();
        gl.show();
    }
}

Es muy práctico tener un acceso global sobre las views:
Por ejemplo, si quiero actuar sobre una view desde un comando:

Con GraphicLibLocator:

import com.bourre.data.libs.GraphicLibLocator
import sushi.uis.UIList;

class sushi.commands.PlaceOrder
    implements Command
{
    public function execute( e : IEvent ) : Void
    {
        var myView:MovieClip = GraphicLibLocator.getInstance().getGraphicLib( UIList.SUSHI_List ).getView();
        myView.app.orderProcessed();
    }
}

con MovieClipHelper

import com.bourre.visual.MovieClipHelper
import sushi.uis.UIList;

class sushi.commands.PlaceOrder
    implements Command
{
    public function execute( e : IEvent ) : Void
    {
        var myView = MovieClipHelper.getMovieClipHelper(UIList.SUSHI_List);
        myView.view.app.showDataPreloader();
        myView.traceTest(); // calling a method on SUSHIListUI
    }
}

Aquí, en los que nos concierne, Sushi service tan sólo tiene una View de tipo MovieClipHelper

En una instancia de MovieClipHelper típicamente, vamos a:

- definir el comportamiento de los objetos (TextField, MovieClips, v2 components...) presentes en la View a través de sus nombres de instancia.

En el caso de Sushi service, la UI ActionStep no es tan sólo una concha vacía.

La view externa posee ya métodos:

hideDataPreloader();
showDataPreloader();
orderFormSelect();
viewOrdersFormSelect();

Luego, en cada "estado" ( Navigation, Order, ViewOrders ), los event handlers de los botones están ya definidos, ej.:

// NSButton
placeOrderButton = (new NSButton()).initWithFrame(new NSRect(300, 205, 80, 22));
placeOrderButton.setStringValue("Place order");
placeOrderButton.setTarget(this);
placeOrderButton.setAction("placeOrder");
view.addSubview(placeOrderButton);

No pasa nada ^^. Vamos a manejar y cambiar el scope, todo junto desde nuestra subclase MovieClipHelper :)

class sushi.uis.SUSHIListUI
    extends MovieClipHelper
{
    private function _initBehaviors() : Void
    {
        _pbCancelOrder.setTarget(this);
        _pbCancelOrder.setAction("cancelOrder");

        _dSelectViewOrders = new Delegate(view.app, view.app.viewOrdersFormSelect);
        _dShowPreloader = new Delegate(view.app, view.app.showDataPreloader);
    }

    private function _gotoViewOrders() : Void
    {
        _dSelectViewOrders.execute();
        _dShowPreloader.execute();
    }

    private function cancelOrder() : Void
    {
        _dShowPreloader.execute();
        _fireEvent(new BasicEvent(EventList.cancelOrderEVENT, view.app.viewOrders.getOrder() ));
    }
}

Une "arquitectura de legos" donde tenemos un control total sobre cada pieza autónoma pluggeada.
Retomemos un poco el hilo.
En una instancia de MovieClipHelper, vamos también a:

- definir los callbacks del ou de los Modelos.
- enviar (con nuestro EventBroadcaster global) mensajes de tipo BasicEvent o customizado (subclase BasicEvent) hacia los comandos correspondientes.

No dudáis en extender BasicEvent a fin de crear vuestros propios objetos de evento. Es otra piedra angular de Pixlib.

Echadle una ojeada al método placeOrder(). Veráis que difunde un evento de tipo OrderEvent.

private function placeOrder() : Void
{
    _gotoViewOrders();
    _fireEvent(new OrderEvent(EventList.placeOrderEVENT, view.app.order.orderName, view.app.order.orderTicket));
}

Cuidado, la comparación es odiosa, pero es sólo para que los que vienen de ARP puedan captar rápidamente la idea.
Pensad en OrderEvent como un Value Object (VO) que pasa las informaciones a los comandos.
Hala, podais desmelenaros todos y gritar Herejía! alto y claro ^^.

II. El FrontController

Es en sushi.commands.Controller (subclase de FrontController) que se asocian y almacenan eventos y comandos. A diferencia del ControllerTemplate de ARP, el FrontController no impone ninguna referencia directa a las views. Less coupling!

FrontController:

public function init() : Void
{
    push ( EventList.placeOrderEVENT, new PlaceOrder() );
    push ( EventList.getOrdersEVENT, new GetOrders() );
    push ( EventList.cancelOrderEVENT, new CancelOrder() );
}

ControllerTemplate:

private function addEventListeners ()
{
    app.orderForm.addEventListener ( "orderPizza", this );
    app.viewOrdersForm.addEventListener ( "getOrderList", this );
    app.viewOrdersForm.addEventListener ( "cancelOrder", this );
}

private function addCommands ()
{
    addCommand ( "orderPizzaCommand", OrderPizzaCommand );
    addCommand ( "getOrderListCommand", GetOrderListCommand );
    addCommand ( "cancelOrderCommand", CancelOrderCommand );
}

III. ServiceLocator y Commands

En el Singleton ServiceLocator definimos y almacenamos uno o varios servicios remoting (según nuestra necesidades). El nombre de alias de cada servicio es definido de manera estática

- La definición del servicio remoting:

// sushi.service.ServiceLocator
public static var SUSHISERVICE:String = "dejavue_net.sushi.sushiService";

public function init( remotingURL : String ) : Void
{
    gatewayURL = "http://www.deja-vue.net/amfphp/gateway.php";
    push( ServiceLocator.SUSHISERVICE, ServiceLocator.SUSHISERVICE );
}

- Configuración tipo de un comando:

1. Localización del servicio remoting et llamada del remote method

Cuidado, en el momento de escribir este artículo, el paquete remoting sigue estando en versión alfa y no disponible desde el svn. No me extendré pues en la implementación del responder y tampoco en la API.

// class sushi.commands.PlaceOrder

public function PlaceOrder()
{
    _service = ServiceLocator.getInstance().getService( ServiceLocator.SUSHISERVICE );
}

public function execute( e : OrderEvent ) : Void
{
    _service.order( new ServiceResponder(this), e.getName(), e.getTicket() );
}

public function onResult( e : BasicResultEvent ) : Void
{

}

public function onFault(e : BasicFaultEvent) : Void
{

}

2. Todos los caminos llevan a Roma:

Ahora, es GRANDIOSO. Desde un comando (y no solo desde ahí) podemos:

- actuar sobre la view de nuestra elección (acordaros de GraphicLibLocator, MovieClipHelper y ViewHelper).
- difundir un evento y llamar un comando.

EventBroadcaster.getInstance().broadcastEvent( new BasicEvent(EventList.getOrdersEVENT) );

- actuar sobre el modelo elegido.

SUSHIExpert(Model.getModel( ModelList.SUSHI_EXPERT )).onUpdate( e.getResult() );

Alucinante, tener tanto control :)

La palabra final (ya era hora! ^^):

Hace 2 días se me había metido en la cabeza escribir un artículo sobre el paquete MVC de Pixlib. Al mismo tiempo, me dije que era un tema un poco "ligero". Fue al profundizar en los paquetes events y visual que llegué al FrontController + MovieClipHelper y al deseo de probar todo eso. Pixlib no había terminado de sorprenderme...
Sigo estando boquiabierto. No me esperaba eso. Adivinad con qué voy a atornillar mi próximo proyecto ;) .

"Châpeau bas" para Francis.

Vínculos de referencia:

-MVC y FrontController
http://www.tweenpix.net/blog/index.php?2004/09/22/460-whiteboard-10
Discussion about models in mvc and front controller patterns on Pixlib list

GraphicLib, LibStack y MovieClipHelper
http://www.get-url.net/blog/?47--pixlib-libstack-ou-le-multi-chargement
http://www.get-url.net/blog/?48--pixlib-graphiclib-et-moviecliphelper-vs-movieclip-parti

Comentarios (25) Trackbacks (1)
  1. Très bon sujet.
    Si un jour tu avais le temps de (re)définir les utilisations des patterns FrontController et ModelLocator, je serai ravi.

    Un info, depuis swfmill, il est possible de lier une classe avec un clip de façon plus élégante à mon goût. Il suffit d’ajouter un attribut class dans la définition de l’import du . L’association se fait en interne.
    Cela permet de configurer l’ensemble depuis le fichier swfmill.

    respect ;)

  2. >erixtekila

    Très bonne suggestion. Je vais noter ça quelque part dans mon dashboard…

    C’est vrai, j’ai été plutôt expeditif sur le FrontController et j’ai fait l’impasse sur le ModelLocator mais le sujet est si riche, il y a beaucoup à couvrir et je ne voulais pas ennuyer avec un trop long billet :D .

    Concernant swfmill, tu peux donner un exemple de cette association en interne à laquelle tu fais référence ? Je suis pas sûr de connaitre cette façon là.

  3. A vot’ service, monseigneur :

    … plus loin, l’instanciation :

    L’association est crée en interne par swfmill (merci Dan)

  4. Est-ce que tu peux développer cette façon que tu as d’instancier les classes ?
    [as]
    static var id = (id=”__Packages.org.actionstep.view.sushi.Navigation”)+(Object.registerClass(id,Navigation)?”":”");
    [/as]

    Je ne suis pas sûr de comprendre la procédure de l’identifiant utilisé avant d’être initialisé…

  5. Mais je te reconnais ! Le ptit dernier au fond du post .

    On suivait d’une oreille, je vois… ^^.

    Enfin pour finir, Dave Yang donne ici un exemple très clair pour illustrer en quelques lignes l’astuce dénichée par Peter.

  6. Ouh qu’il est vilain lui !
    Ok, je ne me souviendais pûs du post de Dave, mais selon lui :

    Here’s a shortened (and more obscured) example:

    Alors si t’as pas compris non plus, c’est pas une raison pour embêêêêêter les aut’, voilà. ;)

  7. Hello :)

    Pour attacher un clip ou un Textfield qui utilise une classe “Custom” pour moi il ne faut pas utiliser la méthode de l’identifiant de liaison dans un attachMovie… cela nécessite de se prendre la tête avec une propriété quelquepart etc….
    Le mieux c’est de manipuler le __proto__, j’en parle déjà ICI et ICI

    Avec au passage ma classe DisplayFactory qui permet dans VEGAS de faire tout cela proprement :)

    C’est vraiment plus “ECMAScript” comme gestion de l’héritage et surtout moins “obscure” comme on peut le lire au dessus dans la citation ^_^

    EKA :)

  8. Salut EKA :) .

    Sois le bienvenu !

    Je viens de jeter un oeil à Vegas et Asgard. Beau boulot! Il y a du matos… :)

    J’ai pris quelques minutes ce matin pour tester le DisplayFactory sur OSFlash Pizza mais ça ne marche pas pour moi.

    [as]
    /*
    navigationForm = NavigationForm(
    attachMovie(NavigationForm.id, “navigationForm”, 1));
    */

    navigationForm = NavigationForm(
    DisplayFactory.createChild ( NavigationForm , “navigationForm” , 1, this) );
    [/as]

    Un examen avec Xray n’a cependant rien révélé de particulier. La classe est bel et bien instanciée.

  9. Hello :)

    J’ai pas regardé de prêt ton taf, tu utilises des composants compilés ou sont bien totalement dynamiques ? Car sinon faut se méfier :) Ma classe permet d’utiliser une classe qui hérite de MovieClip et de créer via un createEmptyMovieClip ou un createTextField un clip qui utilise une autre classe que la classe MovieClip pour son héritage.
    Faudrait que je regarde ce qui cloche ? Peut être avec un exemple à part de ce que tu cherches à faire ? Dans tous les cas tu as du le voir je fourni des exemples avec Asgard et Vegas et on y retrouve dans le répertoire bin/test/vegas/util/factory un exemple d’utilisation :) Tu peux peut être te baser là dessus pour tester ma classe ? :)

    Au passage si tu veux utiliser un composant dans la biblio et lui coller une classe tu peux utiliser la classe ConstructorUtil et la méthode createVisualInstance pour ajouter dynamiquement à ton clip qui vient d’être attaché la classe qu’il faut :) Je vais voir si je peux pas goupiller un truc automatisé dans Vegas ce soir :)

    EKA :)

  10. En l’occurence les composants (ActionStep) sont pure ActionScript (l’application est 100% IDE free)

    NavigationForm, par exemple, hérite de org.osflash.arp.ArpForm, la classe de base pour toutes les Views d’un projet ARP. ArpForm heritant de MovieClip.

    Oui j’ai bien vu les exemples. Les commentaires accompagnants DisplayFactory sont déjà très clairs :) .

    La classe ConstructorUtil à l’air très intéressante ;) . Je regarderai moi aussi tout ça de plus près ce soir.

  11. J’ai pas pu résister je viens de mettre en place rapidement dans la clase DisplayFactory une nouvelle méthode attachChild qui permet d’utiliser de façon combinée un attachMovie et la modification de l’héritage, exemple :
    [AS]
    import myPackage.RectangleComponent ; // classe qui hérite de MovieClip

    // Initialisation du composant
    var init = {
    t:2 , lc : 0xCCCCCC , la:100 ,
    w:50 , h:50 , _x:50 , _y:50
    }

    var rec:RectangleComponent = DisplayFactory.attachChild( RectangleComponent, “Rectangle”, “rec”, 1, this, init )
    [/AS]

    Mais bon dans tous les cas à part cause extrème je préfère créer des composants à base de full dynamique qui font ensuite dans le constructeur de la classe des attachMovie des éléments graphiques si je ne peux pas faire autrement que d’utiliser des symboles dans la biblio :)

    eKA :)

  12. @eka : j’ai toujours privilégié la composition à l’héritage, surtout pour les MovieClip et TextField.

    J’utilise par contre dans toutes mes classes sérialiables :
    [AS]
    // Sérialisation de la classe
    /**
    * Liaison de l’objet à sa classe.
    * Utiliser “__Packages.packageName” si extension d’un clip dynamique.
    */
    public static var linkageID:String = “net.via.ui.GraphicState”;
    public static var classRef:Function = GraphicState;
    public static var className:String = “GraphicState”;
    /**
    * Permet la serialisation d’un objet.
    * 1- Relie un objet avec la classe d’où il provient,
    * une fois remonté par SharedObject ou échangé par LocalConnection.
    * 2- Dans le cas de l’extension d’un MovieClip,
    * effectue la liaison avec un graphique généré dynamiquement.
    */
    public static var serializable:Boolean = Object.registerClass(linkageID, classRef);
    [/AS]

    J’ai puisé cela du framework AsUnit et je trouve la méthode très élégante.
    Dans Eclipse, j’ai un template qui me génère cela très aisément.
    Ainsi, les LocalConnections, SharedObject et services remoting peuvent utiliser simplement une classe personnelisée.

  13. Hello :)

    Alors pour le Object.registerClass je ne m’en sert pas car pour FMS … les namespace cela ne fonctionne pas correctement coté SSAS :) Et du coup je préfère utiliser EDEN pour les objets customs. J’ai posé la question justement aujourd’hui sur FCNG ici.

    Ensuite pour ce qui est de la composition ou de l’héritage, pour ma part j’utilise les 2 avec des composants qui restent des classes qui héritent de MovieClip (niveau performance c’est mieux à mon avis et cela permet d’aller assez loin dans l’héritage sans se prendre trop la tête) et dans le reste des cas j’utilise une classe DisplayObject qui utilise la composition et qui se calle sur la classe DisplayObject AS3 et ce que l’on peut voir dans Pixlib avec les MovieClipHelper. A mon avis il suffit de faire le bon choix selon la situation :)

    Sinon un truc au passage en voyant ton code au dessus, dans Vegas pour retrouver le nom de la classe et le package de celle ci, j’utilise les méthodes statiques de ma classe ConstructorUtil :

    [AS]import vegas.util.ConstructorUtil ;

    import vegas.events.BasicEvent ;

    trace ( “constructor name : ” ConstructorUtil.getName(BasicEvent)) ;
    trace ( “constructor package : ” ConstructorUtil.getPackage(BasicEvent)) ;
    trace ( “constructor path : ” ConstructorUtil.getPath(BasicEvent)) ;
    [/AS]

    et cela marche aussi avec les instances :
    [AS]var e = new BasicEvent() ;
    trace ( “constructor name : ” ConstructorUtil.getName(e)) ;
    trace ( “constructor package : ” ConstructorUtil.getPackage(e)) ;
    trace ( “constructor path : ” ConstructorUtil.getPath(e)) ;
    [/AS]

    Du coup à utiliser dans les toString(), les gestions d’erreurs etc.. pas besoin de stocker des static dans la classe pour stocker ces infos également, c’est pratique :)

    EKA :)

  14. D’accord, eka, je vais aller faire un tour dans ton framework. C’est vrai que la réflexion en actionscript c’est une drôle d’affaire…
    Si ton ConstructorUtil rempli bien sa tache, je te l’emprunterai.

    Pour ma part, j’ai pris la décision de faire hériter toutes les classes de mon travail d’un BasicClass, qui gère notamment les toString, erreurs, et fonctions par défaut (clone, compare…). Si tu fais mieux, j’adopte ;)

    Mais par contre, eka, ce qui me manque dans ton travail, c’est son orientation générale.
    Je crois depuis le début que vegas == ssas.
    Je m’aperçois que ce n’est pas forcément le cas.

    Je lis en ce moment “Java, plus simple, plus rapide”
    J’ai toujours peur de prendre un framework disproportionné par rapport à mon projet.
    Mais le fait de ne pas trop saisir l l’axe de vegas, ne m’a pas aidé.

    C’est pareil d’ailleurs pour pixlib que je commence à cerner, ou encore aslib qui rempli tellement de taches que l’on s’y perd.
    A mon avis, un framework doit avoir un orientation bien déterminée. S’il répond à plusieurs taches trop disparates, il oblige une utiilsation parcéllaire voire fortuite.
    Cela serait dommage de tomber dans les excès des libs java, voir Spring et hibernate comme décision de desighn plutôt que les entreprise java beans.

  15. Ma révérence à ce billet et son auteur qui ont su cerner les finesses (bluffant!!!) de la partie architecturale de pixlib. Well done mike, renversant ! :)

  16. Hello :)

    @erixtekila

    Justement Vegas est un framework de base et ensuite tu as des extensions comme Asgard pour gérer tout le reste :)

    Vegas c’est avant tout :

    - la base du framework avec le package core

    - les structures de données dans le package data (Abstract Data Type) avec les Collections, Map, etc.. qui sont nécessaires pour toute la structure du framework.

    - le système événementiel avec le package events

    - le système de Log basé sur le système événementiel dans le package logging

    - la gestion des erreurs dans le package errors basé sur le système de Log

    - Des utilitaires dans le package util et des classes pour manipuler les chaines de caractères dans le package string

    J’aurai pu faire à ce niveau là plusieurs “framework” mais tous ces packages se croisent ou nécessitent une dépendance forte à un autre package ! Donc je pense avoir mesurer le minimum vital dans ce Framework et je peux te dire que j’ai fait beaucoup de découpage depuis le début du projet.

    Ensuite il est vrai que j’ai presque fini de coder la version SSAS de Vegas car le but au final est d’avoir un framework polymorphe à celui de l’AS3 et qui peut s’utiliser aussi bien dans une application Flash que SSAS ou Javascript (c’est la même chose)

    Donc rien de disparatre dans Vegas.. juste ce qu’il faut pour créer une base au niveau des Applications avec tout ce qu’il faut pour rendre homogène le code.

    Ensuite tu as par exemple Asgard qui est le framework spécifique à la réalisation d’UI avec des gestionnaires de chargements de données basé sur JSON, EDEN, etc.. avec un package sur les transitions, etc.. etc. mais attention ASGARD lui peut évoluer (là c’est juste une version 0.1) et se diviser ensuite en plusieurs frameworks plus indépendant… il existe déjà une sous extension de Asgard qui se nomme Lunas mais qui arrivera quand Asgard sera stable complètement. Lunas est un framework de composant qui existe aussi pour Pixlib avec le framework Neo…

    Bref beaucoup de boulot qui me permet de bien évoluer dans mon code avec peut être d’ici peu un vrai changement d’orientation avec le projet SOLO qui m’intéresse encore plus que ce que je suis en train de faire en ce moment et qui permettrait à une équipe de développeur de créer un framework OpenSource utile pour tout le monde :)

    Pour conclure, le mieux, c’est d’utiliser Vegas et ensuite on voit vite ce qu’il permet de faire :) Il y a assez d’exemple dedans maintenant pour cerner l’essentiel. Ensuite c’est pour moi indispensable d’essayer aussi Pixlib etc… Tout est bon à prendre à mon avis dans le boulot de chacun :)

    EKA :)

  17. Salut.
    Je voulais savoir ou il serait possible de choper la version alpha pour les classes remoting.
    Car ton billet est vraiment interressant et je souhaiterai mettre en oeuvre cela ds une api que je dois faire utilisant aussi sushi…

    Merci merci :)

  18. Hope you get the joke above… Rereading it it’s not so clear :)
    Anyway, I’m wainting to see those classes… (I hope so)

  19. Salut Xavier,

    Tu pourras trouver le package remoting pixlib ici (alpha)

    Hope you get the joke above

    I didn’t. Could you try one more time :lol: ?

  20. Thx for the link.
    Nevermind for the joke…
    And be prepared, I’m doing an email for the pixlib mailing list dealing with your tuts.
    Hope you could clear things a bit :)
    Cheers
    Xavier

  21. Ok I have small question here.
    In your tut, in the GetOrders.as command in the onResult function, we’re calling the onUpdate function of the Model.
    This function in the model is doing nothing else than broadcasting the event onUpdateOrderList to the view regestered.
    Just asking if we could skip a step and call the function onUpdateOrderList directly from one of the command.

    Why here braodcasting to the model which is braodcasting to the view then???
    You don’t want to use reference to other view / object ?

  22. True.

    As explained in the article, in the command classes you can also use ViewHelper/ MovieClipHelper to interact with your views.

    [as]
    // GetOrder.as

    //import com.bourre.core.Model;
    //import sushi.models.SUSHIExpert;
    //import sushi.models.ModelList;

    import com.bourre.visual.MovieClipHelper
    import sushi.uis.UIList;
    import sushi.uis.SUSHIListUI;

    // … /…

    public function onResult( e : BasicResultEvent ) : Void
    {
    //SUSHIExpert(Model.getModel( ModelList.SUSHI_EXPERT )).onUpdate( e.getResult() );
    SUSHIListUI(MovieClipHelper.getMovieClipHelper(UIList.SUSHI_List)).onUpdateOrderList( e.getResult() );
    }
    [/as]

    Pixlib give us this FLEXibility ;) .

    I use ModelLocator for the purpose of the article. I wanted to show it in action.

    More generally and personally, as a RIA grows, the strategy I would recommend is the ModelLocator strategy. It helps keeping the code disciplined (not mentionned this is the place to store your state).

    But It just depends on you personal needs or design choices and the application complexity.

  23. Very good article. Thanks for sharing!

  24. Just a question: Haven’t you made the source files available for download!? I’m searching but can’t find it! :(

  25. Ooops… sorry, just found it now :P


Deja un comentario


Bad Behavior has blocked 177 access attempts in the last 7 days.