@avalander
has given great advice. Just to add (and maybe repeat) a few points:
Legacy code is valuable
Legacy code is already out there in the world, helping people's lives. Working on a legacy project is exciting because you are improving on something that is already useful. I find this thought reassuring when in the middle of wrestling with legacy code.
Don't rewrite (unless you absolutely have to)
Avalander has already covered this in depth, but it's worth repeating: Rewrites usually fail.
Your existing codebase is a document of decisions that have been made about your project. A lot of these decisions may seem bizarre, but most will be there for a good reason. If you throw that away, then you have to make those decisions all over again. This takes time. Meanwhile, you're old codebase is dead in the water, while you're playing catch-up.
Yes, there are probably times that a rewrite is appropriate. However, this is not a decision to take lightly. If in doubt, favour refactoring.
Refactor separately
Refactoring and adding features/debugging should be kept separate. They require two completely different mindsets. When refactoring, your biggest concern is not changing behaviour; when adding a feature, your biggest concern is changing behaviour. Mixing these up will cause a lot of confusion, and make them hard to juggle in your head.
My process tends to be:
Find the area of the code that I'll be working on
Create tests (if they don't exist)
Refactor, until I understand the code well enough to change it
Finally begin work on the feature/bug
The refactoring stage is crucial here. Often the answer will just seem to fall out as I'm refactoring.
Make small changes
One thing that I've found useful when refactoring is keeping my changes small. It's much easier to manage lots of little changes, as opposed to one huge change.
@avalander has given great advice. Just to add (and maybe repeat) a few points:
Legacy code is valuable
Legacy code is already out there in the world, helping people's lives. Working on a legacy project is exciting because you are improving on something that is already useful. I find this thought reassuring when in the middle of wrestling with legacy code.
Don't rewrite (unless you absolutely have to)
Avalander has already covered this in depth, but it's worth repeating: Rewrites usually fail.
Your existing codebase is a document of decisions that have been made about your project. A lot of these decisions may seem bizarre, but most will be there for a good reason. If you throw that away, then you have to make those decisions all over again. This takes time. Meanwhile, you're old codebase is dead in the water, while you're playing catch-up.
There are some famous articles about this, notably Things You Should Never Do Part I, by Joel Spolsky.
Yes, there are probably times that a rewrite is appropriate. However, this is not a decision to take lightly. If in doubt, favour refactoring.
Refactor separately
Refactoring and adding features/debugging should be kept separate. They require two completely different mindsets. When refactoring, your biggest concern is not changing behaviour; when adding a feature, your biggest concern is changing behaviour. Mixing these up will cause a lot of confusion, and make them hard to juggle in your head.
My process tends to be:
The refactoring stage is crucial here. Often the answer will just seem to fall out as I'm refactoring.
Make small changes
One thing that I've found useful when refactoring is keeping my changes small. It's much easier to manage lots of little changes, as opposed to one huge change.
This was inspired by Practical Refactoring by Llewellyn Falco and Woody Zuill (which I mentioned here). I'd recommend that video to anyone working on legacy code.
Best of luck Ali!
I didn't know about Joel Spolsky article, it was an interesting read, thanks for sharing!
You're welcome! His blog is probably the most informative I've found on programming. A lot of his posts are old, but stand the test of time.