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 4 5
16  Announcements and General Discussion / Architecture / Re: Bulky Modules on: June 08, 2015, 04:02:00
I've recognized following patterns while working with PureMVC and also enforced some rules on top of that in my projects.

  • Actors have very focused responsibilities
  • Modules have very focused goals

For #1, besides design I also determine by Lines of Code, an average is 65-125 LOC, anything goes beyond is a sign that design needs revision and usually gets solved by brining in another reusable actor.

For #2, If there are too many actors and module is getting bulky, that means the module needs further decomposition, therefore it gets split into another reusable module. On an average usually 3-5 Actors/Commands per module.

Under REST application I'm finding #2 hard to implement as there are too many operations just for a single entity, ending up with 9 Commands in this case. I reduced the clutter at least for the eye by moving the crud based operations into a separate folder (crud) for each module and here's the diagram. (9 Commands in red)
17  Announcements and General Discussion / Architecture / Bulky Modules on: June 06, 2015, 10:03:04
In context of a REST based server multicore app (node.js, express.js), the application under progress is getting bulky and complex because of too many operations involved within each module and since all these operations are related to this single entity (database entity) it doesn't feel intuitive to split them out into several submodules, (besides I've several modules already for other entities).

Starting with 4 CRUD operations (GET, POST, PUT, DELETE), for each there's an AsyncCommand with it's associated AsyncProxy. Adding PATCH support will add another couple.

On top of that some modules may require file upload, although the operation is redirected right from the RouterMediator and piped towards S3Module (Amazon S3 file storage) but then the sender module itself will require S3ResultCommand to handle results (4 kinds of results), or in other words every other module supports different actions/names and therefore requires a Command to handle those results.

Any additional requirement may force another couple of Async Command/Proxy into the module.

Every CRUD AsyncCommand (triggered from the view/RouterMediator/Router), triggers asyncAction of it's associated AsyncProxy, that pools the connection, gathers params from the body, headers, queryString etc., executes SQL, calls the the result/fault within the Proxy, releases the connection there and then responds back to the AsyncCommand so it could shuttle the results to the View layer (browser output).

So even combing above operations into fewer actors will make those actors bulky, plus there could be content negotiations factors that would require me to have different SQL calls in each actor, so I'd rather keep actors following SingleResponsibility Principle.

No problem with the View Layer though, it's pretty lightweight, a single actor ResponderMediator just listens for two notifications (RESULT/FAULT) fired from each AsyncCommands which it then outputs to the browser via Responder component.

In essence REST requirements involving several operations around each entity/resource is requiring me to have several commands and proxies for the related module and I'm not finding a way out of it.
18  PureMVC Manifold / Multicore Version / PureMVC utilities for node.js on: May 26, 2015, 01:30:35
1) Pipes
https://www.npmjs.com/package/npmvc-util-pipes

2) AsyncProxy
https://www.npmjs.com/package/npmvc-util-asyncproxy

3) AsyncCommand
https://www.npmjs.com/package/npmvc-util-asynccommand


Kudos to Robbert Streng - https://www.npmjs.com/package/npmvc
19  PureMVC Manifold / Multicore Version / PureMVC File Templates on: December 10, 2014, 09:27:53
Generated File Templates for PureMVC actors for different IDE's.

https://github.com/sshams/puremvc-templates
20  Announcements and General Discussion / Architecture / Re: handlePipeMessage function on: November 18, 2014, 10:11:46
great, so I'd let it enter the core instead of redirecting from there (I believe the shortcut-redirection in JunctionMediator was leading to this problem), and let the core decide in a command to send it to the auth core. Thanks.
21  Announcements and General Discussion / Architecture / Re: handlePipeMessage function on: November 14, 2014, 02:39:45
because not all cores or even this core requires authentication all the time and shell core can't send all messages via authentication, authentication is a complicated time consuming async process via a 3rd party.

There are apps that uses authentication core directly (response gets output in the browser) so authentication core is getting reused both for the direct as well as requests from other cores.

Here's some more context for this server based app that follows REST.

Shell core forwards the request to the agenda core via named pipe if route is /agendas, (/chat to chat core etc.)

Agenda core serves two kinds of requests

1. General Agenda (all sessions belonging to this event)
2. Personalized Agenda (selected session list of this user identified via authToken)

Agenda core checks if authToken is present in http headers, "only" then it redirects to authentication core (sets the sender property) otherwise simply considers this as a general agenda request and let the request enter the core.

Agenda core followed by redirection is also listening to response from authentication core on STDOUT and compares the message with it's AgendaModule.NAME with sender property before serving personalized agenda.

Chat core on the other hand at STDOUT doesn't do anything since ChatModule.NAME didn't match the sender property.

The authentication core sent the output to STDOUT and not to the browser because sender property was present, meaning some core requested the authentication and wasn't a direct request.

Basically I think it's the reusability aspect of the cores (agenda/chat/authentication) and the 3rd party app is forcing to have some logic and guards at JunctionMediator unless there's a way out.

In this case considering at least two cores (agenda + auth OR chat + auth) were involved in any request, message type checking (every core has it's own Message class) and jump table reduced the complexity to some extent,

but what if this scales up, if a core puts more cores to work with several back and forth messages/communication, the handlePipeMessage is going to get busy.

I think that's where my other question comes in for having multiple input pipes if that's the solution, to manage "Inter-core" communication for several cores for a really large project.

22  Announcements and General Discussion / Architecture / Re: handlePipeMessage function on: November 13, 2014, 09:48:33
jump table/dictionary does simplifies things up, but there's still more to the equation.

What if this core needs to redirect the request first to the Authentication Core (designed to have it's own core because of the complexity involved). Now two pieces.

1. Check if the incoming request needed Authentication (it handles both kinds of requests, i.e. General/Personalized) and then redirect to Authentication core.
2. Authentication core would respond back with true/false and same handlePipeMessage would be called.

So I was forced to have a little bit logic there to check for redirection needs, and then again a little bit of logic to check if response from the authentication core was true or false, that made the handlePipeMessage busy and I feel no way out.

If I let Message that requires authentication get into a core and then have a command checked and send it back to JunctionMediator for redirection to AuthenticationModule, (seems like a loop to me) and instead just redirect from the handlePipeMessage seems intuitive, although it's going against the rule, that JunctionMediator's responsibility is just to translate messages into notifications.

For regular requests, yes jump table using message name diminishes the switch, if else needs but for the above scenario I'm not finding a way out.
23  Announcements and General Discussion / Architecture / Re: handlePipeMessage function on: November 13, 2014, 02:40:10
Some code example (Javascript/Nodejs) in context of the above reply, as you can see my JunctionMediator got busy, it got managed fine but won't be if there's a lot more than this, please advise.

:
handlePipeMessage: function(message) { //EntitlementModule implements a 3rd party authentication system defined in its own core, serves to other cores plus handles direct requests from other client app
    if(message instanceof common.ShellMessage) { //message from Shell
        if(message.body.request.query.authToken) { //if authToken was passed -> MyAgenda (personalized) else General Agenda             
            message.body.sender = modules.AgendaModule.NAME; //set sender as there are other modules listening on stdout of EntitlementModule for authentication response
            this.getJunction().sendMessage(modules.EntitlementModule.NAME, new common.EntitlementMessage({body:message.body})); //get authenticated, response handled below.
        } else { //general public agenda/sessions
            if(message.body.request.route.path == "/sessions/:id") {
                this.sendNotification(modules.agenda.ApplicationFacade.SESSION, message.body);
            } else {
                this.sendNotification(modules.agenda.ApplicationFacade.GENERAL_AGENDA, message.body);
            }
        }
    } else if(message instanceof common.EntitlementMessage && message.body.sender == modules.AgendaModule.NAME) { //reply from EntitlementModule in response to above auth request
        if(message.body.data) { //if authentication successful
            this.sendNotification(modules.agenda.ApplicationFacade.MY_AGENDA, message.body);
        } else { //if authentication failed
            message.body.info.statusCode = 401;
            message.body.info.message = "Unauthorized";
            this.sendNotification(modules.agenda.ApplicationFacade.AGENDA_FAIL, message.body);
        }
    }
},

Another excerpt for the handlePipeMessage

:
handlePipeMessage: function(message) {
    if(message instanceof common.ChatMessage) {
           
        message.getBody().request = {id:message.getBody().socket.id, query:{authToken:message.getBody().socket.handshake.query.authToken}}; //if authToken was passed
           
        switch(message.action) {
            case "connection": //get authenticated first
                message.body.sender = modules.ChatModule.NAME //specify sender as this module is listening to stdout
                this.getJunction().sendMessage(modules.EntitlementModule.NAME, new common.EntitlementMessage({body:message.getBody()}));
                break;
                   
            case "chat": //send a message to the other socket
                this.sendNotification(modules.chat.ApplicationFacade.CHAT, message.getBody());
                break;
                   
            case "disconnect":
                this.sendNotification(modules.chat.ApplicationFacade.DISCONNECT, message.getBody());
                break;
        }
           
    } else if(message instanceof common.EntitlementMessage && message.body.sender == modules.ChatModule.NAME) { //response as a result of above authToken
           
        if(message.body.data) { //user is valid, create a connection
            this.sendNotification(modules.chat.ApplicationFacade.CONNECTION, message.body);
        } else if(message.body.info) { //authentication failed
            this.sendNotification(modules.chat.ApplicationFacade.CHAT_FAIL, {info:{statusCode:401, message:{errorCode:message.body.info.errorCode}}, request:message.body.request, response:message.body.response});
        }
    }
}
24  Announcements and General Discussion / Architecture / Re: handlePipeMessage function on: November 12, 2014, 10:25:07
Hi Cliff,

Basically I had too much going on inside handlePipeMessage and wanted to get it under control, I looked at several example code especially sea of arrows and had following conclusion from there, basically this particular module was receiving several messages from different modules and for different execution paths (commands or sometimes delegating to other modules and expecting an answer back/Authentication) and I noticed the handlePipeMessage was checking for message types there, based on that I defined a Message type class for each module involved in the interaction, and then checked for it's type in handlePipeMessage to determine the execution path.

Also after branching message types if a message type can trigger more than one operation, declare a property action and and then use switch statement to trigger associated commands within handlePipeMessage, that managed things very well.

Since it was a server side code (Nodejs) and I had to keep track of who requested it, so I also passed the request and response objects with the notification/message and view tier would simply use the passed response object to output the data (like sender property)

another question, since we can define several named output pipes for a module and module would send message down to any of these pipes to the listeners on the other end, but for the input it's usually one (STDIN) with an associated handlePipeMessage as a listener, so I was thinking what kind of situation would that be if we have to define more than one input pipe with their own listener handlePipeMessage function for each.
25  Announcements and General Discussion / Architecture / handlePipeMessage function on: October 28, 2014, 03:06:32
In a case when any module is connected to several other modules, and there's communication back and forth.

module A will receive a message from Shell.

then module A will send a request to module B and will get it's response within same handlePipeMessage.

from there, module A will then send some request to module C, and will get it's response within the same handlePipeMessage.

module B is connected to several modules and outputting on it's STDOUT, and I'm filtering based on the requester (module) name.

so handlePipeMessage of moduleA is getting complex.

What's the best workflow would you suggest in the above scenario, have separate Message types or have information like sender/receiver inside the header etc.
26  Announcements and General Discussion / Architecture / Re: Multicore PureMVC with Routing on: October 06, 2014, 08:25:49
that's extraordinary  :)
27  Announcements and General Discussion / Architecture / Re: Multicore PureMVC with Routing on: October 02, 2014, 09:00:55
I've a different case too in context of PHP where things are different, since PHP is a stateless environment, Shell, Modules are loaded at runtime, request is handled and response is returned in a fraction of a second. my workflow would be as follows, please comment for any suggestions.

In a multicore application let's say with 8-10 Modules, Shell is instantiated for each request but then depending up the params, only the required modules (generally 2-3) are instantiated, plumbed and executed because of the efficiency reasons.

The application needs to determine route information the very first thing after the STARTUP before anything could happen, Plumb, configuration everything will follow.

A. In BrowserMediator, after determining route information, it will transition the StateMachine to PLUMBING state hence firing the PlumbCommand along with route information in the notification body, inside a switch statement, the PlumbCommand will instantiate only required modules (based on the first part of the route) and plumb them together.

B. PlumbCommand will transition the StateMachine to the NAVIGATING state passing the given route information in the notification body, NAVIGATE notification will be triggered, passed to ShellJunctionMediator that will STDOUT the route information to the modules so they can further branch execution based on the routing.

Please suggest for any enhancements.
28  Announcements and General Discussion / Architecture / Re: Multicore PureMVC with Routing on: October 02, 2014, 02:40:37
much better  :). Thanks Cliff.
29  PureMVC Manifold / Multicore Version / Re: Port to AsyncCommand - A PureMVC / JS Utility on: October 02, 2014, 08:37:02
I think now it's better to design those SubAsyncMacroCommands to perform their operations without a need for their individual onCompleteHandlers, and just handle onComplete within UberAsyncMacroCommand.

Following line works in this case. The book says to program to an interface not to an implementation and your code is checking the command instance against IAsyncCommand but since we don't have something built-in like Interface in JS, we are forced to program to an Implementation. There are JS patterns/utilities out there to emulate interface with type checking but clarity and checking against just two implementations outweighs bringing in extra set of functions.

var isAsync = commandInstance instanceof puremvc.asynccommand.AsyncCommand || commandInstance instanceof puremvc.asynccommand.AsyncMacroCommand;
30  PureMVC Manifold / Port to JavaScript / Re: State Machine Utility (using native prototype property) with LockableDoor Demo on: October 02, 2014, 08:12:19
Thanks Cliff for your comments.

In context of StateMachine, I've been thinking about an Asynchronous State Machine, on the client side if entering and exit guard notifications trigger asynchronous processes (calling remote services), let's say checking retries for a Simple Form Submission (from your State Machine Presentation), so State Machine has to wait for the response (CANCEL or OK) to determine transitions.

What's your idea on how could that work or what else should go in an Asynchronous State Machine?
Pages: 1 [2] 3 4 5