For further actions, you may consider blocking this person and/or reporting abuse
For further actions, you may consider blocking this person and/or reporting abuse
Andrew Bone -
Michael Tharrington -
vincanger -
Anisha Malde -
Top comments (3)
The hardest part of refactoring legacy code is ensuring your changes to don't break something else, and its hard to check that without having lots of tests. Unless (of even if!) you wrote the entire codebase, it can be tricky to know the full extent of what-depends-on-what, so you need a strategy to verify this.
I also tend to start by finding the smallest-reaching parts of the program that can safely be cleaned up, and starting there. Once you have the smaller bits cleaned up, it should be easier to determine the reach of some of the bigger chunks. Just keep going up the chain in this fashion.
For example:
@deprecatedto the Javadoc of the old methods and the compiler will warn you when it is being used, which may be helpful.Another practical way that I like to refactor large, legacy codebases is by attempting to modularize it. Move classes into isolation so that other parts of the program cannot even see it, or have no way to directly interact with it.
This is pretty easy if you're using Java and Gradle, as you can pretty easy just move code into another Gradle subproject and the compiler will tell you exactly what will break. In a lot of cases, what immediately looks like a dependency is actually just spaghetti code and methods that should be moved closer to where they are actually needed, and the whole lot of them can be moved to another module together.
Unfortunately, I do not have much experience with this outside of the Java world, but similar techniques should be able to be applied with care: Identify all parts of the app using a small bit of code, figure out how much of that code can be extracted somewhere else, and clean up the extraneous bits as you make that move. Effective use of namespacing and working to eliminate global state can help here, as it will enforce boundaries in your code that should be maintained.
Thanks a lot for writing such a detailed answer!
At an abstract level: write a test for the functionality, change the code, run all the tests, repeat.