Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Show Posts

* | |

  Show Posts
Pages: 1 2 [3]
31  Announcements and General Discussion / Architecture / Re: Multicore questions on: February 08, 2013, 01:07:10
Cliff, your continuous support over years by now is unbelievable, many thanks!
There a lot hints inside your answer that I have to grapple with, hope I'll get a better understanding of all these things.

One simple question:
In pipes context there's an extensive usage of the word "plumb/plumbing".
The german translation(s) are not comprehensible within the context for me.
Could you describe what is meant with this?

Thanks!

Olaf
32  Announcements and General Discussion / Architecture / Multicore questions on: February 07, 2013, 01:12:16
Hi,
I'd like to move from standard to multicore version.
After reading a lot of posts in this forum and some blog articles I've got more and more questions.
Simply changing the flex project from standard to multicore seems easy.
But unterstanding the wohle concept and transfer it to my application to get an handsome architecture seems not so easy.
Perhaps there's anybody out there who could ligten me ;-)

I'm building a tab based flex application, here're my questions:

1) More than one shell core inside a multicore project?
There is a skeleton with some navigation buttons and common functions.
In multicore context this would be the 'shell', right?
Inside this 'shell' the user could open different tabs wich will be place inside a view stack.
A tab is like a module and provides different views with different functionalities and it's own tab related navigation. Should be each tab have it's own shell core? Or should each tab 'submodule' including the tab skeleton be represented by a core?

2) How granular-> how many cores in a multicore project?
I've read one benefit using multicore is to be able to create unit tests in a proper way.
But what should we define as a unit, my understanding is that one core represents a unit.
Within an application there could be tons of functions, modules, submodules... units after all.
As a result of this we would have tons of cores inside a project. Is there a limitation for the number of cores inside a project?

3) Shared proxies
In my application each tab has references to same proxies.
E.g. one tab provides a userlist and another tab displays detailed informations of one user. So both tabs have a reference to the 'UserCollectionProxy' and both could manipulate the proxy. How this works with the multicore version? Should this be done by using pipes?
I know the best way is to have 100% encapsulated modules, but I think this doesn't work in real life!?

4) 'Dynamic' cores
To make sure that each view/mediator inside a tab handles the right notifications I make an extensive usage of notifications type parameter by passing an unique id with it. Sometimes this is a bit confusing.
Is it right that by using the multicore version I'll don't have to pay attention to this cause within multicore each core have an unique id?

5) EmployeeAdmin multicore demo?
For me it would be helpful if the EmployeeAdmin demo would be available as multicore demo.
Are there any examples like this out there?

Many many thanks for reading this and sorry for my bad english;-)

Kind regards
Olaf





33  Announcements and General Discussion / General Discussion / Re: PureMVC Vs parsley on: September 06, 2011, 06:45:57
Many thanks Cliff!!!
Your support is still unbelivable, I really appreciate it.

Olaf
34  Announcements and General Discussion / General Discussion / Re: PureMVC Vs parsley on: September 01, 2011, 02:55:37
Hey Cliff,
one question regarding your eyample above:
I've a Collection Proxy that get it's data from a remote server.
The proxy data object is an ArrayCollection.
Now I'd like to get different extracts of the data object e.g. by using the method getMyCollectionByStatus(id:String) and also re-load a part of the data object by using e.g. the method loadMyCollectionByStatusService(id:String). In the first case the id is passed to the method and will be forwarded to the notification.
But what should I do in the second case if I invoke an server side method asynchronous?

Many thanks in advance
Olaf


:
public class MyCollectionProxy extends Proxy
{
public static const NAME:String = 'MyCollectionProxy';

public function MyCollectionProxy(proxyName:String)
{
super(proxyName);
}

override public function onRegister() : void
    {
                        //...
    }


public function getMyCollectionByName(id:String):ArrayCollection
{
                        var data:ArrayCollection;

                        // ...
                        // ... get data by Name
                        // ...
sendNotification(ApplicationFacade.LOAD_DATA_SUCCESS, data, id);
}

public function getMyCollectionByStatus(id:String):ArrayCollection
{
                        var data:ArrayCollection;
                        // ...
                        // ... get data by Status
                        // ...
sendNotification(ApplicationFacade.LOAD_DATA_SUCCESS, data, id);
}


public function loadMyCollectionByStatusService(id:String):void
{
                        // ...what should we do with the passed id?
                        //

var delegate:MyService = new MyService( new Responder( onLoadDataService, onLoginFaultService ) );
delegate.loadDataByStatus();
CursorManager.setBusyCursor();
}

public function onLoadMyCollectionByStatusService(event:ResultEvent):void
{
                       
CursorManager.removeBusyCursor();
var result:ArrayCollection= event.result as ArrayCollection;
                        setData(result);

                        //
                        // ...where should we get the id
                        //

sendNotification(ApplicationFacade.LOAD_DATA_SUCCESS, result, id);
}
}

:
         public static const NAME:String = "MyViewMediator";

         public function MyViewMediator( viewComponent:MyView )
         {
            super( getMediatorNameForID( viewComponent.id ), viewComponent );
         }

         public function getDataByStatus():void
         {
            // this will call the registered Command (inside the Command we invoke the proxy remote call)
            sendNotification(ApplicationFacade.LOAD_DATA_BY_STATUS, false, id);
         }
35  Announcements and General Discussion / Architecture / Re: SuperTabNavigator + Proxy consistency + RemoteServices + Binding on: November 13, 2010, 08:08:35
I think I've got it !
Instead of modeling different proxies (e.g. CarCollectionProxy and CustomerCarsProxy) that handles the same kind of ArrayCollection at least, I'll just have one CarCollectionProxy. This proxy implements various service methods to get the data from the backend.
Each dynamically created tab (view) will registered it's own instance of CarCollectionProxy.
Each instance of CarCollectionProxy could contain different collections of CarVO.

If any commad calls the updateCarService() method from any CarCollectionProxy instance, the CAR_UPDATE_SUCCESS notification is fired.
Each mediator who is interested in, updates it's own instance of CarCollectionProxy proxy.
Cause we don't check the concret id/type when handling the notification, we could feel confident, that every instance of CarCollectionProxy would be updated !

Hope that's it  ;)


CarFormMediator:
:
public function onUpdateCar( event:Event ):void
{
   carProxy.updateCarService( carForm.carVO, id );
}
...
override public function handleNotification( note: INotification ):void
{
   var type:String = note.getType() as String;
   var carVO:CarVO = note.getBody() as CarVO;

       switch ( note.getName() )
       {
           case ApplicationFacade.CAR_UPDATE_SUCCESS:
              if( type==id  )
              {

              }
              // we don't check the id/type, cause we want to make sure that each instance of
              // CarCollectionProxy will updated !
              carCollectionProxy.updateItem( carVO );
              break;
       }
}
...

CarCollectionProxy:
:
...
public function get cars():ArrayCollection
{
    return data as ArrayCollection;
}
...
public function updateItem( carVO:CarVO ):void
{
   for ( var i:int=0; i<cars.length; i++ )
   {
      if ( cars[i].id == carVO.Id )
      {
          cars[i] = carVO;
          break; // exit loop
      }
   }
}
...
public function updateCarService( carVO:CarVO ):void
{
   CursorManager.setBusyCursor();
   var delegate:CarServiceDelegate = new CarServiceDelegate( new Responder( onUpdateCarService, onFault ) );
   delegate.updateCar( carVO );
}

public function onUpdateCarService( event:ResultEvent ):void
{
   CursorManager.removeBusyCursor();
   var carVO:CarVO = note.getBody() as CarVO;
   updateItem( carVO )
   sendNotification( ApplicationFacade.CAR_UPDATE_SUCCESS, carVO , id );
}

public function getAllCarsService():void
{
   CursorManager.setBusyCursor();
   var delegate:CarServiceDelegate = new CarServiceDelegate( new Responder( onGetAllCarsService, onFault ) );
   delegate.getAllCars();
}

public function onGetAllCarsService( event:ResultEvent ):void
{
   CursorManager.removeBusyCursor();
   this.setData( event.result as ArrayCollection);
   sendNotification( ApplicationFacade.GET_ALL_CARS_SUCCESS, cars , id );
}

public function getUserCarsService():void
{
   CursorManager.setBusyCursor();
   var delegate:CarServiceDelegate = new CarServiceDelegate( new Responder( onGetUSerCarsService, onFault ) );
   delegate.getUserCars();
}

public function onGetUserCarsService( event:ResultEvent ):void
{
   CursorManager.removeBusyCursor();
   this.setData( event.result as ArrayCollection);
   sendNotification( ApplicationFacade.GET_USER_CARS_SUCCESS, cars , id );
}

36  Announcements and General Discussion / Architecture / Re: SuperTabNavigator + Proxy consistency + RemoteServices + Binding on: November 12, 2010, 11:37:25
Hello again,
thinking about the problem on my way home I can say why I don't feel comfortable with the solution above:
Cause this is a tab based application numerous proxies could be instantiated during the user is working with it.
For Example:
Each tab that represents a customer instantiates a CustomerCarsProxy object.
To keep all these proxies up-to-date, we have to take care of all instances of this proxy.
May the solution be to update each instance of all related proxies ?
Is there a possibility to get all instances of registrated proxies ?

Thanks again
Olaf
37  Announcements and General Discussion / Architecture / Re: SuperTabNavigator + Proxy consistency + RemoteServices + Binding on: November 12, 2010, 09:59:20
Thanks for your reply Cliff but I think I don't get it yet.
I've created some fictitious code below that implements my "car rental service" example fragmentary.

My main question is, if it's the right or elegant way to have multipe, identical carVO's in different proxies.
And if this is a normal way, what do you think about the CarFormMediator solution. The CarFormMediator is responsible (in this course of action) to keep all related proxies up-to-date ?

Don't know why, but I don't have a good "feeling" with this but no other ideas.
If the general opinion is, that this solution is definitely ok, then I've to adjust my feeling :D
But currently I need somebody who can give me a leg-up... ???

CarFormMediator:
:
...
public function onUpdateCar( event:Event ):void
{
   carProxy.updateCarService( carForm.carVO, id );
}
...
override public function handleNotification( note: INotification ):void
{
   var type:String = note.getType() as String;
   var carVO:CarVO = note.getBody() as CarVO;

       switch ( note.getName() )
       {
           case ApplicationFacade.CAR_UPDATE_SUCCESS:
              if( type==id  )
              {
                   // take care of the proxy consistency and update all related proxies !
                   carCollectionProxy.updateItem( carVO );
                   customerCarsProxy.updateItem( carVO );
              }
              break;
       }
}
...

CarProxy:
:
...
public function get carVO():CarVO
{
    return data as CarVO;
}

public function updateCarService( carVO:CarVO, type:String ):void
{
    // keep the id of the calling component in mind
    _type = type;

   CursorManager.setBusyCursor();
   var delegate:CarServiceDelegate = new CarServiceDelegate( new Responder( onUpdateCarService, onFault ) );
   delegate.updateCar( carVO);
}

public function onUpdateCarService( event:ResultEvent ):void
{
   CursorManager.removeBusyCursor();
   this.setData( event.result as CarVO );
   sendNotification( ApplicationFacade.CAR_UPDATE_SUCCESS, this.carVO , _type );
}
...

CarCollectionProxy
:
...
public function get carCollection():ArrayCollection
{
    return data as ArrayCollection;
}
...
public function updateItem( carVO:CarVO ):void
{
   for ( var i:int=0; i<carCollection.length; i++ )
   {
      if ( carCollection[i].id == carVO.Id )
      {
          carCollection[i] = carVO;
          break; // exit loop
      }
   }
}
...

CustomerCarsProxy:
:
...
public function get customerCars():ArrayCollection
{
    return data as ArrayCollection;
}
...
public function updateItem( carVO:CarVO ):void
{
   for ( var i:int=0; i<customerCars.length; i++ )
   {
      if ( customerCars[i].id == carVO.Id )
      {
          customerCars[i] = carVO;
          break; // exit loop
      }
   }
}
...
38  Announcements and General Discussion / Architecture / SuperTabNavigator + Proxy consistency + RemoteServices + Binding on: November 11, 2010, 06:04:02
Hello,
I've some problems to find a good architecture for a SuperTabNavigator based application.
The basics regarding the tabs and dynamically proxy/mediator creation/registration are clear.
(Described in this post: http://forums.puremvc.org/index.php?topic=596.msg2626#msg2626 )

To explain the problem assume we'd build an SuperTabNavigator based application for a car rental service:

Please imagine following course of action:

First Tab "Cars":
We open a first tab named "Cars" that display's all available cars of our car rental service.
With opening the tab we dynamically create and register a "CarListMediator" and a "CarCollectionProxy" with unique id's.
The data came from a Remote Service, the RemoteService returns an ArrayCollection of CarVO
and populates the "CarCollectionProxy" data object. The data grid's data provider is bound to the model, it's all fine.

Second Tab "Customers":
We open a second tab named "Customers" that display's all customers of our car rental service.
With opening the tab we dynamically create and register a "CustomerListMediator" and a "CustomerCollectionProxy" with unique id's.
The data came from a Remote Service, the RemoteService returns an ArrayCollection of CustomerVO
and populates the dynamically created "CustomerCollectionProxy's" data object. The data grid's data provider is bound to the model, it's all fine.

Third Tab "Peter Miles":
We double click the customer "Peter Miles" that is listet in the second tab "Customers".
This action opens a third tab named "Peter Miles" that displays detailed informations of "Peter Miles" inside a form and a history of all cars that he ever rent until now inside a DataGrid.
With opening the tab we dynamically create and register a "CustomerFormMediator", "CustomerCarsListMediator" and a "CustomerProxy" and "CustomerCarsProxy" with unique id's. To make sure that the displayed data are up-to-date (perhaps an other logged-in user has modified the customer data) we call an other RemoteService that returns a CustomerVO and populates the CustomerProxy data object.
Moreover we get all cars that ever rent by the customer as an ArrayCollection of CarVO from a RemoteService wich poulates the "CustomerCarsProxy's" data object.

Fourth Tab "Ford Mustang":
We double click the car "Ford Mustang" that is listet in the first first tab "Cars".
This action opens a fourth tab named "Ford Mustang" that displays detailed information of the "Ford Mustang" (e.g. the mileage) inside a form and a list of all customers that ever rent this car until now inside a DataGrid.
With opening the tab we dynamically create and register a "CarFormMediator", "CarCustomersListMediator" and a "CarProxy" and "CarCustomersProxy" with unique id's. To make sure that the displayed data are up-to-date (perhaps an other logged-in user has modified the car data) we call an RemoteService that returns a CarVO and populates the "CarProxy's" data object.
Moreover we get all customers that ever rent the "Ford Mustang" as an ArrayCollection of CustomerVO from a RemoteService wich poulates the "CarCustomersProxy's" data object.

Now we modify the milage value inside the "Ford Mustang" tab e.g. from 15300 to 15400.

To update our backend with this new milage value we call a RemoteSercice "UpdateCar".

And here's my question:
To keep all the data in different tabs and proxies consitency and up-to-date, we must update the "CarProxy", the "CarCollectionProxy" and the "CustomerCarsProxy" with our modified CarVO.

What's the best way to to this ?
Or is the proxy model as described above not the best one  ?
Is it a good idea to keep the data redundant in the different proxies ?

I've take a look at RoleProxy inside the EmployeeAdmin's Demo, but I think this solution doesn't work here, cause we need different views to the data.

Sorry for the mass of text, hope you understand my problem.
Perhaps there's anybody out there who can help !

Many thanks in advance
Olaf
39  Announcements and General Discussion / Public Demos, Tools and Applications / Re: EmployeeAdmin Demo: Why don't use method removeRoleFromUser() any notification ? on: November 05, 2010, 12:58:13
Many thanks for this detailed answer Cliff !

So, this means that following lines of code only demonstrates the notification handling, but
aren't really neccessary cause rolePanel.userRoles is bound to the model, right ?
Perhaps it's a good idea to remove this completely from the demo or to place a short comment to avoid confusion ?

RolePanelMediator.as:
:
case ApplicationFacade.ADD_ROLE_RESULT:
rolePanel.userRoles = null;
rolePanel.userRoles = roleProxy.getUserRoles( rolePanel.user.username );
break;

Great work, keep up this incredible engagement Cliff !
40  Announcements and General Discussion / Public Demos, Tools and Applications / EmployeeAdmin Demo: Why don't use method removeRoleFromUser() any notification ? on: November 02, 2010, 01:45:50
Hi,
can anybody help me to understand the following:
By adding a new role to the selected user, addRoleToUser() is called and the role proxy sends a notification, the RolePanelMediator handles the ADD_ROLE_RESULT notification and updates the view... that's clear !

By removing a role from the selected user, removeRoleFromUser() is called but no notification is send and the view is update anyway... seems through some binding ?

My Questions:
1)
I don't understand this binding, for me it seems something like voodoo.
The removeRoleFromUser() method manipulates the local userRoles ArrayCollection. Why has this manipulation an effect to the view at least ?
2)
Is it a good practise using in the first (add role) case a notification and in the second (remove role) not ?

Many thanks for help in Advance, hope my questions arent's so stupid ;-)

Olaf



RoleProxy.as
:
       // add a role to this user
        public function addRoleToUser( user:UserVO, role:RoleEnum ) : void
        {
            var result:Boolean = false;
            if ( ! doesUserHaveRole( user, role ) ) {
                for ( var i:int=0; i<roles.length; i++) {
                    if ( roles.getItemAt(i).username == user.username ) {
                        var userRoles:ArrayCollection = roles.getItemAt(i).roles as ArrayCollection;
                        userRoles.addItem( role );
                        result = true;
                        break;
                    }
                }
            }
            sendNotification( ApplicationFacade.ADD_ROLE_RESULT, result );
        }

RolePanelMediator.as
:
       override public function handleNotification( note:INotification ):void
        {

            switch ( note.getName() )
            {
                ...
                    
                case ApplicationFacade.ADD_ROLE_RESULT:
                    rolePanel.userRoles = roleProxy.getUserRoles( rolePanel.user.username );
                    rolePanel.reset();
                    break;
                    
            }
        }



RoleProxy.as
:
       // remove a role from the user
        public function removeRoleFromUser( user:UserVO, role:RoleEnum ) : void
        {
            if ( doesUserHaveRole( user, role ) ) {
                for ( var i:int=0; i<roles.length; i++) {
                    if ( roles.getItemAt(i).username == user.username ) {
                        var userRoles:ArrayCollection = roles.getItemAt(i).roles as ArrayCollection;
                        for ( var j:int=0; j<userRoles.length; j++) {
                            if ( RoleEnum( userRoles.getItemAt(j) ).equals( role ) ) {
                                userRoles.removeItemAt(j);
                                break;
                            }
                        }
                        break;
                    }
                }
            }
        }

41  Announcements and General Discussion / Architecture / Re: How to handle/manipulate (hierachical) VO's and remote proxies on: January 19, 2010, 07:01:32
hey cliff,
thanks... it becomes a bit more clear for myself !
the 'smart vo' sounds interesting.

olaf
42  Announcements and General Discussion / Architecture / How to handle/manipulate (hierachical) VO's and remote proxies on: January 15, 2010, 08:00:48
Hi,
I've some general questions regarding handling VO's and remote proxies:

1)
VO's are used for server side communication and the VO's represents the data model, right ?
I've often read that VO's should contain only properties, no methods. Is it still a good way to implement also some methods to manipulate the VO itself at client side ?

2)
Is it the right way to pass a reference of an VO to the proxy data element ?

3)
Should the proxy implements some methods to manipulate the passed VO or should we use the
methods inside the VO to do this (see question 1) ... or should we use an additional "model class" ?

4)
What could we do, if we'd like to make the application able to work offline ?
Is one way to implement an additional "offline proxy" and switch between offline and online modus (proxy) ?

Hmm... seems that I'm not really able to formulate my questions in an understanding way...
perhaps you can provide some well desigend sample code for the example below ?

Many thanks in advance !
Olaf

Example:
Imagine we've a basket (BasketVO) that's able to pick up some items (ItemVO).
Inside the BasketVO we have a method "addItem()" to add an new item to the basket.
We'd like to save a new item to the remote server's database directly after e.g. clicking an "add item" button by using the "AddItemCommand".
(Following code is only an example to clarify my questions)

:

// BasketVO
public class BasketVO
{
public var userId:String;
public var items:ArrayCollection;

public function BasketVO (userId:String):void
{
              this.userId = userId;
}
 
        // adds new item to the basket
        public function addItem(item:ItemVO):void
        {
                this.items.addItem(item);
        }

}

// ItemVO
public class ItemVO
{
public var itemNo:int;
public var price:Number;
        public var count:int;

public function ItemVO ():void
{
}

        // is it a good idea to place this kind of method here ?
        public function calcSum():Number
        {
                return count*price;
        }
}

// the proxy
public class BasketProxy extends Proxy implements IProxy
{
       public static const NAME:String = 'BasketProxy';
     
       private var _basketService:RemoteObject;
       
       public function BasketProxy(userId:String)
       {
            super( NAME, new BasketVO(userId) );

            // set remote service
            _basketService = new RemoteObject();
            // ...

            _basketService.addItem.addEventListener(ResultEvent.RESULT, onAddItem);

       }

       public function get basketVO():BasketVO
       {
             return data as BasketVO;
       }

       // calls remote service to add a new item
       public function addItem(itemVO:ItemVO):void
       {
           // add item to remote basket and save item into DB
            _basketService.addItem(itemVO);
       }

       public function onAddItem(event:ResultEvent):
       {
           var returnedItem:ItemVO = event.result as ItemVO;
 
           // add item to local basket
           // is this the right way ???
           basketVO.addItem(returnedItem);

          // send notification
          // ...           
       }
}

// command that's add a new item
public class AddItemCommand extends SimpleCommand
{
override public function execute(note: INotification ) :void
{
            var itemVO:ItemVO = note.getBody() as ItemVO;

            var basketProxy:BasketProxy = facade.retrieveProxy("BasketProxy") as BasketProxy;;

            basketProxy.addItem(itemVO);
}
}


43  Announcements and General Discussion / Architecture / Re: Registering Multiple Instances of one Mediator and Proxy: A Best Practice on: September 24, 2008, 09:20:31
@JJfutbol
After studying the pureMVC docs, the forum and best practise infos I think I've got it.
My main problem was the deferred instantiation cause I've used the SuperTabNavigator as nested
component.

For anybody else who has the same problem (view comp is null by mediator registration ), here's the solution:
http://puremvc.org/content/view/91/185/
Many thanks to Cliff for the great documentation !

The "view part" of my DemoApp is working now so tomorrow I'll try to integrate WebOrb and
take a more detailed look at the proxies.

Thanks !
Olaf
44  Announcements and General Discussion / Architecture / Re: Registering Multiple Instances of one Mediator and Proxy: A Best Practice on: September 22, 2008, 08:24:57
Hello JJfutbol,
thanks for this example !
I'm new in flex and pureMVC so I'd like to ask if you'd provide a full example implementation
of this concept.
That would be very helpful for me.

Many thanks in advance.

Olaf
Pages: 1 2 [3]