18 ms·
Undo
- tadfisher 13y agoYou use Gmail's undo feature as an example, but it doesn't work in the way you prescribe. It's the cheap & easy version of undo that doesn't require building your application around the command pattern: just implement a reasonable delay before making the irreversible change, and show the Undo action during this delay (which is really a "cancel the pending change" action). No, it's not as clean or as good of an experience for your users, but it works great for applications such as email that perform fundamentally irreversible actions.
- sgdesign 13y agoYeah, it's kind of a simulated undo. I'll update the post to point it out better. But anyway, the end result is (almost) the same for the user, which is what counts at the end of the day.
- reneky 13y agoThere are actual undo in Gmail as well, for example when applying a label to a message. Since send is making the change in an external system it has to be simulated, but that doesn't change the point of the post.
- raimondious 13y agoI felt like I was having déja vu reading this article. Happy to have found why, Aza Raskin in 2007: http://alistapart.com/article/neveruseawarning http://alistapart.com/article/neveruseawarning
- trevordixon 13y agoI just tried sending a message in Gmail, and it didn't give me an option to undo. Is it a feature I have to enable?
- sgdesign 13y agoYou're right, it's actually a "labs" feature: https://support.google.com/mail/answer/1284885?hl=en https://support.google.com/mail/answer/1284885?hl=en
- vcherubini 13y agoI would wager that the reason Undo isn't implemented more often is that it is very difficult. Executing a DELETE statement and deleting a bunch of data is simple. Implementing "undo" is more difficult, especially for browser based software. How long is the undo valid for? Can you undo every action? How many levels of undo do you support? Do you allow an undo for UPDATE's as well (updating a blog post to set it's content is essentially deleting it, and would probably be something you want undone, for example). On top of just building the functionality in to your app, communicating it to your users is also difficult since the web app medium is so different than the desktop one.
- smooj 13y agoInstead of actually deleting a record when a user hits 'delete' just flip a boolean that indicates it is 'deleted'. Then undoing a delete action is as easy as flipping the boolean back. For more complex application state you can keep a stack of state or actions (depending on the application and code) and then push onto the stack as the user performs actions (killing off actions older than a certain point). When the user hits undo pop from the history stack and push onto a second 'future' stack to support redo. I agree with the author that it would be nice if more web apps implemented undo/redo. I Iecently implemented it in an interior design app I was working on and it's really not that hard to do.
- jd007 13y agoThat may or may not be legal. IANAL but telling a user that his/her data has been deleted when in fact it still sits on the server could be regulation violating or downright illegal depending on where you are. Of course it would probably also depend on what your product ToS says and the nature of the data being deleted.
- sgdesign 13y agoIsn't that exactly what Facebook and every other social network does though?
- coolsunglasses 13y agoEasier to implement this if your data is backed by Datomic. I'm working in a HIPAA environment and we're quite happily using Datomic there.
- praptak 13y agoThat's interesting. Do you have any "really delete this data" requirements and if so, is it hard to deal with that with Datomic? (sorry if question is dumb, I have near zero knowledge on both HIPAA and Datomic)
- coolsunglasses 13y agoExcision is built into Datomic expressly for this purpose. I don't know why people assume those capable of building a database would also fail to anticipate this need. The difference is that you don't use excision except in special cases (like legal obligation to delete data), you use retraction which doesn't lose any history.
- alanning 13y agoThank you for sharing your experience. > I don't know why people assume those capable of building a database would also fail to anticipate this need. Praptak asked if it was hard to deal with and did not imply Datomic's developers failed to anticipate the need. Excision is a feature that must be prioritized like any other and in fact was not available until Datomic 0.8.3941. https://groups.google.com/forum/#!topic/datomic/Gk8h6MrnJYs https://groups.google.com/forum/#!topic/datomic/Gk8h6MrnJYs
- coolsunglasses 13y ago3941 was pretty early in Datomic's lifecycle so far. It's still a young product but it's very practical already. Fair point. :)
- tomasien 13y agoI was thinking about how memory must work to allow "Undo" on desktop apps earlier today, and realizing how different that is as it pertains to the web. Undo is amazing, it's a life saver - it's probably literally saved me days of my life when I've accidentally deleted entire projects before.
- jakejake 13y agoMy philosophy is that of all the things that are important for a business or a web service - keeping your data is the very highest priority. Just about anything else can be fixed, but if your data is lost with no backup then no amount of programming or time or sweat is going to get it back. It's a good idea to just keep this in mind when you're working anywhere near a production database. backup, backup, backup.
- vdm 13y agoBackup is manual Undo.
- blt 13y agoImplementing bug free undo is difficult, in my experience. I have a gut feeling that functional programming has a lot to offer here.
- joshmlewis 13y agoFamous last words. :) > doesn’t seem like it would be that hard technically.
- kcorbitt 13y agoImplementing a passable undo with a database-backed system gets a lot easier if you have an append-only record of every transaction. Rails has a great gem that adds this feature with a minimum of fuss (https://github.com/airblade/paper_trail https://github.com/airblade/paper_trail). There's even a Railscast that goes over how to use it to implement "undo" (http://railscasts.com/episodes/255-undo-with-paper-trail http://railscasts.com/episodes/255-undo-with-paper-trail).
- deleted 13y ago[deleted]
- GuiA 13y agoInteresting write up. Thanks a lot for writing it Sacha. Okay, so I have a question. Isn't this just a property of the internet as a system? If we remember the history of human-computer interaction on 2D displays, we first really remember what led to the desktop GUI (Xerox Alto, all that stuff). This domain had tons of research poured into it (of which Raskin is a member) - including from the military, for usability in extreme situations - and by now it's reached a pretty mature stage, and we have developed a nice design language to describe it and advanced technological tools to implement that language. On my Finder, or in Pages, I can reliably undo things nicely. Just today, I deleted a file by mistake- command + z, boom, undone. (by the way, this is exactly what Apple and mobile devs talks about when they say that well done native apps can never be beat by web apps- those decades of best practice experimental research) Web apps, on the other hand, run on the internet, which adds some constraints structure wise. All of a sudden, we have at least 2 computers talking to one another, and in most cases many, many more than that. So we have to come up with design principles to make all of this somewhat work together, and we come up with things like RPC and REST. Those things are how our servers talk now, and they influence every technology that we build. They come with some constraints however- notably the ideal of statelessness, in which implementing "undo" would be really hard. Relational databases don't have the semantics to express "undo the last statement that was a user action done with id N", and good luck implementing things like undo in a system where you have caches you can't invalidate, content determined by one way hash functions, etc. If you have a binary blob of 5 lines, that user 1's action modify the first 3 lines, that user's 2 action modifies the last 3, and that user 1 then decides to undo his command? You'd basically have to version everything, and have super amazing algorithms doing bisects and diffs on your content. The http internet is really just a way to exchange documents. We've hacked it, using fancy stuff like AJAX, to make it behave more like the traditional GUI that we know and love, but at the core it's still a way to transfer documents. And naturally, HTML, the description language we use for web content, has semantics for describing static documents. Heck we've had to design a whole new language for design (CSS), because it's really just a way to describe documents! So ultimately it lacks the way to implement concepts like undo-ing as first class features. Let it be noticed that mobile apps do undo-ing very poorly, as well.
- sgdesign 13y ago
- apeace 13y agoIt's worth noting here, the two instances where the author wished for an "undo" (dropping a data database table and deleting a production server) are very different from what the rest of the article discusses (user-facing apps like Gmail, Photoshop). A database or IaaS application are typically used by administrators, and typically every action is rehearsed in the form of staging testing or automated tests. Furthermore, these types of applications would need significant additions or rearchitecture to account for undo operations. For example a SQL implementation might not be able to reclaim disk space as well if it were unable to really delete the data from a dropped table. Likewise an infrastructure platform would need to keep unused resources busy. In both systems there are important ramifications of the deletion, and providing the ability to undo them doesn't exactly make sense.
- MichaelGG 13y agoIt is true though that some of these cloud services should offer some way to enable an extra level before deleting. Azure, for instance, makes it quite easy to nuke a database or storage pool. I'd really prefer if there was a forced sign-in again for such rare options. IIRC, AWS has a 2FA option for deleting S3 buckets or something. As for databases, always have BEGIN TRAN at the beginning of any commands, with a commented out COMMIT.
- brianberns 13y ago"Undo" only makes good sense in an app where each user works in her own isolated sandbox. This is a common paradigm on the desktop (e.g. word processing), but less common on the web. As soon as Alice's transaction is visible to Bob, making it undo-able gets much more complex.
- uniclaude 13y agoThis is a good point, but as the author points it, it feels so useful in Gmail.
- Legion 13y agoGmail undo is basically job cancellation, not really returning a changed state back to its original state. Gmail can't "undo" once that job has been processed - in other words, when something has been actually done.
- r00fus 13y agoIt's not job cancellation, your view is such that unless you undo, that's reality (you can confirm this by browsing in a separate window, your non-undone actions have taken place). What Google is doing is (at least for deletes on mails) is equivalent to a database transaction rollback. So they have a tiny (likely 1-entry) transaction log that they keep per user, and if the user desires, they can use it to fully reverse any operation that is undoable aka reversible. I suppose it works different for email sends you can undo - in that case it is job cancellation.
- uniclaude 13y agoWe, on HN, all have an idea of the tech behind this, but to the user, it is still perceived as an undo action, and that's what I believe the point of the author was.
- sesqu 13y agoGmail can't, but Exchange and Skype can (and do).
- 13y ago
- crystaln 13y agoUndo is hard, not a core competency for most companies, and most users don't care. In fact, many users don't want deletes to be undoable, they want deletes to be delete. You could probably make a stronger case for improving deletes by overwriting the disk space with garbage and ensuring users that no derivatives were left around. That would be a selling point. Imagine SnapChat with undo...
- brryant 13y agoWe here at Webflow went through great lengths to implement the command pattern in our web designer. It has definitely paid off when we tell our users they can just hit Cmd+Z and Cmd+Shift+Z anytime they make a mistake. That said, it's really difficult for webapps to fully support undo/redo. A lot of the web is transactional, and different actions trigger follow on actions. GMail does a really good job with its undo, but there's a reason it goes away after 10, 15 seconds!
- jayfuerstenberg 13y agoCocoa offers the same undo implementation as described here with "NSUndoManager" where, for each action, you add the opposite action to an undo stack. As a pattern it is proven to work. It just consumes memory and servers might not scale as well as a desktop app in this regard. If the undo/redo stacks don't grow too long and the operations are simple enough in nature it might work though.
- radicalbyte 13y agoThis is funny, as in my career I've seen a number of domains, and built (web) systems which required a form of undo. You just don't see it too often in the PHP/Ruby crowd because it's hard to get right and each implementation has inherent limitations. Luckily there has been work on patterns since the CoF Command/Memento: the Event Sourcing pattern (http://martinfowler.com/eaaDev/EventSourcing.html http://martinfowler.com/eaaDev/EventSourcing.html) can be used to implement system-wide undo functionality.
- coolsunglasses 13y agoI've worked on event sourcing based systems, Datomic is a lot saner.
- laumars 13y agoThis isn't a web thing, it's a technology thing. If you dropped a database via a command line tool or desktop app, you'd still lose everything. It's not phpMyAdmin -nor any other web app- being lazy, it's just how that technology works. And I think the argument that you can't blame the users isn't fair because these are sysadmin tools - so you'd expect the users to know what they're doing.
- voyou 13y ago"That's how technology works" because that's how the specific bits of technology we're talking about have been implemented. We make the technology, and we could make it work differently. There are cases where un-undoable commands are useful, but these cases are only a small fraction of the things we do on computers, sysadmins or not. Sysadmins may "know what they're doing" but they make mistakes like anyone else, and software should, where possible, be designed to reduce the impact of those mistakes.
- laumars 13y agoSoftware is designed to reduce the impact of those mistakes - that's where back ups, file system snapshots and virtualisation / OS containers come in. Some database operations do have an undo command per session; up until a commit is made. But it makes no sense to have an undo for drop database, which is why it auto-commits. Sometimes the "undo" command needs to run a layer or two lower down in the stack than on the application layer. 9/10 times, there is an undo command (assuming the platform is installed correctly) - and as the author noted, he had a backups so that would have been his "undo". So while I'm all for building safety nets and better tools; I also think the OP is being completely unreasonable expecting every sysadmin application to have an inbuilt "undo" command. Sometimes "undo" tools need to be worked into another layer of software lower down the stack - but just because they don't exist in the GUI frontend of choice, it doesn't mean that they don't exist at all. But that's just my opinion as someone who also constantly makes mistakes hehehe
- dcposch 13y ago> it's just how that technology works I think we can fix that! You're right that some things aren't amenable to a literal "Ctrl Z"---but I think Sacha's underlying point is spot on. Many "irrevocable" actions could, with better design, be made made safe. For example, Sacha's second story was where he accidentally deleted a production server instance. With a typical VPS, his configuration might be irrevocably gone, and he has to manually recreate everything under time pressure. But if next time he uses, for example, a Docker host, then such an error will be as simple to fix as deploying the same image again. Another good example is Git. With most version control systems, "rebasing" is either unsupported or discouraged, and if you mess up, you can lose data permanently. Git's design is undo-friendly from the ground up: any commit hash encodes the exact state of your repo, including history all the way back to your first commit. So even if you rebase or force push and make a terrible mistake, you can nearly always use `git reflog` and get things back just as they were. Also, unlike some lesser VCSs, Git is transactional---so if you say "git pull" and then trip over the power cord while it's updating, your repo will still be in a good state afterward. Technology that has a simple, explicit concept of state--such as Docker images or Git commits--is fundamentally nicer to work with. You can explore and experiment, and if things go wrong, you can roll back with confidence.
- AlexanderDhoore 13y ago"Destroys privacy by posting tons of selfies" UNDO UNDO UNDO
- tchvil 13y agoWe provide a timesheet web app. And didn't want save/submit buttons. Auto-saving the data as users type. To alleviate this change for business users, we decided to build an Undo, and a Redo, for most user actions. With a similar technique, by storing the action and it's reverse in 2 stacks. And moving them from one stack to the other. It was quite hard to implement together with an auto-saving of the data. But after 3 years of operations, the undo/redo is barely used. And we get requests from users who clearly didn't see it. Or don't imagine it is possible. While I was really happy seeing it working on a web app. I'm not sure it was worth the effort, and the additional complexity to save data.
- fivesquare 13y agoNever thought about it. The concept is interesting.
- fivesquare 13y agoInteresting concept.
- j_s 13y agoCouchDB supports undo as part of their core storage model. http://guide.couchdb.org/draft/btree.html http://guide.couchdb.org/draft/btree.html The short answer is that because CouchDB uses append-only files, the B-tree root node must be rewritten every time the file is updated. However, old portions of the file will never change, so every old B-tree root, should you happen to have a pointer to it, will also point to a consistent snapshot of the database.
- andyroid 13y agoDoesn't that mean a rollback of the entire database, as opposed to just a single operation?
- CodeMage 13y agoOn the one hand, I agree with the ideas here. On the other hand, it really worries me when I find out that some server doesn't delete the data when I tell it to delete it. For example, when you delete your Facebook profile or your mails on GMail, wouldn't you like that data to be utterly destroyed? What would be the correct solution, the one that balances out both of these needs?
- cgmorton 13y agoThe correct solution would be to tell you what's happening. "Your data will be deleted in 24 hours. You can undo this deletion at any time before then."
- Hannan 13y agoPresumably something similar to the Gmail "Undo Send" example? Time limited reversal (in this case specified by user preference) to give you at least some amount of time to reverse your actions before they become permanent. It's 5/10/20/30 seconds for an email, which seems like a good fit for that use case. Perhaps a Facebook profile delete or mail delete might be more like a 5 min/1 hour/1 day option set, since it doesn't interfere with the primary purpose (i.e. I wouldn't want to wait an hour for all my emails to get sent, but I might be OK waiting an hour for them to actually delete).
- lazerwalker 13y agoGmail's "undo send" functionality faces a similar but different problem: once an email has actually been sent, there is no way to undo it. They way they solve that is by letting you configure a delay, so you have some period of time in which the email hasn't actually been sent yet so you can undo it. Something similar could work here. When you delete some data, it gets soft deleted (still exists in your database/etc, but is considered deleted by the application). After a matter of minutes (hours?), it gets actually deleted. You've got a grace period in which you can undo the delete, and then it's gone forever. Since the most common use case for an 'undo' feature is undoing something you did very recently, that should strike a good balance.
- graue 13y ago"every undoable action first needs to be represented by an object in your code. This is called the Command Pattern" This is too OO for my taste. Having just seen a talk about MiniKanren, I wonder if you can implement undo effectively with a relational (logic) programming system. Is anyone aware of research (or practice) to that effect? My googling isn't turning up anything relevant.
- krallja 13y agoFor FogBugz and Kiln, we try to follow the principle that changes should always be reversible. Clicking "delete" on something just marks it as deleted, for example, with a corresponding "undelete" action hidden somewhere administrators can find it. If you want to truly delete something, you have to get in contact with our customer service folks (sometimes to our users' chagrin).