Steve, thanks for the answer! I thought about it since the last time and got to a conclusion that this might not necessarily be a bad thing to have this kind of design, but is certainly something to look at critically.
As for the error recovery you mention, in this particular case (as I remember correctly from the code), the error handling was done by the entity that triggered the procedure (don't remember the exact reasons, sorry...). Also, some of the steps had rollback mechanism implemented, but the rollback was inherent to a single mechanism rather than it being a "step" or "action" (e.g. saving configuration file was triggered from some other places than just the replications setup procedure and in all of those places, we needed to guarantee the rollback, so the rollback was triggered internally and additionally, exception was reported, e.g. to display it on GUI), while some of the steps did not require rollback, because they did not leave machine in the "corrupted" state.
Having said that, there were other places in the application, where I used a pattern similar to the one you mention - I had a series of "steps"/"actions" that I went through in a loop and each had rollback()/undo() method.
The reason I asked this question is because when I moved from "doing structural design with objects" to "doing something more OO style" then many (not all of course) of my conditionals went from the logic itself to either the structure, i.e. the the way pieces are assembled together at the application entry point or to factories. Further down the way, trying to follow "tell don't ask" heuristic led to decisions being made locally where the information is available instead of as a part of higher level workflows. This left me with a considerable amount of "cyclomatic complexity 1" workflows and there wasn't a need for every such workflow to have its own error handling. I noticed that I tend to tolerate such "series of calls" as long as the number of dependencies is relatively small and I seem to break it into "actions"/"steps" collections as soon as I observe I am pushing too much objects through the constructor.
Also, I am rather talking about workflows such as:
a.x();
b.y();
c.z();
where a, b and c are not closely related to each other (i.e. are different subsystems), than something like this:
v1 = a.x();
v2 = b.y(v1);
v3 = c.z(v2);
return v3;
I know it's very hard to reason without looking into the actual code and its context, but does what I described sound as something familiarly good/evil or is too much dependent on the context to draw any general conclusions?
I'd be happy to know your thoughts!
grzesiek