View Full Version : Command Pattern Query
mcampster
04-10-2008, 11:16 AM
I'm using the MVC Model, with the Command Pattern playing a large part within the controller.
The view dispatches various events, and I have a commandFactory (FrontController) that listens for these events and delegates to a new instance of particular command object. This command object then does what it needs to do (updates backend database, updates model) before dispatching an event to redraw the view. The 'View Helper' then redraws the view and we start again. I understand this is similar to Cairngorm, however I have NOT used Cairngorm in my implementation.
I have two questions...
What happens to the instance of the Command Object that was created? I assume that because nothing references it it would be garbage collected.
Secondly, if the command object was for example part of a wizard with 3 stages, each stage would require further user input. So when the view dispatches an event to either move to next stage or move to previous stage, how would the FrontController 'find' the command object?
Thanks
Mark
kahuja
04-10-2008, 01:42 PM
1. The GC will collect the Command Object
2. If you need to get back to the command, then you will have to register that in a Dictionary and clean up later - a design you will have to code, But, i will challenge the reason for using the same Command object. If you are in a wizard, and you need 3 pieces of information, then there should be 3 commands for the same. This way, if you want to extend the command to another grid you can do it. Example: If you have a wizard that has a command for accepting license, having a command of its own means that you can re-use the command in another wizard that needs to accept license.
Makes sense?
mcampster
04-10-2008, 02:10 PM
I see your point, and it does make sense. But...
What I really would like, is to link 2 commands together. So 1 command always happens after another command. I will explain why I need to 'link' 2 commands. A user requests a page via a navigation tree, but the command that is in charge of getting pages realises that it doesn't have enough information to get this page. It delegates the job to another command, that is in charge of getting this extra info from the user by drawing another, intermediate page, on screen.
The user fills in the appropriate details, and then click Submit. I would like the controller to then continue the original command.
So, using your suggestion of a dictionary, I would store the commands in a dictionary, but would I have to pass a reference to this around the view, so that the next click by the user knows which command to get out of the dictionary, or do I save like a session variable into the model?
kahuja
04-10-2008, 03:22 PM
sorry, i can't help you It is simple, if you cant please do not post - saves me one less email in my inbox.
kahuja
04-10-2008, 03:26 PM
I see your point, and it does make sense. But...
What I really would like, is to link 2 commands together. So 1 command always happens after another command. I will explain why I need to 'link' 2 commands. A user requests a page via a navigation tree, but the command that is in charge of getting pages realises that it doesn't have enough information to get this page. It delegates the job to another command, that is in charge of getting this extra info from the user by drawing another, intermediate page, on screen.
The user fills in the appropriate details, and then click Submit. I would like the controller to then continue the original command.
So, using your suggestion of a dictionary, I would store the commands in a dictionary, but would I have to pass a reference to this around the view, so that the next click by the user knows which command to get out of the dictionary, or do I save like a session variable into the model?
I am a big MVC fan - so what you need is information between two commands and not the command itself. So, here is the deal:
1. Call Command1 - which finds it needs more info;
1.1. Command1 will send update the model to show a new view
2. The new view (View2) will then send the request back to Command2
3. Command 2 gets the information and updates the model
4. Command 2 then dispatches an event to Command 1
5. Command 1 now completes it work
I am not answering the Disctionary question because i feel that is a wrong way to go to. In case, you want to go down that road, let me know and i can help you there as well.
mcampster
04-10-2008, 04:08 PM
I am a big MVC fan - so what you need is information between two commands and not the command itself. So, here is the deal:
1. Call Command1 - which finds it needs more info;
1.1. Command1 will send update the model to show a new view
2. The new view (View2) will then send the request back to Command2
3. Command 2 gets the information and updates the model
4. Command 2 then dispatches an event to Command 1
5. Command 1 now completes it work
I am not answering the Disctionary question because i feel that is a wrong way to go to. In case, you want to go down that road, let me know and i can help you there as well.
So, at point 4, Command 2 dispatches an event to Command 1. Is this the same instance of Command 1 that was instantiated in point 1, or a new instnace of command 1? I assume it is the latter, as otherwise I would still need to pass a reference around Command 2 and the view to Command 1.
kahuja
04-10-2008, 04:19 PM
Yes it is a new instance of Command 1.
mcampster
04-10-2008, 04:29 PM
Thanks - that seems to make sense.
Final question - is there any situation, if using MVC, where you could NOT store the data in the model but pass it into the view, and back up in the next event?
In this particular situation, the data isn't really 'model' as such as it is completely unrelated to the actual data that makes up the app, but more temporary data associated with the view.
Just wondering if it is frowned upon to pass this kind of info around in the events?
kahuja
04-10-2008, 04:45 PM
I will still say that it is a model, even though transient. But, if you can use Events to pass that data to the view, which would be okay.
And, no passing info in events is not an issue - that is what events are for. They get created, get captured, server their purpose and die away. Like a thread in any single-threaded app.
mcampster
04-11-2008, 08:38 AM
Thanks.
So, if I am always creating NEW instances of the commands, which does seem like the correct thing to do, how would you go about undo-ing a previously executed command? Would this not be a case for using an UNDO dictionary, that holds references to the last 5 executed commands giving the user the ability to roll back changes made by these commands?
kahuja
04-11-2008, 08:53 AM
What do you mean by UNDO. Undo is not about commands, it is about data. So, if you have to do an undo, then you need to to know changes done and then roll them back. And, as I see you can not (should not) use the same commands.
mcampster
04-11-2008, 09:03 AM
What do you mean by UNDO. Undo is not about commands, it is about data. So, if you have to do an undo, then you need to to know changes done and then roll them back. And, as I see you can not (should not) use the same commands.
Well, one of the main reasons I chose the Command Pattern was for the ability to UNDO a command.
The majority of our commands are about retrieving data and placing it in the model, or manipulating data and posting back to the back end db. So, all the commands that manipulate data in some way can be 'undoable' commands. I was thinking of having a stack of undoable commands so that if the user chooses to undo a previously committed transaction, the front end can simply post the old data (which it would keep in the command) back to the database.
Is that not one of the big advantages of the Command pattern? All of this is purely design at the moment, and testing ideas out but this was one of the ideas I didn't see any problems with. The only thing I was unsure of was whether to store the old 'undoable' commands in the model, or keep reference to them in some kind of commandManager?
kahuja
04-11-2008, 09:10 AM
Let me clarify, i think i may have jumped the gun with my articulation.
One of the biggest reasons to use the Command pattern is to be able to to Undo and you decision is correct. But, what I meant was that there could be several ways to do it because you want to undo actions on data/model. I think where I lack visibility was that what is your data store - so if you are sending messages to an external system, then UNDO would be something that would need additional logic like serving another API which can be a command of its own, just that when you call UNDO on command1, it simply fires another command UndoCommand1 (bad names :-) ).
So, in short you can use the same, just see where the logic/code should go, in same command or another one. Always, consider that commands are also used so tha they can be reused, can there be a case that 2 commands can call same undo? Example: 2 commands send print jobs (word, poertpoint), but undo would be to cancel the queue which can be re-used.
Makes sense?
mcampster
04-11-2008, 09:26 AM
OK, I will explain my app in a little more detail...
The application is mainly a front end to a database. Its main purpose is to collect and manipulate data. Using a database of products and suppliers as an example:
Using an MVC design, when the details of a product load up on the screen, the representation of this product in the flex Model is state A.
The user makes changes to the product using a view. The view now contains the altered details of this product. When the user clicks save, the product details are passed up in an event to the controller which delegates work to a SAVE command. This command saves the data to a database, and receives the updated dataset back from the server. This dataset is then used to write over the MODEL, putting it into State B.
Now, my idea is, prior to saving the data to the database, have the SAVE command retrieve the data from the flex model (which would be in STATE A) and store it in a private property of the command, undoData.
So, if after committing the data to the database the user wishes to undo their previous save action, it fires off an UNDO command as you suggested, and its job is to pop the last executed undoable command off the UNDOABLECOMMAND stack and execute it's undo method. The undo method simply writes STATE A back to the database, and then updates the model.
How does that sound?
kahuja
04-11-2008, 09:36 AM
One word... (pick)
Flawed - if you have Client server architecture
Good - if you have standalone.
There would be a long reply that is coming to my head, I do not have the time now to put that down. I will do that later some time. Meanwhile, you can let me know what are you using?
mcampster
04-11-2008, 11:42 AM
One word... (pick)
Flawed - if you have Client server architecture
Good - if you have standalone.
There would be a long reply that is coming to my head, I do not have the time now to put that down. I will do that later some time. Meanwhile, you can let me know what are you using?
Client Server - any clues as to why its flawed, or shall I sit tight for a while and surf the web ;-)
kahuja
04-11-2008, 12:07 PM
Quick reply (I am still stuck with client meetings)... when many people access the application, there can be a reason that between the time User 1 makes a commit and undo, a User 2 can make 10 commit, or 10 users can make several commits. The Undo that is actually irrelevant.
kahuja
04-11-2008, 04:53 PM
reply coming in 20, 19, 18, 17, 16, 15... (hours)
|
vBulletin® v3.8.4, Copyright ©2000-2009, Jelsoft Enterprises Ltd.