Processing becomes more complicated when the operation could throw an exception, as we then have to consider how to handle the exception:
- Should the exception be propagated?
- Should the caller be expected to be able to reverse any previous state changes?
- Should the exception be caught and ignored?
- If so, should we continue to recursively apply the operation?
An alternative approach which may be useful in some situations could be to have a helper object which takes a copy of the outermost starting object and attempts to apply the recursive operation on the copy. If the operation is successful then the completely transformed copy object can replace the original object. If the operation was not successful then the original object would remain untouched and the information exposed by the failing operation could be made available to the caller.
I think this may count as a special case of the Unit of Work pattern, where the objects involved are actually part of one composite structure.