No subject

E.'s Avatar

E.

07 Dec, 2011 10:32 PM

My custom flex ui components often span several parent/child levels:

E.G.

[MainComponentClass]
- [MainComponentClassSkin]
- - [Component01]
- - - [Component01Skin]
- - - - [Component02]
- - - - - [Component02Delegate01]
- - - - - [Component02Delegate02]
- - - - - - [Component02Skin]
...

To make things easy for the developer (me) using my components I want all of the components subclasses to be encapsulated by the [MainComponentClass].

THE PROBLEM:
If "data01" is set on the [MainComponentClass] and "data01" is needed by a class deeper in the component tree, how does one propagate "data01" to that component?

THE QUESTION:
What would be your objections/hurrahs, if one said they were to use an application framework, like RobotLegs, to push data on the component level, rather than on the layer-level of the application.

If in-component-use of RobotLegs is discouraged: How do you solve the problem outlined above by hand? The best "non-framework-solution" I've been able to come up with is: Listen for propagating lifecycle events in the [mainComponentClass] and if you find a component that needs data set up a binding.

  1. 1 Posted by E. on 07 Dec, 2011 10:36 PM

    E.'s Avatar

    Move to the "Questions" discussion board?

  2. Support Staff 2 Posted by Ondina D.F. on 08 Dec, 2011 12:03 PM

    Ondina D.F.'s Avatar

    Hi E.

    You are right, in-component-use of RobotLegs is discouraged.

    “If "data01" is set on the [MainComponentClass] and "data01" is needed by a class deeper in the component tree, how does one propagate "data01" to that component?”

    There are many ways to do this depending on what you want to achieve.

    The question is: does the MainComponent have a Mediator? Do these subcomponents have a Mediator?

    • If the answer is yes, then there is an easy way to populate all components with the same data. One possibility:

    Use a VO, let’s call it SomeVO, that has a property public var someData:String.
    Map it as a singleton injector.mapSingleton(SomeVO);
    Then use the Mediators to pass the VO to their views.
    In a mediator you do:
    [Inject] public var someVO:SomeVO;
    in onRegister you can then do:
    view.someVO=someVO;
    In the View
    public var someVO:SomeVO;
    And then you can set the component’s data to someVO.someData using getters and setters, for example.

    • If the answer is no, the components aren’t mediated, you’ll have to use one of the many ways to pass data from a parent component to its children.

    I would prefer to use getters and setters:
    SomeChildView.mxml
    private var _labelData:String;

    [Bindable]

    public function get labelData():String
    {

    return _labelData;

    }

    public function set labelData(value:String):void
    {

    _labelData = value;

    }

    <s:Label id="someLabelNeedsData" text="{labelData}" />
    SomeParentView.mxml
    someView.labelData=someData;

    I hope this helps, but if it doesn’t answer your questions, please provide more details:)

    Ondina

  3. 3 Posted by E. on 08 Dec, 2011 01:28 PM

    E.'s Avatar

    Hi Ondina!

    Thanks for your reply. When you are working as a solo developer as I am it's nice to be able to get some feedback through a forum like this.

    If this post gets lengthy – the ramblings are aimed at myself: It's helpful to think out loud in the presence of another developer. And sorry for my English. Swedes are not as skilled in the language as we think. ;)

    First. I've heard many developers distinguish between VIEWS and COMPONENTS. I find it a fruitful distinction.

    In short. "Views" are non reusable, application specific, domain aware, ui parts.
    In short. "Components" are reusable, application agnostic, domain unaware, ui parts.

    Views aggregate components and other views. A LogInPanel is a view. A LogInButton is a component.

    Views take precedence over components. The view paints (skins/styles) its components, positions them, handles their events, passes them data ...

    When using RobotLegs: A view is often handled by a domain bound mediator. A component is often handled by a domain bound view.

    It makes sense that we should not use RobotLegs below the view level of the application. But the question remains: If we develop "deep" ui components, how to propagate data set on the component in the "view"?

    A concrete example: I'm developing a time-line-based component. A zoom value set on the main component is needed in a layoutClass several levels down in the component.

    As you say there are many options for propagating the data:

    ALTERNATIVE ONE:
    We could make the component less encapsulated. Let the developer assemble the component in the view and let the developer set the data, not on the main component, but where it is needed.

    Upsides: Flexibility. It's easy to vary the component from view to view. No data propagation mechanism is needed.

    Downsides: The developer must know what parts are needed to assemble the component (when writing MXML components we can't ask for parts in a constructor). Instantiating the component can get lengthy and errorprone.

    ALTERNATIVE TWO:
    Pass data from parent to child, as you suggests.

    Upsides: It's obvious how the data is propagated.

    Downsides: Adds a lot of overhead to the codebase. Component middle layers must handle data it might not need, just for the sake of its children.

    The process can be automated by setting up bindings from parent to child in a commonly shared super-class, but this option is not always available if the different component parts needs to inherit from different super classes.

    ALTERNATIVE THREE:
    Make the MainComponentClass a dependency delegator. The MainComponentClass listens for children added deeper in the tree and injects dependencies in subParts as needed, depending on their type. If subParts implements interfaces the MainComponent class is decoupled from the actual subPart implementation.

    Upsides:
    Keeps component encapsulation. Data is set directly from source to target. Through interfaces component parts are decoupled from each other.

    Downsides:
    Not clear how data propagates through the component. Only viable on the displayList.

    Are there upsides, downsides I haven't noticed? Are there other better options for propagating data inside a "component". Comments welcome.

  4. 4 Posted by E. on 08 Dec, 2011 01:31 PM

    E.'s Avatar

    Hi Ondina!

    Thanks for your reply. When you are working as a solo developer as I am it's nice to be able to get some feedback through a forum like this.

    If this post gets lengthy – the ramblings are aimed at myself: It's helpful to think out loud in the presence of another developer. And sorry for my English. Swedes are not as skilled in the language as we think. ;)

    First. I've heard many developers distinguish between VIEWS and COMPONENTS. I find it a fruitful distinction.

    In short. "Views" are non reusable, application specific, domain aware, ui parts.
    In short. "Components" are reusable, application agnostic, domain unaware, ui parts.

    Views aggregate components and other views. A LogInPanel is a view. A LogInButton is a component.

    Views take precedence over components. The view paints (skins/styles) its components, positions them, handles their events, passes them data ...

    When using RobotLegs: A view is often handled by a domain bound mediator. A component is often handled by a domain bound view.

    It makes sense that we should not use RobotLegs below the view level of the application. But the question remains: If we develop "deep" ui components, how to propagate data set on the component in the "view"?

    A concrete example: I'm developing a time-line-based component. A zoom value set on the main component is needed in a layoutClass several levels down in the component.

    As you say there are many options for propagating the data:

    ALTERNATIVE ONE:
    We could make the component less encapsulated. Let the developer assemble the component in the view and let the developer set the data, not on the main component, but where it is needed.

    Upsides: Flexibility. It's easy to vary the component from view to view. No data propagation mechanism is needed.

    Downsides: The developer must know what parts are needed to assemble the component (when writing MXML components we can't ask for parts in a constructor). Instantiating the component can get lengthy and errorprone.

    ALTERNATIVE TWO:
    Pass data from parent to child, as you suggests.

    Upsides: It's obvious how the data is propagated.

    Downsides: Adds a lot of overhead to the codebase. Component middle layers must handle data it might not need, just for the sake of its children.

    The process can be automated by setting up bindings from parent to child in a commonly shared super-class, but this option is not always available if the different component parts needs to inherit from different super classes.

    ALTERNATIVE THREE:
    Make the MainComponentClass a dependency delegator. The MainComponentClass listens for children added deeper in the tree and injects dependencies in subParts as needed, depending on their type. If subParts implements interfaces the MainComponent class is decoupled from the actual subPart implementation.

    Upsides: Keeps component encapsulation. Data is set directly from source to target. Through interfaces component parts are decoupled from each other.

    Downsides: Not clear how data propagates through the component. Only viable on the displayList.

    Are there upsides, downsides I haven't noticed? Are there other better options for propagating data inside a "component". Comments welcome.

  5. Support Staff 5 Posted by Ondina D.F. on 08 Dec, 2011 04:56 PM

    Ondina D.F.'s Avatar

    Interesting questions!

    "If this post gets lengthy – the ramblings are aimed at myself: It's helpful to think out loud in the presence of another developer. And sorry for my English. Swedes are not as skilled in the language as we think. ;)"

    I’ll answer just a few questions today, and more tomorrow. Hopefully others will participate in the discussion as well.

    Oh, if you’re sorry for your English, then I’ll have to apologize for my English too;)

    “First. I've heard many developers distinguish between VIEWS and COMPONENTS. I find it a fruitful distinction.”

    In my understanding the V in the Robotlegs-MVCS, the View tier, represents a Component (interactive or non-interactive, visual or non visual) paired to its Mediator.
    But very often we use the term View to denote a Component, be it a simple Button or a pretty complex one containing lots of sub-components, that is mediated. You can mediate every single component or subcomponent in your application, the decision is yours, depending on your project’s requirements and how you want to group the functionality.
    To make it clear that a Component is mediated, a common practice is to suffix the class names:
    SomeView (Component) paired to SomeMediator(extends Mediator)
    and to have a package like this (this is my personal preference, other people do it differently):

    -controllers

    -models

    -views

    -----components

    ----------SomeView.mxml

    -----mediators

    ----------SomeMediator.as

    “Views aggregate components and other views. A LogInPanel is a view. A LogInButton is a component.“
    In your example, using my terminology, LogInPanel would be the View and would have a LogInMediator. The LogInPanel is actually a custom component.
    The class package would be yourpath.views.components.LogInPanel and
    yourpath.views.mediators.LogInMediator.
    The LogInButton could be mediated as well, if you wanted to, but in this case of a simple login form it is probably not necessary, so it would be just a subcomponent.
    So when we refer to the LogInPanel as being a View, we mean the custom Component that has a LogInMediator.
    A custom component can of course contain other mediated Views (custom components).

    Some custom components can be reusable. That’s actually one of the reasons why we use Mediators for communication with other parts of the application.

    “It makes sense that we should not use RobotLegs below the view level of the application. But the question remains: If we develop "deep" ui components, how to propagate data set on the component in the "view"?”

    LogInPanel would dispatch events that LogInMediator would handle and redispatch it to the rest of your application, for example to trigger the LogInCommand, that would call LogInService.
    On logInSuccessful the LogInService would dispatch an event that LogInMediator would hear, and then utilize API methods on LogInPanel to set some data, say change the label of the LogInButton.
    To be consistent with what I said above, I would call LogInPanel LogInView

    More on this later...

  6. 6 Posted by E. on 08 Dec, 2011 08:14 PM

    E.'s Avatar

    Thanks for sticking with me :)

    As you say: Inside an application the distinction between "view" and "component" might be overkill. From the "applications perspective" there is no distinction between "views" or "components". They are all handled the same on the displaylist. And RobotLegs can map a mediator to any ui-type known at compileTime.

    Why distinguish between "views" and "components". Well: Above the "application perspective" there is the "developer perspective". The developer knows of other applications than the one at hand and wants to reuse some components between applications.

    Given the "application perspective" we could have our components tap the application dependency management system and our problem is solved. Given the "developers perspective" this may not be a viable option. A future application dependency management system may not be known at component compile time.

    Reusable components must be framework agnostic (or carry a framework encapsulated inside them). Instantiating an application framework at the component level is considered bad practice – for performance and probably for many other reasons as well.

    RobotLegs is great companion. But it can only accompany you so far. What's best practice when we must leave RobotLegs behind and carry our own data. (Insert tears on cheeks here.)

    This may have turned in to a non RobotLegs question. But it is a dependency management related question. So maybe it still belong in this forum.

    I've tried to look at the FLEX-components for guidance but they all seem to be pretty flat architected (maybe thats my answer) and when they're not they often depends on the developer to assemble them at compile time.

    I'm enclosing a picture with a sketch of the top layers of a TimeLineComponent I'm working on. RobotLegs would operate behind the yellow "view" Layer. The "components" above the yellow "view" layer are intended to be reused in other applications and should not depend on RobotLegs to push dependencies down the tree. Lets imagine that a property needs to travel from the blue [TimeLine] to the unnamed red component below the [EntitySubline]. How would one do that?

  7. Support Staff 7 Posted by Ondina D.F. on 09 Dec, 2011 01:02 PM

    Ondina D.F.'s Avatar

    So, you are actually looking for an architectural solution independent from the robotlegs framework.
    If you don’t like the downsides of:

    • setting the properties on a child component upon its creation from a parent
    • using events dispatched by the sub-component to signal the need for data
    • using BindingsUtils and ChangeWatcher
    • sharing bindable VOs
    • having a reference to the parent to get its data (not really a good option)
    • other ways that I’m not aware of at the moment

    then using a Factory, a Proxy or a Delegate to manage the creation of child components and control the access to them seems to be the best solution for what you want to achieve: assigning properties (and dynamically change them) to well encapsulated and reusable components.
    An implementation of the Class Factory could be what you needed and maybe the benefits of being able to pass properties or even styles dynamically and to manage events would surpass the disadvantages.

    But I hope others will share their opinions as well :)

    I think, and I might be wrong, that you wish there was something similar to robotlegs on the components’ level, an MVC for Views to compensate Flex’s limitations?

  8. 8 Posted by E. on 09 Dec, 2011 09:04 PM

    E.'s Avatar

    You are right: I am probably looking for the RobotLegs that is to a component, what the real RobotLegs is to an Application.

    Some sort of native dependency injection mechanism in FLEX would be great! (Maybe @jhooks could lobby for it as the president of Spoon! :)

    Thanks for your list. Could you elaborate on "sharing bindable VOs"?

    Something similar to your Factory/Proxy/Delegate hint is in fact the best solution I've been able to come up with for my components.

    STEP ONE:
    Define component parts at the Interface/Abstract level. E.g. IScalable, ATimeLine, AEntityGrid, ALineLevel ...

    STEP TWO:
    Implement actual component parts. E.g. DateLine (ATimeLine), WeekLine (ATimeLine), LinedGrid (AEntityGrid) ...

    STEP THREE:
    Implement a "Container" that aggregates selected component parts and exposes a common component interface, aggregated from the interfaces of the component parts.

    In the views, the developer instantiates the container and sets it's properties.

    The container is responsible for propagating property data to component parts. I usually have the Container set up bindings between its own properties and component part properties. The container gets notified of parts being added to its subtree by intercepting the lifecycle events crawling the tree as parts are added to the display list.

    This way the component implementation is encapsulated at the "view" level. And encapsulation continues inside the component. The Container instantiates its concrete children, but are only aware of interfaces of branches further down the tree.

    Maybe this is a good way to do it after all. Now that I've rambled about it a bit.

    Any further thoughts or real world experiences are more then welcome though.

  9. Support Staff 9 Posted by Ondina D.F. on 12 Dec, 2011 11:42 AM

    Ondina D.F.'s Avatar

    Hi E.

    Some sort of native dependency injection mechanism in FLEX would be great! (Maybe @jhooks could lobby for it as the president of Spoon! :)

    Indeed.

    Could you elaborate on "sharing bindable VOs"?

    I mentioned it because it was one of the ways to populate components with data. A bindable VO has its downsides, of course. It is also Flex specific.
    The term “VO” has diverse meaning to different people. I’m sure you already know all this:

    -http://martinfowler.com/eaaCatalog/valueObject.html

    -http://lostechies.com/jimmybogard/2008/05/21/entities-value-objects...

    -http://domaindrivendesign.org/node/135

    -VOs (or TOs - transfer objects) are intended as data carriers to shuttle typed data across tiers

    -VO is a design pattern used to transfer data between software application subsystems

    -A VO should be immutable. It is born with a set of values, and it contains these values until death. It's read-only.(Stray)

    -A VO is an immutable representation of complex state. A snapshot of how things are at a moment in time.(Stray)

    So, in this light, we shouldn’t call it a VO, but for the sake of an example I’ll call it SomeVO, as in a previous post.

    Add the [Bindable] metadata tag to the SomeVO class. Pass a bindable reference to SomeVO to the actors interested in its values. Say, ParentView and SubcomponentView, both hold a reference to it and a change to the someVO.someData in one component will be reflected in the other component as well.

    I’m not necessarily advocating this way of using a VO, but it is something doable.
    Since you don’t want to use robotlegs for passing data to views you’d have to do it like this:

    [Bindable]

    public class SomeVO
    {

    public var someVOData:String;

    public function SomeVO()
    {}

    }

    In your ParentView

    [Bindable]private var someVO:SomeVO=new SomeVO();

    <s:Label text="{ someVO.someVOData}"

    <components:SomeView id="someView" someVO="{someVO}"

    In SomeView

    [Bindable] public var someVO:SomeVO;

    <s:Label text="{ someVO.someVOData}"

    Anyway, that’s probably not what you’re after. Your solution sounds good, as far as I can tell from your description.

    For further inspiration you could also look at how Flex handles styles’ inheritance (StyleManager & Co)

    Others' opinions would be indeed welcome:)

    Ondina

    P.S.
    I don’t know what’s wrong with Tender, but from time to time many posts get marked as spam and some get even deleted. All of your posts have been deleted and I had to restore them every time you’ve posted. We don’t get notifications about such posts, so the only way to see if there are false positive spams is to look into the Spam or Trash folder, and that’s not a nice task:)
    Now, my questions to you are: have you posted via email? Have you registered before posting? Maybe it should be better if you created an account. Thank you.

  10. 10 Posted by erik on 14 Dec, 2011 01:11 PM

    erik's Avatar

    Hi Ondina!

    Thanks for the info on the VO. Read up on something you know and you will learn something new :)

    The VO might be a good "helper" class if the data being passed around is complex. But still – the VO becomes the data that possibly needs to travel the depth of the component. And we are back to unsatisfactory solutions like passing the VO reference from parent to child, parent to child, parent to ... or some of the other solutions we have been discussing.

    The Flex styling mechanism is an option. It is actually a relief when passing around visual configuration data. Like overriding default skin classes for components in a custom project.

    But there is something about the styling mechanism that gives me the chills when I am implementing a custom component. My component should not be qualified to reach out to the global state. This is an illness of UIComponent and we should try to distance us from it.

    But on the other hand: Styles being everywhere in Flex and one can hardly escape them. So maybe one should embrace them. (Keep close to your enemies or something like that!) I don't know how to test a UIComponent without something like FlexUnit's UIImpersonator anyhow.

    Watching the FlexSummit there seems to be smart people thinking about Flex dependency management at the core, integrated with the compiler (?). So maybe the best is yet to come!

  11. Support Staff 11 Posted by Ondina D.F. on 15 Dec, 2011 12:45 PM

    Ondina D.F.'s Avatar

    Hi Erik :)

    You’re right, there is no ideal solution (yet) for what you want to achieve.

    I share your frustration with the Flex SDK and with the lack of an elegant way to manage complex Views (V in MVCS), i.e. a good micro-architecture for components.
    There might be a couple of frameworks out there, trying to solve this problem, but I have no idea what they do. I never tried them. Some are targeting games architectures. So, I’ll mention Gaia, Ember and Starling just as a hint.

    I’ve looked through my bookmarks regarding SwiftSuspenders and as3-signals and I found this:

    http://blog.cjcat.net/2011/10/redesigning-rusher/

    I haven’t had the time to study it, but it looks interesting at first sight. Take a look at it. I'd like to know what you think of it.

    Ondina

  12. 12 Posted by erik on 15 Dec, 2011 02:06 PM

    erik's Avatar

    Love to the people who have potential answers hidden among their bookmarks :)

    I'll take a look at the frameworks you posted and see if I find something interesting.

    /Erik

  13. Support Staff 13 Posted by Ondina D.F. on 15 Dec, 2011 02:47 PM

    Ondina D.F.'s Avatar

    Love to the people who have potential answers hidden among their bookmarks :)

    You do? Really? I’m glad you genuinely love it ;)

    Actually, the “bookmarks” are part of a database that I use in an AIR application. I’ve built it in order to better manage the many resources I occasionally find on the web.
    I’ve already shared (in a post on this forum) ~ 165 links that I gathered under the ‘robotlegs’ category, because I thought it might be useful to have robotlegs-resources in one place.

  14. Ondina D.F. closed this discussion on 17 Jan, 2012 10:57 AM.

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