The refactoring sandwich is a refactoring technique. The refactoring order is "sandwich shaped". For example, secondary -> primary -> secondary
, or, tertiary -> secondary -> primary -> secondary -> tertiary
, etc.
When a refactor of a primary component requires a refactor of a secondary component, you first support the upcoming primary refactor with a secondary refactor. You then perform the primary refactor. Finally, you refactor/remove the outdated code in a closing, secondary refactor. The number of layers can be arbitrarily large and the timeline can be arbitrarily long.
Example: Database Refactor
Let's say you want to move from incremental ids in the data layer, to uuids. Your source-code uses ids, so this refactor is non-trivial (particularly if you are replacing ids with uuids). In this scenario, the data layer is the secondary refactor, and the source-code refactor is the primary refactor.
The first refactor is creating the uuid column in the database. The original ids are still in use, but now there's an unreferenced uuid column. This changeset can go to prod without any problems (theoretically).
The second refactor is replacing references to ids with uuids in the codebase. This could be a step-wise refactor that spanned an arbitrary amount of time. During this period, both lookup strategies would be supported. Developers would begin using uuids, and a strategy of moving fully to uuids, and removing ids, would be adopted. Every changeset during this time can go to prod without any problems (theoretically).
The third refactor is droping the id column. By this point, the id column is in the same position the uuids were at the beginning. That is, the id column is an unreferenced column in the database. The droping of the column would go unnoticed by all consuming systems. This changeset can go to prod without any problems (theoretically).