Lately I’ve been working on an app to automate some features of a really great deployment product called Octopus Deploy. It’s a really great product, but when you need to set up a new deployment, you need to go into several screens and it’s several steps. The good news is, the app is all API-based. So, you can do everything either via a REST interface for a C# client library.
In this case, there are I think like 6 things I need to do in that system. If any one of the steps fail, I need to undo everything I’ve done up until this point.
Enter the Command Pattern:
Universally, it’s accepted that if you need undo functionality, you’d use the Command design pattern. However, that design pattern is really geared towards a system you are writing, where you have control over the state of everything. In this case, it’s quite different: I’m interacting with an API of a 3rd-party system and have no control over it’s state nor availability.
So I took the spirit of the Command pattern and simplified it a bit. First, I want to “unwind” the list of things in the reverse order. For example, if the order is:
1) Create project group
2) Create project
3) Create team and assign to team
I don’t want to undo those in the same order, because just about all of the steps will fail. I’d need to unwind them in reverse order:
3) De-assign team from project; delete team.
2) Delete project
1) Delete project group
So, the correct data structure for that is a “Stack” object. You “push” things onto the stack (like loading a Pez dispenser or firearm magazine) or you “pop” things off the stack when you want to retrieve them. For example:
And this “UndoItem” type is just a class I created to keep track of every item to undo:
Now, for each operation I want to do, I keep track of the code that it would take to “undo” that operation. I made an example project which just creates directories:
When we do a “undoItems.Push(..)” – that is what keeps track of the code that it would take to undo that operation. What’s crazy is that because .NET supports “closures”, you can reference variables outside of the scope of your anonymous function. So, imagine several minutes later if we were undoing this operation, “directory1” would normally be out of scope. However, .NET knows how to keep track of the external references that you make.
Doing the Undo:
OK – so we have a stack to keep track of the undo items, and whenever we do something undoable, we write down what it would take to back it out. Finally, we need to actually execute the stack of undos. So, I have code like this in the exception block:
So this walks through the stack, pops off an item, and then executes that undo code while printing the screen what it’s doing.
I thought this was an interesting computer science problem. I didn’t solve it in the typical way with a full-blown Command pattern, but this little chunk of code in the same vein/spirit worked out well, so I wanted to write it down.
As I mentioned, I made a complete sample, which you can view or download from GitHub: