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]
1  Announcements and General Discussion / Architecture / Module->Core: Sharing instances vs. sharing classes across cores on: August 25, 2016, 12:36:39
Hi,
this might be also already discussed in the past so sorry for asking again ;-)

In a lot of cases it's necessary to share e.g. login information across all cores.
I wonder if it's better to share a LoginProxy instance that resides in the shell or if it's better to share the LoginProxy class,
let each core create its own instance and just inject the LoginProxy data to the new instance.

[1] Share instance:
// Retrieve login proxy from shell and access login data directly
var shell:IFacade = Facade.getInstance(SharedConstants.SHELL);
var loginProxy:LoginProxy= shell.retrieveProxy(LoginProxy.NAME) as LoginProxy;
:
// Retrieve login proxy from shell and access login data directly
var shell:IFacade = Facade.getInstance(SharedConstants.SHELL);
var loginProxy:IProxy= shell.retrieveProxy(SharedConstants.LOGIN_PROXY) as IProxy;
var loginVO:LoginVO = loginProxy.getData() as LoginVO;


[2] Share class:
:
// Retrieve login proxy from shell, register new login proxy instance within this core and inject loginVO
var shell:IFacade = Facade.getInstance(SharedConstants.SHELL);
var loginProxy:LoginProxy = new LoginProxy(LoginProxy.NAME, shell.retrieveProxy(LoginProxy.NAME).getData() as LoginVO)
facade.registerProxy(loginProxy);
var loginVO:LoginVO = loginProxy.getData() as LoginVO;

Or would it be generally a bad idea to retrieve the shell from another core doing it this way?

Thanks in advance,
Olaf

2  Announcements and General Discussion / Architecture / Notify cores from shell by sending a notification using its particular facade on: August 19, 2016, 06:38:22
Hi,
I just stumbled over an old question wich probably was already discussed in the past.

However, from the shell I'd like to inform all "registered" cores with the same information and wonder if it has any drawbacks
to just loop over the core instances and call the sendNotification() method of their particular facades:

E.g. we could have a "cors getter" inside the shell facade to make the core instances accessible and a command "NotifyCores" that resides in the shell:

ShellFacade.as:
:
public class ApplicationFacade extends Facade
{
        ...

/**
        * Make cores accessible
        */
public function get cors():Array {
   return instanceMap;
        }
}

NotifyCoresCommand.as:
:
public class NotifyCoresCommand extends SimpleCommand
{
override public function execute(note:INotification):void {
                // E.g. use the "type" property to pass the notification name
                var type:String = note.getType();
                
for each(var core:IFacade in ApplicationFacade(facade).cors) {
core.sendNotification(type, note.getBody() );
}
}
}

This would make the "shell->cores" communication very easy without involving the view using interfaces or using the pipes utility.
The only thing that the shell and the other cores has to share would be the note name (Like the "message" in the pipes utility, if I remember it correctly).

Are there any concers with this approach?

Thanks,
Olaf
3  Announcements and General Discussion / General Discussion / New designed web page on: August 12, 2016, 12:56:47
Very nice! Simple and clean as the framework itself ;-)
Thanks for keeping up the great work on PureMVC Cliff.

Olaf
4  Announcements and General Discussion / General Discussion / Mediator: How to get rid of the flash.events.Event dependency? on: March 22, 2016, 12:44:24
Hi,
I've doing some tests using PureMVC with FlexJS and it seems that it works fine.
(If it makes sense I'll publish a PureMVC FlexJS version as soon as I'm able to create a swc of it)

What I'm currently trying to achive is to outsource the complete business logic to a pure AS3 lib using PureMVC.
My goal is to be able to switch between the "Flex standard SDK" and "FlexJS" without changing any line of the business logic. So the business logic has to be free of any flash or flex dependencies.

Cause the mediators main purpose is to handle view events it has a depenency to flash.events.Event (or org.apache.flex.events.Event for FlexJS).
To resolve the dependency to the view itself I'm using interfaces and that works fine.
But the interface itself also has currently a dependency to IEventDispatcher.

So I'm searching for a solution that makes the business logic flash/flex free while putting as much code as possible to it. In best case the app that uses the "business logic lib" tells the lib which kind of Event implementation it has to use respectively pass the 'right' Event implementation to it... some kind of a switch.

One solution that comes in my mind is to extend the concrete mediator, overwrite all methods that depends on Event and make it part of the app that uses the lib. But this would mean additional code.

Any ideas how to achive this much more elegant?

Thanks,
Olaf


:

// How to get rid of it?
import flash.events.Event;
//import org.apache.flex.events.Event;

public class MyMediator extends Mediator implements IMediator
{
    public static const NAME:String = 'ApplicationMediator';
    
    public function ApplicationMediator(component:IViewMyView) {
        super(NAME, component);
    }

    override public function onRegister():void {
super.onRegister();

         view.addEventListener(ApplicationEvents.DO_SOMETHING, onDoSomething);
    }

    // How to get rid of Event?
    private function onDoSomething(event:Event):void {
    }

    public function get view():IViewMyView {
        return viewComponent;
    }
}

:

// How to get rid of IEventDispatcher?
import flash.events.IEventDispatcher;
//import org.apache.flex.events.IEventDispatcher;

public interface IViewMyView extends IEventDispatcher
{
    function setData(data:String):void;
}
5  Announcements and General Discussion / General Discussion / Usage of Undo Utility on: February 01, 2016, 07:05:19
Hi,
I've just stumpled over the "Undo Utility" and took a quick look inside it.
To get it work, is the only thing to take care of the extension of the "UndoableCommandBase" for undoable commands?

If I'd like to use it with multicore, is it sufficient to replace the libs standard imports by the multicore ones?

Thanks for help,
Olaf
6  Announcements and General Discussion / Architecture / Inter-core communication by implementing sendMessage() method in Facade.as on: August 15, 2013, 02:23:16
Hi,
I'm still struggling with inter-core communication and just wondering if we not could simply add a "sendMessage()" method to the Facade.as.
This method forwards it's message by calling the sendNotication() method for the passed or all registered cores. At the end each core could listen to notifications(messages) that was triggered by other cores.
To avoid conflicts between notification names and message names we coud define a seperate common file for the message constants with it's own "namespace":

MessageConstants.as:
:
public class MessageConstants
{
public static const TEST1:String   = 'msg/Test1';
public static const TEST2:String  = 'msg/Test2';
}

The modified org.puremvc.as3.multicore.patterns.facade.Facade.as:
:
/**
* Send notification (message) to other cores
* @param notificationName the name of the notiification to send
* @param body the body of the notification (optional)
* @param type the type of the notification (optional)
* @param coreId the multitonKey of the receiver core, sends message to all registered cores by default (optional)
*/
public  function sendMessage(messageName:String, body:Object, type:String, coreId:String="*"):void
{
if(coreId=="*"){
for(var multitonKey:String in instanceMap)
{
                        // Send notification to each core
instanceMap[multitonKey].sendNotification(messageName, body, type);
}
}
else{
if(hasCore(coreId))
{
// Send notification to passed core
instanceMap[coreId].sendNotification(messageName, body, type);
}
}
}

Usage:
:
// Send message to all registered cores
facade.sendMessage(MessageConstants.TEST1, "I am a message for all cores");

// Send message to core "Test"
facade.sendMessage(MessageConstants.TEST1, "I am a message for the 'Test' core only", null, Test.NAME);

What do you think about it?

Thanks
Olaf
7  Announcements and General Discussion / Architecture / Multicore communication by using interfaces on: July 25, 2013, 09:03:54
Hi,
I use the PipesUtil a lot and my experience is, that for me it is very hard to keep the survey.
Moreover the addidtional code is a bit annoying.
In general my impression is that by using the standard PureMVC version it is hard to keep the survey over all the notifications and by using the muticore version it is hard to keep the survey over all the plumbing and module communication.

So I asked myself what is the "smaller evil" and do I really need the multicore architecture?
At least I don't need "real modules" that behave like an application or could execute standalone and I don't need 100% decoupled modules.
But I definitely like it to split my applications in differents cores and have all the other benefits of the multicore architecture.

So I'm searching for an easier way to communicate with modules, perhaps by using interfaces?
I've take a look at the modularity demo but I don't feel comfortable with it.
Probably my programming experience is not enough to understand all the things inside.

My understanding is as following:
Module A provides an interface e.g. "IModuleA.as".
Module B would like to communicate with Module A and so it has to implemet "IModuleA.as".
But wich component of Module B should implement the interface?
Should it be a view component or should it be an own class like the "Pipes JunctionMediator" acting as
an class that handles the communication only?

Thanks for help!
Olaf
8  Announcements and General Discussion / General Discussion / Is the Eclipse Pureclipse plug-in still available? on: March 04, 2013, 04:40:10
Hello,
does anybody know, if the Pureclipse extension is still available?
It seems that the project website http://www.slide.name/pureclipse/ is offline.

Olaf
9  Announcements and General Discussion / General Discussion / Is there a Bug in pipeworks demo? on: February 27, 2013, 11:35:38
Hello again,
while debugging the pipeworks demo again and again to understand all the things inside I'm wondering if there's a bug in the PrattlerModuleMediator.as.

My understanding is that after the FeedWindow's close event was fired we should only remove the module mediator of this concrete instance.
But the notification handler removes all registered instances?!

:
/**
* Handle PrattlerModule related Notifications.
* </P>
* Remove the application-level references to the module instance.
* Note that the module itself will also be listening for the
* window close and will do it's own internal cleanup to ensure
* that the instance can be garbage collected.</P>
*/
override public function handleNotification( note:INotification ):void
{
switch( note.getName() )
{
case  ApplicationFacade.REMOVE_FEED_WINDOW:
viewComponent = null;
var mediatorName:String = this.getMediatorName();
facade.removeMediator(mediatorName);
sendNotification(LogMessage.SEND_TO_LOG,"Removed window from shell.",LogMessage.LEVELS[LogMessage.DEBUG]);
break;
}
}


Should do something like this instead of the origin coding, or am I on the wrong track?:

:
/**
* Handle PrattlerModule related Notifications.
* </P>
* Remove the application-level references to the module instance.
* Note that the module itself will also be listening for the
* window close and will do it's own internal cleanup to ensure
* that the instance can be garbage collected.</P>
*/
override public function handleNotification( note:INotification ):void
{
switch( note.getName() )
{
case  ApplicationFacade.REMOVE_FEED_WINDOW:

if(viewComponent.getID() == note.getBody().moduleName as String)
{
viewComponent = null;
var mediatorName:String = this.getMediatorName();
facade.removeMediator(mediatorName);
sendNotification(LogMessage.SEND_TO_LOG,"Removed window from shell.",LogMessage.LEVELS[LogMessage.DEBUG]);
}
break;
}
}

Thanks for help!
Olaf
10  Announcements and General Discussion / Architecture / Multicore -> Pipes -> 'Submodules' on: February 14, 2013, 02:54:24
Hi,
after switching to Multicore and adding the PipesUtility by implementing the ideas of the PipeWorks demo
there remain some questions regarding 'submodules'.
I've read a lot in this forum regarding this issue but at least I don't understand it.

Imagine we'd like to extend the the PrattlerModule (from the PipeWorks demo) with more features.
For instance there is a navigation tree with some items that offers some more complex functions (in prattler context).
To be encapsulated we would like to build an own core for each function.
So here a function is something like a 'submodule' but of course each submodule should be independent and self-contained.

How we could solve this by using pipes?

Is this a appropriate way:
A PrattlerSkeletonModule implements the 'main' module frame including the navigation.
A PrattlerModuleX implements the current PrattlerModule features as 'submodule'.
A PrattlerModuleY implements new Prattler feature(s) as 'submodule'.
A PrattlerModuleZ implements more new Prattler feature(s) as 'submodule'.
...

By requesting the Prattler from the shell, the PrattlerSkeletonModule is delivered.
After this the PrattlerSkeletonModule request the default module, e.g. PrattlerModuleX from the shell and displays it.
By clickling a navigation item inside the PrattlerSkeletonModule the suitable module is requested by the PrattlerSkeletonModule and the shell will deliver this to the PrattlerSkeletonModule to display it.
(Or should the PrattlerSkeletonModule deliver the requested module directly, without involving the shell? )
Each Module(core in this case) is connected by own pipes from the shell to itself and vice versa.

Would it basically a good idea that some cores are connected directly with each other without involving the shell?

Thanks for help!

Olaf


 
11  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





12  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
13  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;
                    }
                }
            }
        }

14  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);
}
}


Pages: [1]