I'm looking for a design pattern or suggestions that can help refactor my code into something a bit less repetitive. I have a method that has several sequential steps (10-15) that if any of them fail must record detail about the failure to a log and rollback all previous portions of the transaction. The example is below.
I have thought about taking each try catch and turning it into an individual method but then I have to pass around my undo stack (among several other variables) and I still have to conditionally abort the method and process the undo stack. I've briefly looked into the Momento and Command patterns but both seemed to grow the line count by a fair margin.
EnumResult TransactionThatRollsBack()
{
var undoLog = new Stack<Action>();
try
{
MoveInventory(inv, src, dest);
undoLog.Push(() => MoveInventory(inv,dest,src));
}
catch (Exception ex)
{
RecordError("InventoryError", ex, inv, src, dest);
Undo(undoLog);
return EnumResult.FailedInventoryMove;
}
try
{
NotifyReportingOfMove(inv, user);
undoLog.Push(() => NotifyReportingOfUnMove(inv, user));
}
catch (Exception ex)
{
RecordError("NotifyReportingOfMove", ex, inv, user);
Undo(undoLog);
return EnumResult.FailedReportingMove;
}
try
{
AddUserToSweepstakes(user);
undoLog.Push(() => RemoevUserFromSweepstakes(user));
}
catch (Exception ex)
{
RecordError("AddUserToSweepstakes", ex, user);
Undo(undoLog);
return EnumResult.FailedSweepstakesAdd;
}
...
return EnumResult.Success
}