8

How does one prevent users from creating erroneous input sets, when there is no practical way to vet the input?

The scene

I modify a small ERP package written in Visual FoxPro. One part of the package concerns itself with printing truck manifests and invoices to be sent with the drivers on their delivery routes. The print routine, when fed nothing as an input, will attempt to print everything, resulting in reams and reams of printer paper being wasted on a high-speed printer.

I am not in a position to re-write any of the GUI interface elements, nor can I adapt any frameworks, tool kits, or other outside code to be used in this situation. The reasons are related to office politics, please do not suggest that I can override the existing ERP framework, as it is not an option for me.

The issue

The users are in a high-pressure, time-critical environment. Each process is measured in minutes or even seconds, which means that I have to minimize processing time as much as possible. Because of this environment, and possible distractions, users frequently ignore the dialogs, pressing the [Enter] key which causes the focus to rapidly move through the form and eventually landing on the action button for the input dialog, resulting in them triggering an automatic printout.

The input consists of a date range, route range, and sales order range.

The input for date range cannot be auto-set to "today's date", as frequent back-printing is required. Also, the end-users work during midnight, i.e. date rollover makes this impractical without rigging a routine that auto-detects the change, etc.

The input for routes cannot be hard-coded, nor can it be deduced from routes that have already been shipped, because re-prints are required (see above).

The input for sales orders only has meaning when printing single orders or specific ranges.

So, frankly, there is no practical way to validate input.

The action button that triggers printing cannot be blocked. Any suggestions that a blocking dialog be placed in front of the user will be ignored. I am not at liberty to discuss why this is not an option, other than the concept has been already discussed elsewhere on the site (from a different vantage point) and was rejected.

Blocking printouts when all inputs are empty was rejected as a design decision as the software must accommodate this as a feature.

The users

The users have been repeatedly asked not to do this. They frequently ignore this advice. Triggering this unfortunate event is not something that their foremen/managers will address, so there is no pressure to end the behavior.

The organization

I do not have a say in the workflow involved, only the modification of existing software components affected by that workflow.

The vendor

The vendor second-sources the package as a custom installation from the original software vendor. The vendor requires that all code changes be sent back to them for integration into their codebase. Significant changes to architecture will result in increased future costs during version migrations due to the extensive customization involved; in some cases, the programmers have even told me that they will completely ignore such large changes and will do as they please.

The software

I have no say in the selection or installation of the software, so changing the platform is out of the question.

Regarding the environment of the software, each invoice printed is a single call. There isn't a batch printing facility, and because of how the print facility is integrated into the system (and some language quirks as well) it isn't feasible to make a batch wrapper around that API. Topping this off, this part of the program calls another program that does the invoice print, which in turn calls the print-a-report API, which prints a single invoice. Horrid design, I know.

Input forms are a weird combination of a form header that is devoid of input boxes, but can contain other GUI elements. Input boxes are defined at runtime.

The objective

The software will prevent the users from erroneously printing all paperwork.

How would you solve this issue?

Avery Payne
  • 183
  • 6
  • 5
    Seems to me that you need to thoroughly analyze the *usability* of your software first. Sounds like a nightmare to use. – Bernard Jan 06 '12 at 19:16
  • 3
    This is a very aggressively worded question. Could I suggest that you try to tone it down a little. Listing all of the things you *can't do* in one block at the end would certainly help with this. Also, if you could explain a little more about the architecture of the system, such as how your code is called and what calls your code makes, then we might stand some chance of making some useful suggestions. – Mark Booth Jan 06 '12 at 19:17
  • @Bernard, while that's a great suggestion, it's not something I'm in a position to do. My employment is to modify existing code and write new code when needed for this package. My employer decides on the package, not me. – Avery Payne Jan 06 '12 at 19:19
  • 6
    so if i understand this right printing everything needs to be a feature, then why can't print all be its own button and the existing print button be blocked until at least one field has data? – Ryathal Jan 06 '12 at 19:21
  • @MarkBooth, I find your comment actually highly ironic, given that all I have seen at this site in the last 30 minutes is hostility. That being said; I will attempt to provide some additional details. Because of liability issues, I can't get too specific about the package, the vendor that second-sourced the package, or other such specifics. I'll try to "tone it down" a bit, as well. – Avery Payne Jan 06 '12 at 19:22
  • @Ryathal, the problem will still remain - while you will have a subset of data that matches input criteria, you will still have an enormous subset, and still print reams of paper... Still, write up your comment as an answer, as this is the first constructive idea I've seen so far. – Avery Payne Jan 06 '12 at 19:23
  • 8
    Haven't heard of FoxPro in a while, sounds like you guys are stuck in the mid 90's. On an aside note you sounds horribly stressed out and your situation seems pretty hopeless. They threw you into rapids but bound your hands and feet with rope, how are you supposed to solve a problem if you are focused on not drowning? – maple_shaft Jan 06 '12 at 19:26
  • 4
    I would change the Output everything param to something specific like PRINTALL. Make the empty param to output the most common selection (probably current record) – SoylentGray Jan 06 '12 at 19:30
  • @maple_shaft, would you believe that I only spend 80% of my time coding? ;) I'm also a network administrator, and have on-call rotation. If this sounds "horrible" to you, then what other programmers go through must be paradise from my vantage point. This is just day-to-day for me, has been for over 10 years now. – Avery Payne Jan 06 '12 at 19:35
  • @Chad, that's a 2nd great suggestion. But that's also the 2nd suggestion that should have been an answer. I don't bite, don't worry about downvotes. – Avery Payne Jan 06 '12 at 19:37
  • 2
    @AveryPayne I am on call 24/7 for software I write and support and I feel like its paradise compared to you because I would hate to be thrown into the gladiator pit without a weapon. Your organization is too conservative and afraid of change, you are paying the price. Given the choice people will choose a familiar hell over an unfamiliar heaven. If I couldn't sell them on usable application then I would have left that company because *there would be NOTHING I could really do to help them.* Good luck to you. – maple_shaft Jan 06 '12 at 19:45
  • 1
    @AveryPayne: I know this isn't about the question, but what you described is no way to live. You should have been looking for a new job 8 years ago. – unholysampler Jan 06 '12 at 19:50
  • @unholysampler, This *was* the new job, over 12 years ago. The prior job involved an ex-alcoholic business owner with bad anger management issues, and I ran the whole show. – Avery Payne Jan 06 '12 at 19:53
  • 5
    @AveryPayne: Just because the new job is better than the old job doesn't mean the new job doesn't suck. – unholysampler Jan 06 '12 at 19:59
  • 1
    @unholysampler Ha! You made me laugh! :) (yes, I'm being truthful, I have a smile on my face) I'll return the favor, 'here are my internetz, let me show you them' http://serverfault.com/questions/29665/morning-rituals/31391#31391 – Avery Payne Jan 06 '12 at 20:05
  • 1
    @AveryPayne I read your post on serverfault and it made me literally want to cry. My heart goes out to you. Please try to escape from Portland, it really is a land that God forgot. You could live like a human being anywhere else in the country. – maple_shaft Jan 06 '12 at 20:45
  • 2
    Stop filling the printer for them. – JeffO Jan 06 '12 at 21:31
  • 1
    @maple_shaft still a lot of FoxPro out there, since like COBOL it tends to continue doing what it was supposed to just fine. – Alan B May 15 '12 at 08:41
  • A follow-up a year later: the reason why you can't have a blocking dialog? Because I had *already* suggested it, aka The Dialog of Evil(tm), which was intentionally designed to prevent the user from progressing without reading the warning on the screen. Even though the original question was in jest, it was universally reviled. Because it was based on a real-life event, I wondered what people would say if I changed the approach, so I made this question, the genesis of which was *to replace the same dialog that people hated*. Watching the responses and comparing results has been educational. – Avery Payne Jan 26 '14 at 04:31

7 Answers7

27

It sounds to me like you've got a requirement to fix something, but every time you propose a solution (and there are plenty of good ideas in your list) it gets shot down.

This is the point where you need to push back. You don't need a vague idea that "this is wrong; fix it." What you need is a spec. Ask the people who want it fixed exactly what they do want done, since so far all you have is what they don't want. That much is easy: just do nothing, and then you won't do any of the things they don't want. Tell them that if they want changes made, they need to come up with positive, concrete rules and you will implement them.

Mason Wheeler
  • 82,151
  • 24
  • 234
  • 309
  • Very original thinking "outside of the box" (ick, did I just say that old phrase?), so +1 for you. :) – Avery Payne Jan 06 '12 at 19:59
  • 3
    Sadly, when 'office politics' are the reason for braindead constraints, sane requirements are generally thin on the ground. The elimination by force or fiat of 'office politics' as a thing that exists would universally improve the quality of production code by several orders of magnitude. – Jason Lewis Jan 07 '12 at 04:31
25

This is easy, if they leave everything blank you prompt that this will print everything, however, the DEFAULT selection in that prompt MUST be to cancel.

If they enter values, print whatever they asked for.

This way, they won't accidentally blaze through the form and print everything. They'll blaze through and print nothing. They would need to pause, and print change the selection at the prompt to OK, from Cancel, to print everything.

CaffGeek
  • 8,033
  • 5
  • 32
  • 38
  • 2
    This won't work - as soon as the users realize that they have to use their mouse to click the button (or hit tab before they hit enter), they will start doing that automatically, without thinking about it at all. – TehShrike Jan 06 '12 at 20:40
  • 7
    @TehShrike, no, it will, because the prompt only appears when printing EVERYTHING. So it's going to break their normal flow, causing them to either hit enter again because they expect a different prompt (and cancel the print) or stop to read the prompt and pick the correct choice. – CaffGeek Jan 06 '12 at 21:21
  • This solves the requirement to eliminate the "need a Dialog of Evil(tm)" issue, while accomplishing the original goal - to break their "concentration" (or lack thereof). It will stop them in their tracks, and make them wake up for a second instead of slamming the [Enter] key. In all other conditions, they can go about work as normal without interrupting their work flow. Great response. – Avery Payne Jan 12 '12 at 18:29
  • @AveryPayne, glad it helps. – CaffGeek Jan 12 '12 at 18:42
10

I'll try to give an answer for a more generic question: how to avoid a user making a mistake which leads to disaster or something which cannot be canceled or undone (like wasting paper by printing several pages the user didn't expect to be printed).

As said in the original question:

The users are in a high-pressure, time-critical environment. Each process is measured in minutes or even seconds, which means that I have to minimize processing time as much as possible.

This means that:

  • The software product must make its best to increase the productivity of the employees. When every second counts, user experience and productivity is even more important than for general products, where a loss of a few seconds on some feature the person don't even use too often is acceptable.

  • The users are too busy to pay attention to the software product. When, in a calm environment, I use some feature of Microsoft Word I used the last time a year ago, if Microsoft Word asks me a question, explaining what would be the consequences of my choice, I can afford spending a minute or two reading the question, and maybe even going to read the documentation. In your case, you can't afford that. Your users don't have time to read.

Message boxes: no, no and... no!

As already explained in my other answer, message boxes are evil in most cases, for two reasons (see About Face 3 by Alan Cooper for more details):

  • The dialog that cried “Wolf!” principle incite the user to dismiss repeatedly a dialog without paying attention if the application shows the same dialog too often.

  • The dialog disturbs the workflow: the user can't stay focused on the application, because the dialog grabs this focus away and the interaction with the application is suspended until the dialog is dismissed¹.

This means that dialog boxes are an absolute evil in your case from the UX point of view: they will be dismissed and they will decrease productivity in an environment where every second counts.

Other means

According to the question:

  • "The input consists of a date range, route range, and sales order range."

  • There are no wrong values (for example the user can enter a previous date, a future date or today in the first field), so validation is not possible.

  • "The print routine, when fed nothing as an input, will attempt to print everything, resulting in reams and reams of printer paper being wasted on a high-speed printer."

  • It's totally possible to ask to print with default data used.

In more generic terms, it means that:

  • You have a default value, which can actually be valid,

  • You don't want the users to hit "Print" button with default values kept by mistake, while they intended to change them.

Here's a few techniques you can try:

1. The magic undo

Yes, the users are in a time-critical environment. Yes, once the printer starts printing, it cannot be stopped. But there is still something you can do.

Even in a time-critical environment, chances are that printing right now and printing in five seconds will not change anything.

When the user clicks "Print", display a small "Undo" button, just like GMail does when you ask to remove, by mistake, all your mail. Wait for five seconds². Hide the "Undo" and only after that, print.

Now, the user has a chance to notice the mistake and cancel it before the harm is actually done, while the stuff is printed only with a small five seconds delay.

2. The discrete "default value" background

Is having default values suspicious?³ With one value, it's rarely suspicious. With three, there are chances that the cases when the user has to keep all three values by default are quite rare.

In this case, you can:

  • Highlight the value when it has its default value. Not in red: red is for invalid values. Set it to yellow-orange, and back to white when the user alters the default value.

  • Or disable the "Print" button until a value is changed. Add a checkbox nearby, which the user can check to confirm that his intent is to print with default values.

3. Enhance the UI of your controls

We are Friday, 6th of January 2012 today. What will be the date the next Thursday? Quick, quick, you're under pressure, you have only one second for your answer. Also, you're tired and there is a lot of noise all around. Not easy to answer, isn't it?

People can't manipulate dates easily when it's written as 1/8/1012. Saturday, 7th of January (tomorrow) is a bit easier. A graphical view which highlights Saturday and Sunday, shows today and the offset is even better.

Nothing is as ugly as "Location: NYC". Those three letters are meaningless when you're tired and work in a stressful environment; mistakes are easy. Instead, a graphical map of United States showing a red dot for New York city is much more appealing, and the user has much more chances to notice that, while he wanted to select San Francisco, the red dot seems to appear in a wrong place.

enter image description here

Would you enjoy if your GPS told you that you have to move from 38.90403, -77.04878 to 38.90568, -77.04665, then turn right and move to 38.90565, -77.04345, then turn 90° left and move to 38.90660, -77.04345? Would you be able to concentrate on your work (the road)? Showing 1/8/2012 and NYC to busy users is as friendly as a GPS that throws raw coordinates instead of a 3D view of a map full of color.

By providing richer controls and richer visualization of data, you can decrease the level of mistakes of your users in a stressful environment.


¹ This, by the way, applies to other variants of dialog boxes. You previously asked a question about the dialog boxes where the buttons will be random and which will make it difficult to dismiss. Sadly, such approach will not help, but only hurt: the users will still dismiss what is said by the dialog, but waste more time trying to close it to return back to work.

² I say five seconds as an example. You have to monitor the activity of the users for a few months to see how fast they click on "Undo". Chances are it will be below one second. If you see that the delay is from 0.6 to 1.8 s. with an average of 1.1 s., you can show the "Undo" for two seconds, and then print.

³ Please, please, please, say no! Because if it is, it means that there is something wrong with your default values. For example if the default value for the date is today, while in 75% of cases, the users have to set it to tomorrow, in 10% to yesterday, and in 10% to the day after tomorrow, you should rather set the default value to tomorrow.

Arseni Mourzenko
  • 134,780
  • 31
  • 343
  • 513
  • Option 1 is the best of the three. Option 2 may or may not be possible due to poor API design for the interface. Option 3 is definitely broken due to poor API design (text boxes and buttons are the only things available). Still, thank you for *constructive* commentary. :) – Avery Payne Jan 06 '12 at 21:29
  • 1
    You can manage the second option by adding some labels and turning their visibility on and off (you still have labels, do you?). For the third option, forget about it until your boss/customer understands that he expecting good quality software with good quality UI built on a crappy framework with just textboxes and buttons is like expecting a Lamborghini to be built from wood and some rusty old pieces of metal. – Arseni Mourzenko Jan 06 '12 at 23:03
  • Magic Undo is definitely a beautiful thing. – Nick Chammas Jan 07 '12 at 00:11
  • @MainMa, just as a side note, the API is rather primitive for what you're attempting to accomplish in #2. A dialog with four buttons is a single function call that draws the dialog, spews some text from a string, and auto-populates buttons with words. There are, you guessed it right, 7 parameters - "message", button count, default button focus, button string1, button string2, button string3, button string4. There isn't a "layout" or "object re-class" that can be applied. But thanks for the suggestion, and it certainly is within my power to write my own dialog and call it instead... – Avery Payne Feb 21 '12 at 23:08
3

How would you solve this issue?

Clearly separate the use cases. There's a "print something right now" case that can lead to endless output. Fix this to provide all the right defaults.

There's a "reprint some previous thing" case that is a special (non-standard) request where inputs can be checked carefully.

The input for date range cannot be auto-set to "today's date", as frequent back-printing is required.

False.

The input can be auto-set today with no effect at all on frequent back-printing requests.

What possible impact would a auto-set to "today's date" have on back-printing requests? Please enumerate them in the question.

The input for routes cannot be hard-coded, nor can it be deduced from routes that have already been shipped, because re-prints are required (see above).

False.

Reprints and back-prints are a special case. They never have default fields and are the exception, not the rule.

S.Lott
  • 45,264
  • 6
  • 90
  • 154
  • This concept was originally discussed about in my department, and dismissed because (a) the user will now blaze through the input with the *wrong date*, and (b) auto-setting the date for just the same day will still result in all of the paperwork being printed, when it was not desired. – Avery Payne Jan 06 '12 at 19:14
  • 1
    "blaze through the input with the wrong date"? Which input? There are two separate use cases: Default date and back date. Please clarify. – S.Lott Jan 06 '12 at 19:18
  • 2
    @S.Lott This is more of a comment then an answer. – Josh K Jan 06 '12 at 19:24
  • There is no default date. By default, the input field is blank. – Avery Payne Jan 06 '12 at 19:24
  • @S.Lott `What possible impact would a default date have on back-printing requests? Please enumerate them in the question.` Isn't asking for clarification better done via a comment on the question? – PersonalNexus Jan 06 '12 at 19:24
  • 3
    @PersonalNexus: Possibly. The question is quite hard to deal with because it's full of assumptions. – S.Lott Jan 06 '12 at 19:25
  • @AveryPayne: "There is no default date". "The input for date range ... auto-set to "today's date"". This gets confusing. You suggested a default date as a possible solution to your problem. Now you're saying that it cannot be done? – S.Lott Jan 06 '12 at 19:28
  • 2
    @AveryPayne - So why not just disable the ability to print with no parameters? – SoylentGray Jan 06 '12 at 19:34
  • @S.Lott Totally agree. All the more reason, I think, to ask for clarification before one can provide an answer. – PersonalNexus Jan 06 '12 at 19:36
  • @S.Lott you're confusing me - I don't mention the word "default" in the posting. Here, from the post: "The input for date range cannot be auto-set to "today's date", as frequent back-printing is required. Also, the end-users work during midnight, i.e. date rollover makes this impractical without rigging a routine that auto-detects the change, etc." – Avery Payne Jan 06 '12 at 19:39
  • 1
    Please take extended discussions to [chat](http://chat.stackexchange.com/rooms/21/programmers). – Josh K Jan 06 '12 at 19:53
  • So "auto-set" is not "default". I would have thought these were synonyms. Since you don't like the word default, I updated the answer to use the words you appear to like. – S.Lott Jan 06 '12 at 19:55
3

Can you determine before printing how many pages will be printed, or in some other way measure the size of the output? If so, determine a maximum size for normal use, and if it is bigger, use a confirm dialog that states the output size and, so it cannot be dismissed without reading, requires the user to type back the output size to confirm.

JGWeissman
  • 1,061
  • 8
  • 12
  • While it is possible to attempt to compute the number of pages, it is time-prohibitive, and therefore, the design decision was rejected because of the time constraints mentioned above. Still, if time wasn't a factor, this would be a large help. The secondary blocking dialog however runs contrary to my posting above (see the 2nd to last paragraph in "The Issue:". – Avery Payne Jan 06 '12 at 19:27
  • @AveryPayne Can you cancel printing once it is started? You could instead have a non blocking screen indicating the number of pages (computed in parallel with getting the printing started) with an option to cancel if it wasn't what the user meant to do, so you only waste a few pages while the user realizes the mistake. – JGWeissman Jan 06 '12 at 19:40
  • +1, simply because so far, this is the only practical answer that has been given. However, I still can't accept the blocking dialog part of it. – Avery Payne Jan 06 '12 at 19:41
  • I wish I could, but the hook for printing is "brain-damaged" at best - it flashes a dialog for each printout. I will try to clarify this in the question, thanks for pointing this out. – Avery Payne Jan 06 '12 at 19:42
2

You have a situation where the current process default is creating waste and costing time for your users.

Disable the ability to just hit enter all the way though by having the focus on the "reset parameters" button(create one if needed) so if they hit enter it stays on that screen, but does nothing. I would create some sort of hot buttons for the most common selections to auto fill the form with those parameters to help the users out. But this should solve your problem even with out the hot buttons.

SoylentGray
  • 3,043
  • 1
  • 23
  • 31
  • The input fields are "dynamically" added at runtime (there is no design-time layout)...but the buttons are coded into the form, so adding new buttons is a great suggestion. – Avery Payne Jan 06 '12 at 20:12
  • The dynamically added does complicate things but I think you can still populate them even in foxpro if there is value in figuring it out. – SoylentGray Jan 06 '12 at 20:46
2

Allow me to restate the problem.

Present state: blindly pressing Enter causes reams of paper to be printed.

Desired state: blindly pressing Enter does not cause reams of paper to be printed.

Solution: change the software so that blindly pressing Enter does something, anything, other than causing reams of paper to be printed.

That pretty much leaves you with the problem of what it should do instead. Personally, I would ask the operators what they want. My guess is something like printing the most urgent invoices that haven't already been printed. Leave the ability to print all, but require a conscious decision to do so.

Karl Bielefeldt
  • 146,727
  • 38
  • 279
  • 479