Whipping inherited code into shape
When I receive code, and before adding anything new to it, I always spend a little time (1 hour, 1 day) on "preparing" the code for the later modifications. This preparation is made in 2 steps:
- code cleaning
- code clarifying
Once I've done that, I understand the code/project better, and I can start adding tests, and functionalities.
Note: all the actions below are possible thanks to modern tools, and 100% safe refactorings => no need to write tests first.
Code cleaning : First, I run a quick and fully automated analysis of the code, with just a few rules:
- remove dead code (classes, methods).
- remove unused method parameters, variables
- remove useless variable initialisation
- remove useless Casting
- tighten visibility (public => private)
- move tests code to a separate code tree
- modernize (Java1.4 => Java5)
Second: amongst the hundreds of inspections rules offered by IDEA, a few dozens will spot oddities and probable bugs in the code (like modifying the contents of a collection passed as parameter, etc..). In those "hot" locations, I add a "todo: check", or "todo: modernize" tag, for later review.
Code clarifying : I examine the code structure, starting with the 2-mile high view of the project, and going down. Along the way, I would perform :
- rename : (package, class, method, parameter
- move : package, classes, methods, ...
- extract/inline method
- introduce variable
Note: As this has to be fast, I only "cure" the worst problems. I tag the others for later reviews: "to optimize", "to betterize", "to fix", "danger", etc..
Some advice from Rod:
Help! API Overload
Today, there are many API and technology choices for most problems in J2EE.
Even Sun now seems to be at the point where pulling it all together is so complex that we're seeing significant duplication of effort. For example, JDO and EJB 2.0 entity beans with CMP seem to overlap significantly.
Ultimately, we all pay for duplication of effort in increased effort and decreased quality. At least we can do our utmost to control it within our organization. I believe that code reuse impossible, and we should do our best to achieve it.
There are many ways to avoid duplication of effort and leverage existing code. I suggest the following practices as a starting point:
-
Adopt existing frameworks where possible. For example, use a standard logging framework and an existing framework for web applications. However, don't force developers to use organization-wide standard frameworks if it seems that they're not proving a good fit to the problem in hand. Where multiple alternative frameworks exist, survey the options. Don't automatically assume that the first product you look at, or the most popular, will best meet your needs.
-
Have zero tolerance for code duplication. This indicates the need for generalization: try to avoid code duplication in the first place, but refactor it out of the way as soon as it appears.
-
Ensure good communication amongst developers. For example, have developers give presentations on modules they've recently completed, so that other developers know what common needs are emerging or have already been met. Encourage developers to encourage other developers to use the infrastructure components they've implemented.
-
Develop and maintain some simple infrastructure packages that implement functionality that's widely used. Document them well and ensure that all developers are aware of them.
-
Adopt standard architectural patterns, even where it's not possible to share code. It's much easier to avoid duplication of effort when working with familiar patterns.
-
Use code reviews. This not only helps to boost quality, but also spurs communication within a team.
Technorati Tags: Java