I wonder, given some program source code, and applying small incremental refactorings, is it always possible to get from any starting code to any other code configuration where the code still retains all the functionality of the original code, or are there valid code configurations which cannot be achieved through refactoring?
For example, starting with code which sorts using Bubble Sort, is it possible to refactor that using small incremental refactorings and end up with a much better sorting algorithm, such as Heapsort or Quicksort?
(I suspect not. I suspect the only way to go from Bubble Sort to Heapsort would be to first analyze the Buble sort code and realize on a higher level what the code is achieving, namely that this bit of code is a "Sorting Algorithm", and then one can replace that sorting algorithm with any other sorting algorithm, but the swap I'm guessing consists of fully replacing the algorithm with a different algorithm which accomplishes the same thing; I'm guessing there are no smaller incremental refactoring steps that could be made without understanding the higher concept of what the code is trying to achieve.)
Is my hunch correct? Has any mathematician examined this to prove what better code configurations are reachable and which ones are not, by using only standard refactoring techniques, without understanding the "goal" of the code?
(I'm kind of fudging because I'm sure someone will say "replace one algorithm with a better one" is a refactoring technique.)