Best Practice - Value Lists

Jon's Avatar

Jon

23 Aug, 2010 11:40 AM

We just started our first project with RL (it is the first Flex Framework we've ever used). So far we were able to resolve our doubts using the online knowledge base but we cannot figure out what's the best way of doing the following. We believe it is a pretty common scenario so it has probably been discussed in another thread. Unfortunately we couldn't find it.

We have a Projects module with two views: a List View and a Detail/Edit View. Each project has an Offices dropdown and a Leader dropdown. Each Leader is assigned to an Office so when the user selects an Office, Flex requests a list of Leaders from the server to populate the Leader dropdown. Those are the different options we came up with:

The mediator listen for changes in the Offices dropdown AND

1) Dispatches event with payload, command calls service, service updates model, model dispatches event, mediator listens for event and updates the Leader dropdown.

OR

2) Dispatches event with payload, async command calls service and listens for result, dispatches event, mediator listens for event and updates the Leader dropdown.

OR

3) Mediator calls service asynchronously, listen for result and updates the Leader dropdown.

In case we have to update the model, should we update the Projects model or should we create a separate model for the edit view? Is there any example available with dynamic value lists?

Also, the following is not probably a RL question but in the list view we want to show the Office and Leaders fields for each project. We could either
- Make the Office and Leader names properties of the Project value object which are passed from the server, or - Store a list of id/name pairs for the Offices and Leaders in a separate Model within Flex and only store the Office and Leader ids in the Project value object. We could then use a labelFunction that "calculates" the label.

What would be best practice?

Thanks in advance.

  1. 1 Posted by Nikos on 23 Aug, 2010 01:59 PM

    Nikos 's Avatar

    I think the 1st option sounds best

  2. Support Staff 2 Posted by Shaun Smith on 23 Aug, 2010 05:03 PM

    Shaun Smith's Avatar

    If the service is well designed, I'd go for option 3 - fewer moving parts, less to refactor when things need to change, and, possibly, easier to look at and reason about. Don't forget that mediators already provide a level of de-coupling, you don't always need to go as far as:

    view -> event -> mediator -> event -> command -> service -> event -> command -> model -> event -> mediator -> view

    There are A LOT of moving parts there. Sometimes it's OK to go:

    view -> event -> mediator -> service -> mediator -> view

    What you don't want is for the system's operation to become dependent of the operation of the mediator - ie, if you yank out the mediator everything breaks.

    Of the two flows I illustrated above, I use the first when the data in question is applicable to the system as a whole - where many parts of the system may be interested in the process. I use the second when the only thing that cares about the data is the view node that is going to represent that data. Hope that makes sense!?

  3. 3 Posted by Nikos on 23 Aug, 2010 05:13 PM

    Nikos 's Avatar

    i agree, would you pass a callback from the mediator to the service?

  4. Support Staff 4 Posted by Shaun Smith on 23 Aug, 2010 05:23 PM

    Shaun Smith's Avatar

    I probably would! But only if the service is well designed - has a configurable parser, is decoupled from the transport protocol, and deals in Async Tokens or Promises. What I wouldn't do is pass a callback and then manually parse server results in the mediator. That would be bad.

  5. 5 Posted by Nikos on 23 Aug, 2010 06:05 PM

    Nikos 's Avatar

    would you inject the model in both the service and the view then but update
    the model in the service only?

  6. 6 Posted by Jon Otaegi on 24 Aug, 2010 12:57 AM

    Jon Otaegi's Avatar

    Thanks guys! It was really helpful!

    Once explained it makes a lot of sense :)

    Re the second question, between the client and the server in a MVCS implementation, is it better practice to pass simple individual objects linked by ids, such as:

    Project {
      id:int = 1
      name:String = "First Project"
      office_id:int = 1
      leader_id:int = 1
    }

    Office {
      id:int = 1
      name:String = "Corporate"
    }

    Leader {
      id:int = 1
      name:String = "John Smith"
      office_id:int = 1
    }

    Or should we pass a single complex object such as:

    Project {
      id:int = 1
      name:String = "First Project"
      office:Office = officeInstance
      leader:Leader = leaderInstance
    }

    Thanks in advance.

  7. Support Staff 7 Posted by Shaun Smith on 24 Aug, 2010 12:52 PM

    Shaun Smith's Avatar

    I tend to prefer going the ID route - I find it simpler to manage.

  8. 8 Posted by Jon Otaegi on 25 Aug, 2010 02:49 AM

    Jon Otaegi's Avatar

    Thanks Shaun.

    What strategy would you follow to display the labels of the children objects in a List or DataGrid?

    Would you pass the labels of the children within the parent object:

    Project {
      id:int = 1
      name:String = "First Project"
      office_id:int = 1
      office_name: String = "Corporate"
      leader_id:int = 1
      leader_name: String = John Smith"
    }

    Or would you have a separate piece of logic to get the labels?

    Thanks.

  9. Support Staff 9 Posted by Shaun Smith on 26 Aug, 2010 06:11 PM

    Shaun Smith's Avatar

    @nikos "would you inject the model in both the service and the view then but update the model in the service only?"

    You could do that, sure. You could even enforce it: just map something to two interfaces (read-write, and read-only).

    // For RL 1.x
    
    // If the thing already exists, use it
    injector.mapValue(IWritableThing, thing);
    injector.mapValue(IReadableThing, thing);
    
    // If not, map as Singleton and reuse the rule
    var rule:* = injector.mapSingletonOf(IWritableThing, ConcreteThing);
    injector.mapRule(IReadableThing, rule);
    
  10. 10 Posted by Stray on 26 Aug, 2010 06:50 PM

    Stray's Avatar

    That's a REALLY neat implementation of mapRule. Very cool.

  11. Support Staff 11 Posted by Shaun Smith on 26 Aug, 2010 09:16 PM

    Shaun Smith's Avatar

    mapRule is kinda icky to be honest - I think something like mapFactory (see: http://github.com/tschneidereit/SwiftSuspenders/issues#issue/21 ) could be much nicer:

    // You can't do this yet, but maybe soon
    injector.mapFactoryClass(IWritableThing, ThingFactory);
    injector.mapFactoryClass(IReadableThing, ThingFactory);
    
  12. 12 Posted by Stray on 27 Aug, 2010 08:37 AM

    Stray's Avatar

    Interesting.

    I've never used mapRule, but the example you gave was a nice clear corner case for its use.

    mapFactoryClass looks super useful, presumably the factory would return 'as' the required interface?

  13. Support Staff 13 Posted by Shaun Smith on 27 Aug, 2010 12:37 PM

    Shaun Smith's Avatar

    How it would actually work is still unclear. One way is to have an annotation, something like [Provider], that marks a method that can be called to produce the instance. This is how it's done in Dawn: http://wiki.github.com/sammyt/dawn/dawninjections (under Factory Driven Injections).

  14. Stray closed this discussion on 16 Feb, 2011 09:06 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac