Context: I am a new hire out of university at a large software company tasked with either refactoring or re-writing a large legacy method (~500 lines, ~2000 lines expanded with private method calls) that performs a complex workflow with many responsibilities. You can imagine it applying a complex series of interdependent transformations to its input before returning the transformed data. Static code analysis indicates it has a cyclomatic complexity of 67. This class is part of a package used across multiple services not owned by my team and as such the interface cannot be modified. This method is part of a package that is being deprecated feature-by-feature over a long period of time. The goal of the refactor/rewrite is to make it so that we maintain feature parity with the original implementation, but can easily disable individual transformations over time. The method has few tests, so my first task will be to create a full test suite for the class to enforce stable behavior.
What sort of design patternsapproach can I apply in order to successfully perform this refactor? My current idea is some sort of Pipeline pattern where we take a collection of enums which describe which transformations to disable when assembling the pipeline. This way deprecating transformations in the future is a matter of adding an additional enum to the parameter. E.g. Something along the lines of
public class LegacyClass {
...
public WorkflowResponse performWorkflow(WorkflowInput workflowInput) {
WorkflowPipeline pipeline = this.assemblePipeline(this.featureDeprecations);
pipeline.validate();
return pipeline.execute();
}
private WorkflowPipeline assemblePipeline(EnumSet<FeatureDeprecations> featureDeprecations) {
WorkflowPipeline pipeline = new WorkflowPipeline();
pipeline.addTransformation(new TransformationOne());
if(!featureDeprecations.contains(DEPRECATE_TRANSFORMATION_TWO)) {
pipeline.addTransformation(new TransformationTwo());
}
pipeline.addTransformation(new TransformationThree());
return pipeline;
}
Is following this design patternapproach a good idea for my situation? The main downside I can see is that the code for assembling the pipeline will grow to be very complex even if I manage to encapsulate each transformation rather than having them live within the performWorkflow
method.