I wanted to see what folks thought were the best way to help junior members gain confidence in their ability to refactor code. I find that often junior developers simply follow the existing patterns and sense an aversion to break anything due to the perceived risk. I am trying to get them to look at the requirements (new and existing) and have the code map onto the domain model versus "tweaking" or "bending" the existing code base to support new functionality. Just wanted to see if there were any folks who have success here. We are currently thinking about pushing more pair programming, TDD, code reviews etc., but wanted to check if there were other success stories...
The only reliable answer will be unit tests IMHO. Not necessarily TDD -- just get them to write tests for the existing methods/classes they want to refactor, make sure they're doing what they're doing, then allow them to refactor like crazy while relying on the tests to make sure the methods are still valid.
The confidence level and flexibility unit tests allow are immensely valuable in these kinds of activities.
I recommend you to have Unit Tests before start a heavy refactoring, if you have a good code coverage, by simply running the tests you'll be able to see if some test fail, which refactoring affected the desired program behavior.
Basically Unit Testing can give you the confidence your team needs to refactor.
The first step would be to have them write tests for whatever they want to refactor FIRST and then refactor. I also think there is some merit in code reviews with more senior developers as well as pair programming.
It seems that pair programming with a senior developer in combination with writing tests would be the optimal situation. If the more experienced developer in the pair is leading, the testing will just be part of it.
Writing tests alone leaves room for improvement. Writing tests in a pair environment is the best of both worlds and therefore should build the confidence quicker.
My suggestion would be to take a system that will change quite a bit over time and let a junior developer give a plan of what basics they want to apply to it, e.g. are unit tests missing, what design pattern may make sense to use to add the new functionality, do you feel this is "good" code and if not, what changes would you make to it? Part of this is getting them into the code and comfortable with it as when a developer doesn't know what anything within the system does, chances are they want to make minimal changes for fear of breaking something and the subsequent negative fall out. If there can be a senior member that can act as a mentor and guide what junior developers suggest into something that better matches what is being sought, this may be the big thing to get in there.
Note that for the above that senior member may have to have a good deal of familiarity and in a way already done the planning of how to make the changes that the junior developer will do, but the idea is to get the juniors more into the code is how I'd see it. If the junior developers can get in the habit of jumping into things and be encouraged to do that, then I can see some success there. The key is to have the idea of how to correct what the junior developer suggests and yet encourage them to give more into the overall process rather than be told what to do.
Some people are more likely to stand out and take a chance, the key is for the group to see how this turns out as what you want in the end is a group of junior developers all working on various solutions where the senior developer may have originally built the system or integrated various products together and thus can give an input on what should be done but act as a guide rather than a parent in getting stuff done.
Another way to view this is to simply visualize things from the junior developer's view. If they suggest something and get something, e.g. praise or better assignments, then this may get things rolling, though one has to be careful on what is given as to keep taking things up a notch can run into problems if it grows too high.
No matter what, you should push for "more pair programming, TDD, code reviews etc". You should also make sure that your programmers (both Junior in years and in habits) are skilled in the fundamentals.
I reccomend suggesting that they read McConnell's Code Complete and Fowler's Refactoring.
- Ask them to write or investigate existing test cases
- Run the those test cases, record the result
- Ask them to refactor the code
- review the refactor code
- Run the test cases match the previous observations
I'd say that for refactoring to be reliable, easy and effective, you need:
- A good source control system (obvious)
- Unit tests
- Design by contract
- Coding Standards
- A performance profiling system
Also, try doing some coding dojo's. One pair sits and programs at the beamer, rotating one developer every five minutes. Have them talk about how they refactor, and why.
I believe the question is not specific to C#, so I'll suggest giving it a try with Java using Eclipse. Eclipse has the best refactoring tools I have ever seen so far (although I never tried IntelliJ IDEA or Resharper). I have benefited a lot by learning refactoring through Eclipse, especially using the Preview window before performing any change.
I would recommend a combination books, tools, coding and mentoring.
Before anything else - get the candidate to buy or borrow Refactoring by Martin Fowler and read it.
If you have a good source control system - it should be trivial to create a separate branch to play with. Also if the end result of the exercise is useful you can easily merge it into the trunk.
Next, pick a specific task that you know would require them to comprehend the application structure. For example, ask them to instrument a part of the system. This provides a task within which to work instead of general directives (like read the framework documentation or read this code)
The next part is to ask that tests be written to support the functionality touched by this task. Review the tests and encourage writing of comprehensive tests. It is important to use a tool for this like NUnit or if your IDE supports unit testing, use that. Encourage the person to ask questions and find out why things are the way they are.
If you are using an IDE that supports it introduce the refactoring tools in the IDE and encourage them to refactor the code. Use pair programming or regular code reviews to mentor the person. The tests can be used to show how unit tests are a vital part of a good refactoring effort. Start small - may be change the names of things or extract fields into properties and then move to more complex ones.
Hopefully, by the end of the exercise, not only will the person be comfortable enough to question, tweak and change the application and you would have some useful functionality out of it as well :-)