It looks like the intent is to try 5 times, logging the problem each time. If none of the attempts succeed, give up after 5 tries. I'll label this the scaffold, and I'll call the thing to try 5 times the core functionality.
Let's look at the two versions with reference to some coding guidelines from around the web. For simplicity, I'll call versions R for the recursive version and S for the non-recursive version because it has separate code for the scaffold and the core functionality.
S conforms better to SOLID principles than R, in particular to the single responsibility principle, but also to some extent to the Liskov substitution principle.
single responsibility - separating the scaffold from the core functionality allows each to concentrate on their own intricacies.; and
Liskov substitution - separating out the core functionality allows other core functionality to be used with the same scaffold, as you observe.
Your non-recursive version embodies the coding intent more clearly and has less mingling between core functionality and exception code. This helps with code review and maintenance. To improve on it, you can consider using another of the SOLID principles: dependency inversion. Instead of having the generic executeProcess
depend on the concrete someMethod
, add a call-back as a parameter toexecuteProcess
and call executeProcess
with (an encapsulated form of) someMethod
. This allows you to put executeProcess
into a generic library rather than copy-paste-modify it for each new someOtherMethod
that might be introduced later.
Mingling business logic with exception handling is the first warning in this list of best practices for exception handling. Even the sleep can be considered part of the clean-up, perhaps relegated to a finally block or placed outside the exception mechanism altogether.
Another issue with R is that the recursion (into the code that threw the exception) occurs before the exception is fully handled. S
Your refactored version is the better option of the two.