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

Pages: [1]
Print
Author Topic: prana framework  (Read 14723 times)
earmountaina
Jr. Member
**
Posts: 14


View Profile WWW Email
« on: May 29, 2008, 07:55:29 »

Just a little bit of meta info for the reader. The first 5 or 6 posts are about MVC and Data Broker and then a really good post follows about the Prana Framework and PureMVC. -- Mike.

Hi All,
A friend suggested that I look at the Prana Framework (pranaframework.org) and I have, but before I put more time into this, I was just curious to know if anyone can recommend prana?
Thanks for any insights.
-- Mike
BTW, on the home page, there is a prominent declaration that the framework is PureMVC compatible and when I look at the code, I see a corresponding set of code.
« Last Edit: June 17, 2008, 03:02:07 by earmountaina » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: May 30, 2008, 06:22:15 »

They have folded in the PureMVC codebase and made numerous changes/ommissions to meet their ends.

They are of course, free to do so under the creative commons license. I cannot speak to the extent to which PureMVC is used or to its role within Prana. So while I can't 'endorse it' per se, I certainly can't say anything bad about it. I understand the focus is to bring about a configuration-driven 'IOC' framework.

I would be interested to hear the results of any thoughts you may have if you do work with it.

-=Cliff>   
Logged
earmountaina
Jr. Member
**
Posts: 14


View Profile WWW Email
« Reply #2 on: June 01, 2008, 01:08:38 »

Cliff,

Thanks for you reply. I'm probably going to take a hard look at Prana in about two months. I'm interested in using dynamic namespace declarations for increasing semantic richness and discrimination. Right now I'm moving ahead with just a pure pureMVC. BTW, I'm really enjoying this framework. I used to work for Digitalk (Smalltalk).

In your Best Practices writeup (nice work) I'd like a gut-level example of the difference between Business Logic and Domain Logic. If you do a search on the difference the first paragraph of the top listing seems to go against your usage of these terms:
http://martinfowler.com/articles/dblogic.html
I think of domain as part of the problem domain. I'm wondering if domain is about marshalling data into well formed business objects, but then why not allow these objects to embody their own behavior. It seems to me that a complex application would end up with a lot of decapsulated behavior as command objects. Isn't this getting onto a slippery slope of dumb data objects and procedural code snippets. Obviously you would do your best to name these command objects in such a way as to aggregate them, but this is a weak convention compared to keeping them with their business objects. I'm sure I'm missing your point. I hope you'll enlighten me. BTW, if you have already answered this, and I bet you have, please just give me a link to it and save your valuable time.

-- Mike
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: June 01, 2008, 07:22:43 »

Hi Mike,

I have actually addressed this partially (http://forums.puremvc.org/index.php?topic=455.msg1920#msg1920) but perhaps it really deserves a longer exposition in a prominent place like the soon to be started FAQ.

My take is that what business logic and domain logic in an n-Tier system depends entirely on whether you're writing client-side code or server-side code. I consdider the the domain model to be the data objects (usually persistent) that are used by the application to talk itself about (and have conversations with the user in) 'the problem domain'.

First before we consider a separate logic tier on either side (and what might belong there), lets consider a minimally tiered server and client.

In the server, you have a minimum of two tiers, one dedicated to network I/O and one to persistence. Therefore, the logic for accessing database (the subject of Fowler's post) belongs clearly in the latter tier. The logic for locating and interacting with services falls into the former.

In the client you have a minimum of two tiers, one dedicated to presentation and user input, the other to communicating with services and maintaining the client's internal representation of the domain model (which may contain client-only data held in addition to persistent data obtained from services).

Thus:

In all cases the domain model is the persistent and transient data manipulated by the application on either side.

In the 2-tiered server: persistence and data= domain logic / services and protocol = business logic.

In the 2-tiered client: services and data=domain logic / presentation and user input=business logic.


But MVC, you say, is a 3-tiered system. So why not dump all the logic into the middle tier?

In a stateful client, there are pressures that make it more reasonable to move service interaction into the Model region. Here are a few:

1. The Model related classes are often something we want to reuse across clients. Being able to package the model classes separately and placing the logic for accessing the domain services makes sense. To the rest of the client, where the data comes from is completely hidden behind the Model Tier which becomes transportable.

2. Explosion of classes. Systems that use Commands for service interaction tend to have large numbers of them, each of which do little more than take a result, hang it on the Model and perhaps alert the View that it happened. These Commands have to be registered, so for the client to maintain Model integrity requires Model code, Command code and Controller initialization code. Not easy to pick up and drop into a new client app. Too many straps, plugs and dangley bits to hook it in.

3. The client is typically stateful, whereas the server isn't. This makes the logic more tricky and thick in a typical client as opposed to the typical server. Managing the representation of the model is one big part, the other is coordinating complex activities such as preparation of the Model and View at startup.

In PureMVC, the Controller Tier becomes a thin layer that can be used to centralize View to Model interaction triggered from multiple View locations and to orchestrate high-level application state changes.

The Model tier becomes a transportable set of classes that facilitate access to the domain model, including the interacting with services when necessary. This reduces the number of classes dramatically (over a system with services in the Controller tier) because the number of things you might want to ask a service (the Commands) is usually less than the number of services you actually have (Proxies).

A Proxy will have methods that expose the data synchronously or async. The Mediators of the View Tier have a relatively close collaboration with the view component, and a loosely-coupled access to the Proxy via the Facade.

Mediating between the view component and a Proxy is usually a simple set/get on a Proxy followed by a possible async Notification carrying data to set on the view component. There is rarely a need to insert a Controller region class in this simple collaboration pattern.

These thoughts ought to boil down to a FAQ soon.

Cheers,
-=Cliff>
Logged
earmountaina
Jr. Member
**
Posts: 14


View Profile WWW Email
« Reply #4 on: June 01, 2008, 09:07:17 »

Cliff,

Thanks for your reply and the link to the other post. Both were very useful.

Bear with me as I put my thoughts and confusion in terms for which I'm more familiar. I am up against my own biases from having built many fat clients in Smalltalk. I'm trying to move this knowledge into a Flex/AS3 pureMVC application that will have many view components and many data sources (some under our control and some under our customer's control). As I read your post I can't help feeling data-driven. I've always liked Wirfs-Brock's responsibility-driven OO design because it focuses behavior and let's data follow.

In pureMVC I see two main frameworks:
- MVC
- Data Broker
Where MVC keeps the business logic out of the view and the data broker keeps the primary keys and other data artifacts out of the Model or Business Objects (BOs). The BOs are the primary focus of business logic encapsulation, polymorphism, inheritance and delegation.

Data Broker - This framework has two parts. The brokers and the well formed business objects. The data for the business objects could come from a variety of sources, mulitple relational tables, XML heirarchies, etc. and the broker hides this sausage factory of turning that data into a well formed business object. For example, when it is time to persist the BO, it turns to the broker to put all that state to rest in relational table, XML files, etc. The primary keys of the relational world never make it across into the BO. So I'd like to put the data broker behavior/responsibilities into the DOs and the BOs into the Proxies.  This must bear in mind that as your Best Practices points out that Proxies can be of various kinds. This kind being for the encapsulation of business logic (business behavior/responsibilities).

MVC - The Controller is the place where view related state and logic live that do not belong in either the View or the Model (BOs). For example, Bank Account (a BO) has a balance. When the balance goes negative we want the value in the View to change from black to red. The BO should not know red from black because that's view related. Nor should the view be wired with the logic that would change the color based on the Account's balance. Therefore the Controller has the responsibility for knowing about color changes with repect to the Accounts's balance. We get the reuse of this logic across multiple views because the Controller is the one place that can see both the View and the Model. In pureMVC, I'm left with putting this behavior in a command or a mediator and am not sure where.

Finally I'm still not convinced that the Command is "the home of your application's business logic" as stated on page 5 of the Best Practices doc. I'd put that logic, whenever possible, in the Proxy as a way of building a well-formed BO.

Please don't think that I'm being argumentative or esoteric. I'm simply trying to get my understanding in-line with your framework before I and others in our company do more coding in the PureMVC. Thanks.

-- Mike
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #5 on: June 02, 2008, 01:19:11 »

Mike,

I never have a problem with discussion that may yield clarity where it's lacking.

Incidentally, Wirfs-Brock's RDD methodology, particularly the use of CRC cards, was instrumental in arriving at the current distribution of responsibility in the framework.**

Data Broker - This framework has two parts. The brokers and the well formed business objects. The data for the business objects could come from a variety of sources, mulitple relational tables, XML heirarchies, etc. and the broker hides this sausage factory of turning that data into a well formed business object. For example, when it is time to persist the BO, it turns to the broker to put all that state to rest in relational table, XML files, etc. The primary keys of the relational world never make it across into the BO. So I'd like to put the data broker behavior/responsibilities into the DOs and the BOs into the Proxies.  This must bear in mind that as your Best Practices points out that Proxies can be of various kinds. This kind being for the encapsulation of business logic (business behavior/responsibilities).

What you're talking about sounds similar to the collaboration pair Assembler/DAO on the server side. Often that is simply handled by a hierarchy of Proxies in PureMVC. For instance if you have a look at the CodePeek application and its use of the XMLDatabase utility, you see an abstract proxy that knows about how to handle file I/O to persist and parse arbitrary XML structures. Then you'll see that in the demo we subclass that and persist an XML 'database' of your queries by language. Also it makes use of the DesktopCitizen utility to remember its desktop placement and size, which in turn uses the XMLDatabase utility to persist window metrics.

In the CodePeek demo, note how the three proxies split up the responsibilities of managing the database (CodePeekDataProxy and its superclass XMLDatabaseProxy), managing the remote service and teasing the data we want out of it (CodeSearchProxy), and finally persisting and acting on that data (SearchesProxy).

In the DesktopCitizen utility, note how two Proxies split up the responsibilities of managing the WindowMetrics persistence (DesktopCitizenDBProxy) and of representing it (WindowMetricsProxy).

MVC - The Controller is the place where view related state and logic live that do not belong in either the View or the Model (BOs). For example, Bank Account (a BO) has a balance. When the balance goes negative we want the value in the View to change from black to red. The BO should not know red from black because that's view related. Nor should the view be wired with the logic that would change the color based on the Account's balance. Therefore the Controller has the responsibility for knowing about color changes with repect to the Accounts's balance. We get the reuse of this logic across multiple views because the Controller is the one place that can see both the View and the Model. In pureMVC, I'm left with putting this behavior in a command or a mediator and am not sure where.

This is an accurate assessment. The answer to your question about placement in Command or Mediator is that it can go in either place. If you need reuse in other views right now then put it in a Command. If you think you might, then put it in the Mediator for the one component that needs this behavior and put in a comment (in the code and the checkin) that it should be refactored to a Command when the need for reuse arises.

Proceeding in this way gives you the shortest path and simplest implementation now without sacrificing the ability to refactor to a Command (and thus increase complexity and cpu cycles needed to execute), only when you need to.

Or if you could care less about complexity and performance, and would sleep better at night knowing that your tiers are more cleanly separated than if you'd done it otherwise, then simply do all that sort of thing in Commands and rest easy. Sometimes the maintainability, performance, complexity and due date formula yields one answer, sometimes another.

So coming around to the point, about Responsibility Driven Design, I believe there's no barrier to that here. It is a matter of understanding the responsibilities of the actors in this particular implementation of several abstract concepts, and that it isn't so rigid as to require a specific way of doing everything.

I don't precisely follow how your reflections add up to a 'data-driven' paradigm. It's just that we're allowing the logic that manages the data to be encapsulated so the model simply behaves synchronously or asynchronously for a given part of the domain model. The View and Controller are merely about keeping the application state sorted, and consulting the model where needed.

-=Cliff>

**A side note for the benefit of others picking up object-oriented development concepts, I can't think of a wiser way to spend your money than to pick up a copy of: Object Design: Roles, Responsibilities, and Collaborations by Rebecca Wirfs-Brock. http://www.amazon.com/Object-Design-Responsibilities-Collaborations-Addison-Wesley/dp/0201379430/
Logged
earmountaina
Jr. Member
**
Posts: 14


View Profile WWW Email
« Reply #6 on: June 03, 2008, 01:30:20 »

Cliff,

That finally got it through to me. Thanks so much for your gracious persistence.

I missed the CodePeek demo. I'll go find it and look at the XML Database utility.

About my data-driven comment; I was seeing a lot of hollowed out Proxy/BOs and a cloud of behavior commands that make them responsible to the business. I see it differently now.

-- Mike
Logged
ryebrye
Newbie
*
Posts: 7


View Profile Email
« Reply #7 on: June 08, 2008, 03:03:38 »

Going back to the original topic of this thread...

They have folded in the PureMVC codebase and made numerous changes/ommissions to meet their ends.

They are of course, free to do so under the creative commons license. I cannot speak to the extent to which PureMVC is used or to its role within Prana. So while I can't 'endorse it' per se, I certainly can't say anything bad about it. I understand the focus is to bring about a configuration-driven 'IOC' framework.

I would be interested to hear the results of any thoughts you may have if you do work with it.

-=Cliff>   

I'm pretty active with the Prana community, and although I wasn't the developer who did the bulk of the PureMVC integration to it, I have done my part to help improve it to make it easier to use and more inline with the PureMVC way of doing things.

Prana's aim is to be a top-notch IoC container for Actionscript (the primary focus originally was flex, but with recent code changes it has no flex dependencies). Most of its architecture cues come from the Spring framework - in particular the xml driven configuration file has almost identical syntax to the Spring xml files, so developers familiar with Spring will be able to easily pick up Prana.

I wont try to sell anyone on IoC - like any pattern it has benefits and drawbacks and it is not the right solution for every case.

The pieces of Prana that are probably of most interest to the PureMVC community is the initial groundwork that has been put in place to attempt to make it easy use IoC and PureMVC together.

To clarify some of what Cliff said - there are pieces of code in the Prana that are folded-in from PureMVC, but most pieces modify by extension rather than at the source level. To make it clear when you are using classes and interfaces of the Prana versions of the PureMVC classes and interfaces, they are prefixed with IoC in the case of a class, or IIoC in the case of an interface. (I.e. IFacade is IIocFacade, Facade is IoCFacade).

The biggest development difference between coding to an IoC container and coding in PureMVC by itself is that dependencies are injected by the container, rather than retrieved from the facade. For instance, in an application I am developing now I have a mediator that collaborates with a certain Proxy. Rather than retrieve the proxy from the Facade - which I still COULD do if I wanted to - I am simply injecting the proxy into the mediator at creation time.

Here is a simple example of configuring a mediator in Prana.

:
   <object id="specialistSelectionScreenMediatorInstance" class="com.xyz.view.mediator.SpecialistSelectionScreenMediator" lazy-init="true">
    <property name="specialistCategoryProxy" ref="specialistCategoryProxyInstance" />
   </object>
   

(One notable dependency - the actual UI component - isn't being injected here. I have a viewPrep command that I run at startup that does that work for me. View component injection is kind of a pain since you have to do a lot more legwork to handle the creation lifecycle... It's possible, if you need to do it, but for now I just did it this way.)

Earlier in the same file, the specialistCategoryProxyInstance is created and configured to have a concrete delegate class injected into it:

:
   <object id="specialistCategoryProxyInstance" class="com.xyz.model.proxy.SpecialistCategoryProxy" >
<property name="categoryLoadingDelegate" ref="specialistCategoryDelegateInstance"/>
   </object>

The delegate instance that is injected into it for now is one that I have merely generating and returning test data:

:
  <object id="loginDelegateInstance" class="com.xyz.model.business.impl.TestDataProvidingLoginCredentialsDelegate" />

(edit: adding in this last sample piece of code)
As I mentioned above, the mediator example isn't complete until it is registered. I have my viewPrep command do this at startup. It looks like this in the context file:

:
<object id="MainViewPrepCommand" class="com.xyz.controller.MainViewPrepCommand" >
  ...
  <property name="specialistSelectionScreenMediator" ref="specialistSelectionScreenMediatorInstance" />
   ...
</object?

And the relevant pieces of the MainViewPrepCommand look like this in the code:
:
public class MainViewPrepCommand extends IocSimpleCommand
{
    ...
    // the mediator gets injected and stored here. This can be an interface or a concrete class. If Flex Builder had a decent "extract interface"
    // refactoring tool, I'd definitely say "always code to an interface instead of the concrete class..." but what you do in private is your business :)
    private var _specialistSelectionScreenMediator:ISpecialistSelectionScreenMediator;
    ...

   // This is the method that the Prana container calls when it sets this property when creating the mediator
   public function set specialistSelectionScreenMediator(v:SpecialistSelectionScreenMediator):void {
      this._specialistSelectionScreenMediator = v;
   }
   ...

   override public function execute( note:INotification ) :void   
   {
       var app:MyApp = note.getBody() as MyApp;
       ...
        _specialistSelectionScreenMediator.setViewComponent(app.mainView.specialistSelector);           
        iocFacade.registerMediatorByConfigName(_specialistSelectionScreenMediator.getConfigName(), _specialistSelectionScreenMediator);
       ...
    }

As you can see above - it's a fairly straightforward command. Perhaps in the future one of us will create a utility object that will be easily configurable in the context file so you can simply leverage that to help do this all by simply writing a few lines in the configuration file. Even this isn't very painful, however.

The benefits of using an IoC container in this case listed above involve the ease of swapping out delagates. When I am ready to change my implementation to go "live" with a real delegate that will actually communicate with the server, I don't have to touch any of the code - I merely have to change the loginDelegateInstance to be of a different class - and inject any configuration details into that class that may be necessary (such as remote service information). I can even have several delegates in my code that are all compiled and available - so I can perform some kind of performance testing against different remote access methods (i.e. have one delegate hitting a web service and marshalling the objects into strongly-typed return objects, while another delegate would use object remoting and pass off the strongly-typed objects that are returned from that process without doing much additional work) - and in that case, it would be literally simply swapping one line of configuration between executions of the file and the entire behavior of that piece would be changed.

In that vein - one of my favorite things about Prana is the ease in which I can handle remote objects and their configurations. Flex by default practically forces you hardwire the remoting configuration at compile-time, which has always rubbed me the wrong way. With Prana, configuring my remote destinations at runtime is extremely easy. It looks like this:

:
    <property file="remotingprops.xml" />

    <object id="remotingChannel" class="String">
        <constructor-arg value="${remoting.channel}" />
    </object>
   
    <!-- ==================================================  -->
    <!-- Template: Remote Object      -->
    <!-- Usage:    This template is used to make it easy     -->
    <!--           to configure our remote objects.          -->
    <!-- Parameters:  -->
    <!--   destination - The RemoteDestination on the server -->
    <!--   source      - A name to describe the source       -->
    <!-- ==================================================  -->
    <template id="remoteObject">
        <object class="mx.rpc.remoting.mxml.RemoteObject">
            <property name="destination" value="${destination}"/>
            <property name="endpoint" ref="remotingChannel" />
            <property name="showBusyCursor" value="true"/>
            <property name="source" value="${serviceClass}"/>
        </object>
    </template>   

In my remotingprops.xml file I have a simple properties file that I specify the hostname and the context root of my server. You will notice that even the remote service itself is abstracted out... so I can change between different endpoints on the server without having to touch my flex code or recompile it to match a new configuration.

The main difference between Prana's PureMVC classes the pure PureMVC classes is that Prana classes all use the configName rather than the name defined by the concrete instance. This is to provide functionality for the name-based retrieval, but to allow the names to be set in the context and not in the classes (the id attribute of the object is the "configName"). This is the primary change that has been made to the PureMVC classes.

The only other change that I am aware of is that a new IoCManagedMacro command was created because the existing MacroCommand has a final method that dictates that it create an instance of the command itself - and the Prana one relies upon concrete commands being passed into it. (The reason for this is that the commands - although stateless - can still have dependencies upon other collaborators such as proxies... etc. that are set in the context file.) For a similar reason, the IoCMediator provides default null values for both the name and the viewComponent of the constructor to allow for it to be created at run-time.

Aside from those few changes, I don't believe that much else has been changed. The ConfigName mappings are still passed to the standard Facade - and you could create a PureMVC application that used Prana to only manage the dependencies of a small portion of it - the IoC classes and the normal PureMVC classes can coexist in the same application. A command could use the Facade to retrieve an instance of a Proxy that was set up by the IoC Container - for instance - and it would be unaware of Prana entirely.

I think that the number of changes is minimal, and no omissions come to mind. The current SVN trunk of Prana (0.6) has some changes in it to try to bring it even closer to a normal PureMVC way of doing things.

Since PureMVC is architected very well with loose coupling in mind, it is not hard to make it play well with an IoC container. If anyone is interested in helping, check out the code and play around with it a bit.
 

« Last Edit: June 08, 2008, 09:38:27 by ryebrye » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #8 on: June 08, 2008, 06:41:51 »

Thanks for this very useful summary of the role of PureMVC in the Prana Framework. It certainly sounds intriguing, and I'm sure others reading this thread will want to give Prana a look if you're looking for an IoC solution that leverages the PureMVC Framework.

-=Cliff>
Logged
ryebrye
Newbie
*
Posts: 7


View Profile Email
« Reply #9 on: June 08, 2008, 09:23:27 »

Thanks for this very useful summary of the role of PureMVC in the Prana Framework. It certainly sounds intriguing, and I'm sure others reading this thread will want to give Prana a look if you're looking for an IoC solution that leverages the PureMVC Framework.

-=Cliff>

No problem at all. Thank you for providing such a pragmatic and fundamentally-sound MVC framework.

To any PureMVC users who find this post and are interested in playing around with it some more - suggestions and questions are always welcome. :)
« Last Edit: June 08, 2008, 09:44:28 by ryebrye » Logged
earmountaina
Jr. Member
**
Posts: 14


View Profile WWW Email
« Reply #10 on: June 10, 2008, 08:18:32 »

Hi Ryebrye,
Is there any way you could take the CafeTownsend example and retrofit it with a Prana implementation?
-- Mike
Logged
earmountaina
Jr. Member
**
Posts: 14


View Profile WWW Email
« Reply #11 on: June 14, 2008, 09:54:51 »

This repo has a PureMVC sample app:
https://prana.svn.sourceforge.net/svnroot/prana prana
Look in the prana-projects-0.5.zip.
-- Mike
Logged
Pages: [1]
Print