views:

56

answers:

2

I have an application that performs various tasks that can take up to a minute each. I wanted to make sure that I was setting the application to a "working status" in a consistent way, so I set up a class (we'll call it "LockI") that when initialized records the current state of various things (the cursor, the status bar, screen updating and so on). Then when it's restrict method is called, it sets everything to a working status. In the class destructor all of the original settings are restored, so I don't have to worry about an error (or someone forgetting to call the restore method) leaving the application all locked up. Also because it restore the application to the state it was found in, if a second call to the class is made, I don't have to worry about it accidentally unlocking the application when the class deeper in the stack is destroyed.

So now to my question, assuming that what I have described above isn't already a mistake, should the application be locked inside the various procedures, or lock the application in the event handlers (like a button click handler) and then call the procedure? (Or some other option.)

Clarification: To be more concise... Taking into account the following:

  1. For longer actions, you will need an instance of the Lock class available in order to update the progress bar.
  2. You might be calling more than one procedure (unless you funnel them through a top-level procedure).
  3. You won't be displaying a status bar for all procedures (as sometimes it's just not needed and actually slows things down).

Is it better to instantiate the class in the click handler and then pass it to the called procedure(s) as needed or to instantiate the class in the called procedure and if you need to call multiple procedures set up a "funnel"?

A: 

I think your life would be much easier (and the user's life less frustrating) if, instead, you brought up a modal dialog box with a progress bar, a status message, and a cancel button.

Jonathan Feinberg
It's done automagically by the class:) You can set a few properties to change the messages etc. and you can increment the progess bar. The idea being to keep it consistent. But I still consider the display of a prograss bar etc all part of going into a "working status" so the question is, should you throw it into "working" in the click handler or in the procedure (keeping in mind if your procedure is going to update the status you have to make an instance of the object available to the called procedure).
Aaron Bush
+1  A: 

There are varios user interaction patterns that you can use, depending on the application domain, working style and preferences of your users. In my experience, some people prefer to be free to enter data anywhere on screen without any validation or check mechanism locking them, and having these occur only when they finally hit "Enter" or "Save". In this model, status messages signalling potential issues with just entered information are helpful (e.g. "End date cannot be after start date."), but they must be only informational and never modal. This approach allows for a very fluid interaction and long "dialogue times" with the machine.

Alternatively, you can use a "act & lock" approach like the one you describe, where the system prevents all further interaction after each action that the user carries out. This is useful if there is a clear sequence of actions to be performed (not like filling in a form, where you can start anywhere), if they take a relative long time (longer than typing a few characters in a textbox!), and if the dependencies between one action and the next are crucial (i.e. one action cannot be performed if the previous one has not been validated). In this case, the "act & lock" pattern is advisable. It is robust and potentially decreases mistake rates if well implemented. In modern GUIs where multi-thread support is easy to afford, you can just lock the window where the actions are being carried out; alternatively, you can lock the entire application. It is not as elegant but usually easier to develop. In any case, an information message is necessary, and a progress bar of some kind is highly advisable.

Edit. On imlpementation issues, I would create a ModalInteractor class in my presentation (GUI) layer and instantiate an object of this class whenever I want to begin a new modal interaction with the user. This class has the following resposibility areas: (a) locking and unlocking the relevant user interface elements, (b) signalling progress and (c) cancellation management. You can easily work out what properties methods you'll need for each of these areas. Semantically, ModalInteractor is part of the logic that manages or drives your GUI (a "controller", some would say). Whenever the user clicks on the button that initiates the lengthy process, create a new ModalInteractor object and pass a reference to the current window in the constructor. Configure the object with a few delegates so that it knows what method to invoke to begin the lengthy process, what methods in the window to call for progress notification, and what event to respond to when the user clicks Cancel.

Hope this helps.

CesarGon
+2 For a good discussion of the issues. -1 for not answering where the application/window should actually be locked (in the click handler or in the procedure) ;)
Aaron Bush
Thanks! I have added some implementation details that I hope you find useful. I have used this approach a few times and it worked nicely.
CesarGon
Crystal clear thanks:)
Aaron Bush