Never use a warning when you mean undo (2007)
alistapart.com
alistapart.com
All that said, for mature features, it does seem like a reasonable thing to require. Unless there are huge fundamentals standing in the way. (Like undoing forget-me requests days later.)
Sure there are things you can not undo, sometimes you do want to permanently delete something, but maybe with a bit of thinking a undo is feasible more often then one might think :-)
A delay which can be annoying in its own way. It’s rarely an issue to be fair but it means you may not be informed of errors if you leave the mail client too soon. Also there are (admittedly very rare) cases where you want the mail to be sent immediately but it is sent at an unpredictable time : those undo features rarely display a countdown.
At $work we had to implement a feature to delete a custom form object that was linked to maybe hundreds if not thousands of submissions to this form with cascade deletion. The thing is, submissions required something from dozens of minutes to multiple hours. The form was also pretty complex to build and could represent hours of work.
Still, we had to provide full (real) deletion of everything for legal reasons (and it’s hard to implement undo on this).
V1 was a classic "are you sure?"
It was a disaster for our support department and we had to recover data from our production backups way too many times.
V2 we added multiple confirmation boxes with something like "I understand I’m deleting x submissions", "I understand deletion is permanent and can’t be undone", "I understand $WORK support will not be able to help me recover ".
We still got way too much calls of people panicking about what they’ve done.
V3 was the same thing but we added some text to write (à la GitHub).
A little more effective but still not that effective.
The harsh reality is that people / brains just don’t read anything, they just click where they think they have to click.
Also this overkill confirm box would have been enough in a B2C context, but in B2B, you just can’t ignore people because they are stupid because they also pay you big money so they do expect you will solve their fuckups.
IIRC the next step was to implement a hidden undone mechanism like a fake deletion then a cron job does the real thing hours or days matter but it’s a rather expensive and complex thing to implement just to avoid some pretty rare overall (but massive) human errors. But I’m not there anymore.
> The harsh reality is that people / brains just don’t read anything, they just click where they think they have to click.
Absolutely 100% true. The GitHub "danger section" / "type this long, possibly randomly generated, string of text to confirm you want to nuke everything forever" UI was a major step forward but at least for B2B dev stuff we're started to get used to that. I wonder what the next thing will be.
> in B2B, you just can’t ignore people because they are stupid because they also pay you big money so they do expect you will solve their fuckups
You can't ignore them but as long as you have executive backing you absolutely can (and should) say "there were three confirmation screens the data would be lost. The data is lost unless you want to pay Professional Services their hourly rate to go trudge through backups for a day to find it." If you don't have this backing leadership doesn't really care about the tech people and that's a separate issue.
> IIRC the next step was to implement a hidden undone mechanism like a fake deletion then a cron job does the real thing hours or days matter but it’s a rather expensive and complex thing to implement just to avoid some pretty rare overall (but massive) human errors. But I’m not there anymore.
This was my first thought, "delete" goes into a queue that gets processed later which gives people time to go "oh shit" and realize they messed up. We had something similar in a large healthcare company I worked at so probably similar legal requirements around storage of things and actually deleting them for real. We would put items into a queue for deletion, and the consumer of that queue was executed on a once-monthly schedule, but would only delete items that had been in that queue for 6 months already. This let any processing around quarter end or that sort of thing figure out something was wrong and gave it additional months to work its way to "find this piece of data and undelete it."
Pain in the ass to manage and would have been completely overkill if we weren't already using queues for basically everything.
I'm not going into further details, but those forms were there to accomplish some legal duty and each submission contained a lot of very personal information. The reason to delete those forms would always be that they were either created by error or that eventually they wouldn't be useful anymore.
But you are right that it could have been two features : one to delete all submissions then one to delete the form. That was one of my suggestions but it didn't pass some leadership / design validation.
> You can't ignore them but as long as you have executive backing you absolutely can
There are some reasons I'm not working there anymore :) It was a good company on many aspects but not this one.
Conceptually, database backup/restore is effectively mark-for-deletion, but with a more difficult path to restoration, especially for one complex object.
If your database or framework/ORM supports it, my favorite solution is to use virtual tables that hide deleted data, so every the code is kept clean and developers don't accidentally query dead data.
I'd love to see an ORM with full undo/redo support. Examples: https://github.com/zchtodd/Flask-UndoRedo https://github.com/etianen/django-reversion
I've done this before.[1] How did it work out to be expensive and complex to implement for your use-case? Did the "just deleted" elements have to be removed from any results-set as well?[2]
[1] Gather the data into a structure and throw that structure into a queue/bin/table with `now() + 5 days` as the expiry time.
[2] I've done this too, but not with a soft-delete column (which is a nightmare), but in a more complex way by writing the records to be deleted into a log, and then actually deleting them. This lets the user `undo` by showing them their entries in the log and asking which of those entries need to be restored.
Your task/job/goroutine/thread/script runs once every minute, retrieves all the structures/command/forms with `expiry > now()` and removes them.
KDE Plasma embraces this principle with widget deletion, and I believe the KDE UI guidelines pushes this kind of stuff.
I have to say, it's a joy. No additional pointless step / confirmation when I delete stuff and really mean it, which is most of the time, a way back the odd time when I did indeed delete something wrong.
Relatedly, trash bins and file removals without confirmation work very well for the same reason. Let the users empty the trash when they are done, or let a timeout after which deleted item are really deleted from the trash. Less work for everyone, but one more free safety net for the users.
Although strictly speaking, you don't always need one, just a list of stuff the user can restore, in any order. That's because you don't always have dependencies between stuff, and/or you don't always need to be able to redo.
Or even one cell to be able restore the last deletion, that's already a step in the right direction and strictly better than the confirm dialog.
By the way, Plasma might be doing it this way (the list or the cell), you can't arbitrarily undo and redo stuff to my knowledge.
This is a really good principle, not easy to implement but good to keep in mind.
Never use a warning when you mean undo (2007) - https://news.ycombinator.com/item?id=33721930 - Nov 2022 (85 comments)
Never Use a Warning When you Mean Undo - https://news.ycombinator.com/item?id=2150361 - Jan 2011 (83 comments)
Never Use a Warning When You Mean Undo - https://news.ycombinator.com/item?id=34746 - July 2007 (10 comments)
I really wish browsers would do the same with closing browser tabs.
Edit: To clarify, I mean that I wish browsers would actually keep the tab process running for a short while so that the entire state can be restored. I’m aware of “reopen tab”, but that doesn’t help you in most cases if you have a paragraph typed into a web app and accidentally close it.
They do, though. Ctrl-Shift-T does it for me (FF).
A simple example of this would be a trash-bin area, which indirectly summarizes recent deletion activity. However that doesn't extend to stuff like "I accidentally moved fifty items to the wrong place, where did they end up and which ones weren they?"
But even assuming that you are able to follow this advice, I assume (and have personally witnessed) another side-effect. Just as people get accustomed to, and ignore, warnings, they will just as well become accustomed to being able to undo mistakes, and as a consequence become less careful about what they're doing.
One may argue that reserving warnings for only the non-undoable operations will improve their signal-to-noise-ratio and compensate for an overall gain, but whether that is true and worth the additional complexity is not black-and-white.
For the removal of files/dirs, I alias `rm` to `mv -t ~/.trash` in my .bashrc/.zshrc file.
Running `rm foo.txt` then only moves foo.txt into the trash instead of removing it completely.
This can the extended to incorporate a simple automated timed trash empty process.
It just illustrates how one person's indispensable feature is another person's annoyance. These things should exist, but should always be able to be disabled.
What good is an undo if I don’t realize I did something bad? The confirmation dialog serves the purpose of letting me know what the phone thinks I asked it to do.
By all means also allow me to undo though. Undo is super important, just that doesn’t mean we should remove all confirmation dialogs.