Why model is "singleton"

Amnesiac's Avatar

Amnesiac

13 Jan, 2012 10:52 AM via web

Hi,

I used to have model classes that stores some data and have inside own childs ex:

class News{
    private var _title:String;
    private var _content:String;
    private var _author:User;
    private var _comments:Array;
    public function get comments():Array{
        return _comments;
    }
    public function getCommentById(id:int):Comment
    {
        return _comments[id] as Comment;
    }
}

And comment class:

class Comment{
    private var _content:String;
    private var _author:User;
    // getters/setters....
}

And when i needed a news with comments and comments with authors:

var comments:Array = news.comments;
for(var i:int = 0; i<comments; i++)
{
    var comment:Comment = comments[i] as Comment;
    trace(comment.author.name);
}

That was very easy, every News has instances of comments and user that was needed, and Comment has instance of User...

But in robotlegs (if im not wrong) I should have one NewsModel, CommentModel and UserModel with several ValueObjects.
Now if i want to get News i need to call newsModel.getNews(id) than: commentModel.getCommentsByNews(news) and than for every comment userModel.getUserById(userId) ... this is strange for me :/

I think I'm on wrong path... help please

  1. Support Staff 2 Posted by Ondina D.F. on 13 Jan, 2012 12:57 PM

    Ondina D.F.'s Avatar

    Hey Amnesiac,
    One way of solving this is to have 3 VOs:
    NewsCommentVO exposing getters and setters for private var _ comment:String;

    NewsAuthorVO exposing getters and setters for private var _ author:String;

    NewsContentVO exposing getters and setters for private var _ content:String;
    private var _ title:String;

    and in a NewsModel, which would extend Actor, you could manipulate and assemble your VOs (set or get their values) and dispatch an event to interested classes in your application with the updated data as a payload (an array or arraycollection or whatever else you need to represent your data).

    The naming of classes and variables is up to you. The above is just an example.
    Does this help?
    Hopefully you won’t forget what I just said;)
    Ondina

  2. 3 Posted by Amnesiac on 13 Jan, 2012 01:29 PM

    Amnesiac's Avatar

    Hi, thx for reply

    what in situation when I change a User name in some User class, but all NewsAuthorVO has this name as a string, so they won't be updated.

    And why NewsModel should retrieve data about Author and Comment.

    And one more thing... when I have User class, in way that You posted i will have
    NewsAuthorVO
    CommentAuthorVO
    ImageAuthorVO
    etc.

    isn't it a duplicate without sense, when all of them are a User equivalent?

  3. 4 Posted by Stray on 13 Jan, 2012 01:33 PM

    Stray's Avatar

    If the data is genuinely interconnected then you need to design your model to deal with this... which is a little outside the scope of what we can direct you on - but you can inject both small 'child' models and a larger parent model that brings them together. Or you can use a factory to assemble appropriate VOs based on more than one model.

    In the specific example you mention, if a user name changes then a UserNameChangeEvent should fire (or similar) and anything that was using the old VO should be updated with a new one that has the new name.

    Stray

  4. 5 Posted by Amnesiac on 13 Jan, 2012 01:39 PM

    Amnesiac's Avatar

    Why not create just one class UserVO and use it in News and Comment, and every change is only on one object?

    But should VO object have instance of other VOs or should all this informations run through model?

  5. 6 Posted by Amnesiac on 13 Jan, 2012 02:57 PM

    Amnesiac's Avatar

    Ohhh... I think I'm getting understand it a little bit...

    All modules (ex. NewsList, NewsDetails) should have own Model:

    NewsListModel - list of some news
    NewsDetailsModel - for selected news

    And when NewsListView object is selected I have to pass it VO to NewsDetailsModel, and NewsDetailsView will have it injected from newsDetailsModel.

    Am I right?

  6. Support Staff 7 Posted by Ondina D.F. on 13 Jan, 2012 04:55 PM

    Ondina D.F.'s Avatar

    And one more thing... when I have User class, in way that You posted i will have NewsAuthorVO
    CommentAuthorVO
    ImageAuthorVO
    etc.isn't it a duplicate without sense, when all of them are a User equivalent?

    Oh, I see what you mean, or so I think. You want to assign an author_name to the content, the one who wrote the article, another name to the person writing a comment, and yet another for the one who’s uploaded an image? If they are 3 different authors you don’t have to create 3 different VO’s just for the author_name.
    If these were tables in a database, you’d have the following tables: Authors, NewsContent, NewsComments with a reference to Authors.id or something like this, because you wouldn’t want to duplicate the tables (NewsAuthor, CommentAuthor). The authors are unique entries in the Author table.

    I'd add an author property to the following VOs:
    NewsCommentVO

    private var _ newsComment:String;
    private var _ newsCommentAuthor:String;

    NewsImageVO

    private var _ imageURL:String;
    private var _ imageAuthor:String;

    NewsContentVO

    private var _ newsContent:String;
    private var _ newsTitle:String;
    private var _ newsContentAuthor:String;

    You could call them all authorID, if you want.

    Now, I’m not sure about what happens in your views (NewsView). You should provide more details about that. So, I’m guessing that you have a list of Authors, passed to the view by its mediator( AuthorsVO).
    The user selects an item from that list and writes some text in a TextArea. Then the user clicks the sendContent button. The NewsView emits an event with authorName, newsTitle and newsContent as a payload.
    Let’s call it UpdateContentEvent.
    The mediator listening for that event re-dispatches it and it triggers an UpdateContentCommand.
    UpdateContentCommand calls newsModel.updateContent() method passing in the authorName, newsTitle and newsContent coming from the NewsView. (NewsModel has to be injected into the command). Within newsModel.updateContent, newsContentVO. newsContent, newsContentVO.newsTitle and newsContentVO. newsAuthor are set to the values coming from the view.

    Same procedure with a comment: user writes a comment, clicks the sendComment button, an UpdateCommentCommand calls newsModel.updateComment(), where newsCommentVO.newsComment and newsCommentVO.newsCommentAuthor are set.

    The AuthorVO in this example has nothing to do with NewsModel. It just serves as dataProvider for the authorsList in NewsView.

    You can send the data to a server or use it elsewhere in your application.
    On the way back to the view, if you wanted to load News, NewsMediator would redispatch NewsView's request for data and in a LoadNewsCommand you could access a NewsService and when NewsModel gets updated it dispatches an event for the mediator to handle. The NewsView would take care of populating the content, comment or other input fields.

    Your scenario might differ, so without knowing it, I can’t say if the above is what you need:)

  7. 8 Posted by Amnesiac on 13 Jan, 2012 05:10 PM

    Amnesiac's Avatar

    Thx for all replies, I think everything is clear now.

  8. 9 Posted by Amnesiac on 14 Jan, 2012 02:05 PM

    Amnesiac's Avatar

    =[ still don't get it :/

    I will describe my real situation... maby it will be easier.

    I got XML with data as a tree:

    customer
    - modules -- functionalities --- properties

    So customer have some modules and every module have some functionalities and every functionality have some properties.

    My model looks like: - CustomerModel - ModuleModel - FunctionalityModel - PropertyModel

    Now CustomerService loads XML and put data about Customer and a list of Modules into CustomerModel

    But I don't know how and when should I get data about Functionalities and Properties.

    View: ModulesListView - shows a list of modules in my Customer and when select one of Modules a FunctionalitiesListView should appear

    So my ModulesListViewMediator dispatches SELECT event and now what? How can I get data about Functionalities? Via CustomerService again? All XML data to CustomerService was loaded earlier.

    I used to build a classes like: Customer with Array of Module which had Array of Functionality which had properties.
    But in robotlegs VO objects don't have Arrays with their childs...

    Same thing about saving data... I got data in my VO objects, but their are in so diferent places.. CustomerVO and ModulesVO in CustomerModel, FunctionalityVO where? Their are loaded just for one selected module, so when I select a different one all FunctionalityVO are gone... (I don't want to save XML after every action, I want to have it in memory and later do save for all configuration).

    Hope it's clear :/

  9. Support Staff 10 Posted by Ondina D.F. on 14 Jan, 2012 04:50 PM

    Ondina D.F.'s Avatar

    Hi Amnesiac,

    =[ still don't get it :/

    Sorry to hear that.

    The scenario you are now describing is different from the one presented initially in your post, and not very clear, at least not to me. I’d have to ask you a few questions in order to understand the difficulties you’re encountering, but I won’t be able to do so until Monday.
    If you could attach a stripped-down example that replicates the problems you are having, it would be much easier to address each question separately and find a solution.
    Hopefully, someone else will help you sooner.

    Ondina

  10. 11 Posted by Amnesiac on 14 Jan, 2012 05:07 PM

    Amnesiac's Avatar

    Generaly my problem is very easy. I have objects that contains objects that contains objects...

    And don't know how to use Models to get posiibility of smth like that:

    customer.getModuleById(3).getFunctionalityByType('someType');
    

    My ModuleModel have currentSelectedModule (on some list) and I have acces just to this Module (which is selected).

    So when I select some module I can do anything with it, but can't get access to all others.

    All examples on the internet show only simple apps that stores for example UserData, or some Tasks, bo none them shows situation when object -> got objects -> every of objects -> got more objects.

    I got one CustomerModel object - and one customer (that is ok)
    I got one ModuleModel object - and multiple Modules objects that are stored in ModuleModel (that is ok)
    But now I got one FunctionalityModel - and multipliple Functionalities for multiple Modules (here, I don't know how to store, multiple objects of multiple objects in one class and have easy access to them not like getFunctionality(customer, module, index) just module.getFunctionality(index) )

    That my problem:/

    If ValueObjects could contain a Arrays it would be easy for me, but how I know VO are just simple objects with simple data, no arrays.

  11. 12 Posted by Amnesiac on 15 Jan, 2012 09:59 AM

    Amnesiac's Avatar

    Please help me with that... Why should I use mapSingleteonOf for Models when i got so many Modules instances, so many Functionality instances and why all of that goes through a singleton :/

  12. Support Staff 13 Posted by Ondina D.F. on 15 Jan, 2012 11:57 AM

    Ondina D.F.'s Avatar

    I’m really sorry that you are having such a hard time.
    I would like to help you, but I’d need more time to understand your problems and to thoroughly answer your questions.
    I guess the reason none else answered either is that usually on weekends not many people are online or have other things to do:)

    I’ll give you a really quick answer, but I’m not sure it will help you at all.

    If ValueObjects could contain a Arrays it would be easy for me, but how I know VO are just simple objects with simple data, no arrays.

    You can have any type of data in a VO: strings, numbers, arrays, vectors...

    There is a difference between Models and VOs, and there are different definitions of the roles of a VO .
    A Model can manipulate data, assemble it, and can dispatch events on the shared event dispatcher to other parts of your app with that data as a payload.
    A VO is very often just a set of values (any type of values), but as I said, there are different interpretations and implementations, and you can choose what’s more appropriate for your use case.

    See the links provided in this post: http://knowledge.robotlegs.org/discussions/problems/451-no-subject#...

    In A Model class you could do:

    customerVO.id=id from xml;
    customerVO.modules = modules;//the getter bellow

    moduleVO.id=id from xml;
    moduleVO.functionalities=functionalities;

    
    public function get modules():Vector.
    {
    var vectorOfModules:Vector.< ModuleVO > = new Vector.< ModuleVO >();
    var xmlList:XMLList = xml..Module;
        for each ( var moduleXML:XML in xmlList) 
    {
            var module: ModuleVO = new ModuleVO (moduleXML);
            vectorOfModules.push(module);
    }
    return vectorOfModules;
    }
    

    Then a similar getter for Functionalities, returning functionalities.

    The Model can dispatch an event with whatever you need in your view(customerVO and/or moduleVO)
    The view can ask the Model(event->mediator->command->model) for a certain module by id (selectedItem in a modulesList in the view) and the model would look for it
    module=customerVO.modules[id]; and return the module data and the vector of functionalities.

    Now the parsing of an XML can be done in a Parser class, called by the Service class, but the above is just an example.

    Or, start with only one Model(and no VOs), make it work(xml parsing, assigning values to vectors, dispatching events) and later you can refactor the whole thing and make it more granular and loosely-coupled.
    I really, really don’t know if this will help you. I wrote it fast, without much thinking, and I could be totally wrong. I feel your pain, and I’m sorry for not being able to help you right now. Chances that anyone else will answer today are low.

    Until tomorrow, then :)
    Ondina

  13. 14 Posted by Amnesiac on 16 Jan, 2012 07:53 AM

    Amnesiac's Avatar

    Thank you very much Ondina for your help.

    I have one more question:
    VOs are not straight representation of application data becouse they can be cloned, and Models have many copies of the same VOs (for example ModulesListModel and ModuleDetailsModel have copy of the same VO object). So where should I store data, or get from where to save later the whole application config.xml?

    Is it correct to get data from a ModulesListModel (but what if user didn't even opened a ModulesListView and the model is not initialized?). Or maby I should store whole data in some ConfigModel class which would be my application centralized data storage?

  14. Support Staff 15 Posted by Ondina D.F. on 16 Jan, 2012 12:47 PM

    Ondina D.F.'s Avatar

    Hey Amnesiac,

    I’m sure you’ve already read the Best Practices and other tutorials about the roles of the RL classes. Nevertheless, I’ll repeat some of the definitions and roles of the different classes and tiers to make sure we are on the same page :)

    You have some data from external resources (database, file system, other applications) that you want to expose to users of your application and let them interact with it (load, save, update, delete) through a user interface (View).
    You have data on the one side and the visual representation of data on the other side, Resources-----GUI.
    The role of a Service in rl is to connect your application with the outside world (resources), and to interact with it, retrieving data, loading data, sending data to a server or writing it to the hard-disk.
    Now you have your data loaded by a Service and your application can use it. A Service class in rl doesn’t store the data and usually it doesn’t manipulate the data either.
    A Service is exactly what its name implies: a servant, a supplier, a provider.
    What happens to the loaded data and how can you make it persistent in your application?
    Through using Models and VOs.

    Services+Models+VOs =responsible for retrieving data, manipulating data, persisting data structures

    Service = gatekeeper to the outside world, data supplier, data source
    Model = deals with data, data modeler, responsible for manipulating the application’s states
    VO=data carrier class to shuttle typed data across tiers

    Controller=Events+Commands= application logic = application’s behaviour= use cases
    Commands act upon Models and Services, usually in response to user interactions with the application

    View=user interface
    Mediator= intermediate, intermediary between application and View, wiring the Views to the shared event dispatcher.

    Services are the intermediaries between an application and the outside world; Mediators are intermediaries between the application and the user interface.

    --

    Let’s work through a very simple use case to illustrate one of the many ways of using Models.
    View: a List of users’ names (usersList) and a Text element (userName).
    You want to populate the List with names coming from an external service.
    You also want to add a new name to the list and send it back to the external service to be saved. Or you want to use the (same) usersList in several places in your application.
    First thing you want to do is to load the data.
    What to do with the loaded data? How will the data get to the View?
    In a UserVO you define a property usersNames:Array.
    The UserModel gets the loaded data from the UserService and sets the userVO.usersNames to the loaded list of names.
    UserModel sends the UserVo to the View (payload of a dispatched event) and the UserView populates the usersList with it.

    For now, the data is persistent, stored in the UserVO. If you don’t add/delete a new name to/from the list, you can use it everywhere in your application, for instance in another View that needed such a list of users. It would be the same data.

    Why didn’t you set userVO.usersNames=service.result in the UserService class right after the data arrived? Why do you need a UserModel to act upon a UserVO?

    As I said, you’d have a text field userName in your UserView. You want to add a new user name to the list of users. You click on addUser button and the handler function acts upon the UserVO, modifying the usersNames array. But the usersNames lists in other Views won’t be affected by those changes (unless you use bindings, but in this example we’ll ignore other ways of using vos). Let’s say that AnotherView’ usersList has been populated with the same userVO.usersNames initially, and you can add/delete users to/from this list as well. Now, if you modify the usersList in one of the Views, the 2 lists in UserView and AnotherView will be different. Which one of the 2 usersLists will you now send to a server?

    Using a Model can solve this issue.
    If you modify the usersNames in one view (UserView), you’ll have to send it to UserModel (event-mediator-event-command-model) which will then update userVO.usersNames and dispatch an event with the updated UserVO to all interested parties, i.e. UserMediator and AnotherMediator, which will let their views update the dataProviders of their usersList with the same usersNames. For this to happen the 2 Mediators have to register an event listener for the same event. Same for AnotherView, let the UserModel update the changes to the list, so UserView will have the same data.

    The UserModel will be responsible for keeping your data persistent and consistent throughout your application. It will make sure that changes in one place will be reflected in other places too, if need be. Your VOs are just like a variable, they hold data. A VO is a transport box and the Model puts stuff into it and makes sure that they are transported and delivered to other parts of the application, not directly, but by dispatching events, which will carry the boxes.
    The UserModel should reflect the latest changes made to UserVO, to be used within your application or to be send to an external server.

    From your last question:

    VOs are not straight representation of application data becouse they can be cloned, and Models have many copies of the same VOs (for example ModulesListModel and ModuleDetailsModel have copy of the same VO object). So where should I store data, or get from where to save later the whole application config.xml?

    The Models would be responsible for keeping data in synch or to use a different set of data depending on the use case. The ModulesVO(or how else you name the common VO) will be just the carrier of that data. Each Model can dispatch a different event or the same event, and how they manipulate ModulesVO is up to you. But I’m not sure I understood what you meant or what you really want to achieve. You’re changing the scenario with every new post ;)

    But maybe you don’t even need 2 different Models. Maybe a ModulesModel could deliver data in different formats, as an array or arraycolection or single variable, depending on what you need. You’d have public methods (accessible from a Command for example) like this
    public function get modulesAsArray():Array
    public function get modulesAsArrayCollection():ArrayCollection
    public function getModuleById()

    and send that instead of a VO to interested parties.
    dispatch(new ModuleEvent (ModuleEvent.MODULES_LIST_CHANGED, modulesAsArray);

    I’m not sure I understand the role of your config.xml. Is it just a set of loaded config data that you’ll never change in your app but you want it to be accessible from everywhere? What does it have to do with the 2 other Models?
    Are you asking how to save a set of data that you modified in your application due to user interactions?

    Is it correct to get data from a ModulesListModel (but what if user didn't even opened a ModulesListView and the model is not initialized?). Or maby I should store whole data in some ConfigModel class which would be my application centralized data storage?

    If I understand you correctly, you mean that data has been loaded before the Mediators were able to receive it (because the View is not on the display list yet, therefore the Mediator hasn’t been created, so it can’t listen for an event from the Model).
    In this case you either let your Mediator ask for data in its onRegister() method or you make sure to load the data from an external source after all the mapping has been done and your application is ready for interactions (in Flex after the Application dispatches FlexEvent.APPLICATION_COMPLETE) or use utilities like RelaxedEventMap, StateMachine, creynders’ bootstrapping example...

    I hope that was somehow helpful to you.
    Ondina

  15. Support Staff 16 Posted by Ondina D.F. on 16 Jan, 2012 02:04 PM

    Ondina D.F.'s Avatar

    To your question:

    Why should I use mapSingleteonOf for Models when i got so many Modules instances, so many Functionality instances and why all of that goes through a singleton :/

    From Best Practices:
    mapSingleton provides a single instance of the requested class for every injection. Providing a single instance of a class across all injections ensures that you maintain a consistent state and don’t create unnecessary instances of the injected class. This is a managed single instance, enforced by the framework, and not a Singleton enforced within the class itself.

    mapSingletonOf is much like mapSingleton in functionality. It is useful for mapping abstract classes and interfaces, where mapSingleton is for mapping concrete class implementations.

  16. 17 Posted by Amnesiac on 17 Jan, 2012 08:21 AM

    Amnesiac's Avatar

    Thx again Ondina, I'll try to rebuild my model using your directions. Hope with success now :)
    And sorry for my english :)

  17. Support Staff 18 Posted by Ondina D.F. on 17 Jan, 2012 10:44 AM

    Ondina D.F.'s Avatar

    Thx again Ondina, I'll try to rebuild my model using your directions. Hope with success now :)

    You’re welcome!

    And sorry for my english :)

    Don’t be sorry. Not a problem to me, I’m not a native speaker either.
    I’ve just finished another long explanation that is probably not going to help you much either, since, as it seems, I don’t understand the flow of your application, the use cases and what exactly is the issue, but I’m going to post it anyway ;) You can as well ignore it.

    I hope you’ll find a solution. It would be nice to let us know how you solved that particular problem.

    -- Here, the long ‘essay’:

    How you build your Models or how many of them you need is also very much dependent on how you define the functional areas of your application.

    UserView + UserMediator, UserModel + UserVO, UserService, UserCommand+UserEvent would be the classes responsible for the User area of your application - User management, loading, modifying, and presenting the User data in different ways (forms, datagrid, lists).
    In UserView you could add, update, delete users and these changes would be reflected in your UserModel. Your UserModel can provide methods like createUser(), deleteUser(), addUser() and so on, which would modify the state of your User data ( USER_ADDED, USER_DELETED ).
    How your UserVO will look like is dependent on what kind of information you want to have in your view, a single user with details (name, age, hair color), or a list of users? You can, of course, have 2 VOs as well: UserVO (id, name, age, hair color) and a UsersVO (that would return an arraycollection of all users). It’s really up to you how you design it.

    ProductView + ProductMediator, ProductModel + ProductVO, ProductService, ProductCommand+ProductEvent = Product area

    Now, you could as well use a single Service for the communication with external resources, you don’t necessarily need 2 services like UserService and ProductService, but we are talking about Models now.

    In another part of your application you’d want to have a combination of User and Product presented in a StatisticsView or something.
    That will be your Statistics area.
    The StatisticsMediator can send a request for data in behalf of its StatisticsView. A StatisticsCommand triggered by a StatisticsEvent could
    -either access the UserModel and ProductModel getting their users’ and products’ arrays and send them back to StatisticsMediator

    -or get the data from UserModel and ProductModel and pass it to a StatisticsModel, which would perform some calculations, stored in a StatisticsVO to be sent to StatisticsMediator

    It all depends on how you need your StatisticsView to present the data.

    -If you need just a usersList list and a productsList (simplistic scenario, of course) you can choose the first approach

    -if you need some calculation based on the numbers of Users and Products, you can let StatisticsModel do that and send the needed data to be shown as a PieChart in StatisticsView.

    If the external resource would be a data base, you’d retrieve the User from a User table, Product from a Product table and so on. Of course you can make a Service call for both to be loaded in a single result. In this case you’d let a Helper class, or a Factory as Stray mentioned, distribute the data to the Models and VOs, User to UserModel and Product to ProductModel and each of them would dispatch separate events for the Mediators to hear. UserMediator would pick up the User data from a UserEvent, ProductMediator the Product data from a ProductEvent.
    Or, the 2 Mediators would listen for the same event (name of your choice), carrying both User and Product data, and they’d have to decide which data was meant for them. But it would be better to avoid letting Mediators make such decisions, if possible.

    So no matter how you load the data, you’ll have to decide which Model+VO is more suited to store and/or manipulate the loaded data. An XML is just another way of representing data. Maybe you just need a class that would distribute the data to a certain VO or Model, but what goes where is for you to decide. And, maybe you don’t need Models and VOs at all; maybe your XML is just meant to serve as a dataProvider for a list that you’ll never modify during your application’s life-cycle. In this case you can let the Service dispatch an event with the XML (converted into the desired data type) as a payload.

    When you use Models, you’re not forced to have only one VO per Model. You don’t need to have one Model performing just one task either. Of course, it’s good to keep the amount of tasks to a minimum and the types of data manipulation somehow related.

    As I said in a previous post, there are different ways of using Models and VOs and also different opinions about their roles. How you access your Models or from where is another complex and controversial topic. You’ll be the one to decide how strict you need to be about all this.

    You can use something like a 'SmartVO', which does a lot of work on data, but a VO can’t dispatch events to the shared event dispatcher, unless it extends Actor, which would make it to a Model;)
    You also can make a VO bindable.
    You can ignore Models and VOs altogether, and use a class that would do what you wanted it to do. The use of the MVCS’s classes is not mandatory.

    As for something like your ConfigModel, if you want to have access to it from everywhere in your application, you let the interested parties listen for the same event, dispatched by the ConfigModel or you ask a Command to access the model whenever you need it. So, it would be a good idea to have just a single instance of that class.

    As for saving a set of modified data to an XML file:
    In a Command you get the data from the Model, parse it back to XML (in a Helper/Parser class) and pass it to the Service which would write it to the disk.

    Maybe your real problem has to do with the way you extract the objects from the hierarchical XML, how you traverse the structure etc. And maybe using a filter for your collection would be enough to solve your issue, setting the dataProvider of your tree lists after filtering the nodes, ...I don’t know, I’m just guessing...
    Long answer, and I’m not even sure I answered all your questions...

  18. 19 Posted by Amnesiac on 18 Jan, 2012 11:58 AM

    Amnesiac's Avatar

    Hi again.

    i understand that I can have UserVO and User2VO with data about the same user but for some different views.

    When some View need some data about user I can use UserVO and if another View need less data I can user User2VO (with for example just name).

    But in this case how can I save data to XML later, get some data about user from UserModel and some data about the same user from other Model?

    Where should all data about User be stored (not for views).

    When using database I can update records every time some data are changed. For example, user changed his name, listener gets a UserVO and Service updates the database. But I don't want to update it after every action. I want to store it and do it later when someone click "save" button. But not save for user, save for whole application (before close).

    Maby I should have myCustomService that stores data in some objects temporary, and before app close, XMLService should take data from MyCustomService and save it as XML?
    So when UserVO is updated, MyCustomService takes data from it and stores in his User class that represents a single user?

  19. Support Staff 20 Posted by Ondina D.F. on 18 Jan, 2012 01:30 PM

    Ondina D.F.'s Avatar

    Short answer: the UserModel class stores all the UserVOs in an ArrayCollection (or any other wrapper class). When you need to save it, you get the collection from the model, you parse the collection back to XML, and a Service would write it to the disk.

    You’d have several UserVOs, and one usersCollection of those vos. You can search the collection for a userID (or other criteria) and access the UserVO for that userId.
    If you want to create a new user, a new UserVO is created and added to the usersCollection, with a new userID.
    If you want to delete a user, you search the usersCollection for a certain userID, and remove that item and the vo.
    In UserModel you’d have methods to do this(add, delete etc)

    So, one UserModel (mapped as a singleton) has one usersCollection containing many UserVOs.

  20. 21 Posted by Amnesiac on 18 Jan, 2012 01:38 PM

    Amnesiac's Avatar

    But You said in eariler posts that NewsVO can have Vector with CommentVO.

    Now if i have NewsVO stored in NewsModel as ArrayCollection, every NewsVO have Vector of CommentVO.
    And now CommentModel have ArrayCollection of all thoes CommentVO from all NewsVO ?

    And You said that if View need some other data, I should create User2VO with different properties than in UserVO. Which of them should have complete data :/

  21. Support Staff 22 Posted by Ondina D.F. on 18 Jan, 2012 04:01 PM

    Ondina D.F.'s Avatar

    But You said in eariler posts that NewsVO can have Vector with CommentVO.Now if i have NewsVO stored in NewsModel as ArrayCollection, every NewsVO have Vector of CommentVO. And now CommentModel have ArrayCollection of all thoes CommentVO from all NewsVO ?

    No, it should not result in such a convoluted structure. When I talked about this scenario, I mentioned using a single Model which would manipulate all the VOs. You might have a good reason for having a model for each of them, though.

    But let me answer your last question first (repeating a lot of what I've already said):

    And You said that if View need some other data, I should create User2VO with different properties than in UserVO. Which of them should have complete data :/

    UsersListView : usersList (a list of users)
    UserDetailsView: userForm

    Updating a User:

    1. In UsersListView you can select a user and dispatch an event with the selectedItem, containing the userId
    2. UserMediator re-dispatches new UserEvent (UserEvent.USER_SELECTED, userId)); triggering UserDetailsCommand
    3. UserDetailsCommand has UserModel injected (UserModel being mapped as a singleton)
    4. UserDetailsCommand calls userModel.getUserById
    5. UserModel: searches the usersList (arraycollection of userVOs) for userId
    6. dispatches a new UserEvent (UserEvent.SHOW_USER_DETAILS, userVO));
    7. UserDetailsMediator passes the userVO to the UserDetailsView
    8. UserDetailsView populates a form with the details,
    9. where, for example, you change user’s address
    10. and hit the updateUserButton
    11. in updateUserHandler, the UserDetailsView assigns the values of the form inputs to a UserVO
    12. and dispatches UserEvent.UPDATE_USER with the UserVO as a payload
    13. UserMediator listens for that event and redispatches it,
    14. tiggering a UserUpdateCommand,
    15. which calls userModel.updateUser(event.payload). The payload contains the UserVO
    16. UserModel has usersCollection as an ArrayCollection or any other collection or wraper of all UserVOs
    17. UserModel searches the collection for the userId,
    18. finds the UserVO for that user
    19. and UserVO’s properties get updated

    Adding a new User

    If instead of updating, you’d add a new user in your UserDetailsView, the UserModel would create a new UserVO and would add it to its usersCollection.
    Now, as I said, you can store a list of users in a separate VO, but you don’t have to !
    I was mentioning the second VO just as a possibility, nothing more.

    Instead of a separate VO for an array of users(containing a name and id), you can extract the array of users from your usersCollection directly in your UserModel and dispatch an UserEvent.USER_LIST_UPDATED with the users array as a payload to UsersListMediator, and UsersListView would update its usersList’ dataProvider. Now, everything is up to date.
    If you’d have the users list in a separate VO instead of an array in the UserModel, you’d have to update this VO in your UserModel, after adding or deleting a user.

    UserModel takes care of keeping the data consistent: it dispatches events (with the updated data) for the interested parties , i.e. to UsersListView, when a user gets added or deleted, or to UserDetailsView after selecting a user from the user list., so both would be in synch.

    The userCollection in your UserModel is “caching” the data until you want to save it (data base, file).
    If you want to save all users after clicking some saveAllUsers button a SaveUserCommand would take the data from UserModel (usersCollection) and send it to a UserService. If you need it in XML format you’d have to parse it first and then send it to the UserService.
    In SaveUserCommand:
    userModel.getUsersCollection - returns the usersCollection
    parser.arrayCollectionToXML(usersCollection) - returns the xml
    userService.save(parsedCollection) saves it.

    If you need User's details or a list of users elsewhere in your application, you'd have to get their data through UserModel. You wouldn't need a new Model to do that.
    In this scenario, UserModel is the single point of contact to your user data. Whoever needs a User (or users) has to ask the UserModel to provide it.

    HTH

  22. 23 Posted by Amnesiac on 18 Jan, 2012 04:53 PM

    Amnesiac's Avatar

    Ok, I get it. But when I have an arrayCollection of arrayCollections (every User for example have a images) then I should call ImageModel.getUserImages(userId) and go throught all images and return those that have correct userId right?

    I used to have user object that contains its own images, with robotlegs models I have all images in one arrayCollection and goes through all of them to get his own when needed.
    Wysłano korzystając z usługi Era mail wersja BlackBerry®

  23. Support Staff 24 Posted by Ondina D.F. on 18 Jan, 2012 05:21 PM

    Ondina D.F.'s Avatar

    You can reverse the representation of a certain object, of course, and use the id of its parent as index:

    Image[userId] = imageURL

    Image[0] = “smiley_happyface.jpg”;
    Image[1] = “smiley_sadface.jpg”;
    ... [Edit] What I actually meant to say was an array of parents ids for each image id (bottom-up)

    You don’t have to use an ArrayCollection. You can use whatever you want: Object, Array, Dictionary, XMLList, Vector.
    Collections have filter, or sort methods and other methods that are useful.
    But it really doesn’t have anything to do with robotlegs, meaning that robotlegs doesn’t force you to do things in a certain way, as I already mentioned in the previous posts. A Model class is provided by robotlegs just as a convenience (the ability to dispatch events on the shared event dispatcher).

  24. 25 Posted by Amnesiac on 18 Jan, 2012 05:38 PM

    Amnesiac's Avatar

    I know that I can use array or vector etc. But want to know should I collect all users images in one collection in ImageModel and search in it every time when I need one user images. ImageModel.getUserImages(userId) or in some other way...

    Wysłano korzystając z usługi Era mail wersja BlackBerry®

  25. 26 Posted by Amnesiac on 18 Jan, 2012 06:03 PM

    Amnesiac's Avatar

    For example, one collection of images for every user.
    Wysłano korzystając z usługi Era mail wersja BlackBerry®

  26. Support Staff 27 Posted by Ondina D.F. on 18 Jan, 2012 06:13 PM

    Ondina D.F.'s Avatar

    Sorry, but I got to go now.

  27. Support Staff 28 Posted by Ondina D.F. on 19 Jan, 2012 10:27 AM

    Ondina D.F.'s Avatar

    There are several approaches to managing collections of objects and parent-child hierarchies. Some of them:

    1. top-down
    2. bottom-up - each child has the parent identifier
    3. list of child object identifiers (aka foreign keys) in the parent object
    4. bi-directional parent-child relationships - child "knows" about its parent, and the parent "knows" about the child objects
    5. linked lists
      and others...

    You’ll have to read more about these patterns (look for DAO, DTO, Object-Model) and find out each one is more appropriate for your use case.
    Whether you need to build a hierarchical relationship between robotlegs’ Model classes or VOs, it’s really up to you ( whether you have a parent Model and several children Models, or you go the path of having parents VOs having a reference to children VOs collections), but you'll need some kind of a hierarchy to manage the relationships between your objects.

    Of course, if you end up having circular references, it will be harder to manage them.

    I can’t give you the ultimate solution and I can’t design your application for you.
    If you’d show us how you’ve built your Model classes and VOs (you can either paste the code in here or attach it), it would be easier to see if there is an issue specific to robotlegs or not.
    Or, at least show us a (reduced) non-robotlegs version that is working as expected.
    Otherwise, the discussion will continue to be too theoretical and speculative.

    Why are the examples you’ve mentioned initially (News, Customer) still not working, after all that’s been said in this post? Have you tried to make them work with robotlegs already, or all the mentioned use cases were just theoretical?

    I used to have user object that contains its own images, with robotlegs models I have all images in one arrayCollection and goes through all of them to get his own when needed.

    You can do that (User object containing its own images). How you manage that is dependent on the overall design of your application and how you want to use these images.

  28. 29 Posted by Amnesiac on 19 Jan, 2012 10:33 AM

    Amnesiac's Avatar

    Thx again. I'll try to make a lot of work and maby put some code to review to make the conversation easier.

  29. Support Staff 30 Posted by Ondina D.F. on 19 Jan, 2012 10:42 AM

    Ondina D.F.'s Avatar

    Thx again.

    You're welcome.

    I'll try to make a lot of work and maby put some code to review to make the conversation easier.

    Yes, that would be good:) Good luck.

  30. 31 Posted by Amnesiac on 21 Jan, 2012 12:19 PM

    Amnesiac's Avatar

    Hi again. If You have a time and can take a look on my code...

    http://kuziu.dmkproject.pl/editor.zip (AIR app)

    ConfigService loads XML and puts objects parsed by ConfigParser to models.

    config.xml have one customer with multiple modules, and every module have some functionalities.

    Most important files for me are: CustomerModel, ModuleModel and FuntionalityModel.

    Thx

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