Thursday, September 3, 2009

Some Thoughts on Refactoring

Recently I refactored the Crackpot code to replace all shared_ptrs by auto_ptrs and pointer containers (see here for a list of changes). There were about 2500 occurrences of shared_ptrs in the code. This was a relatively large refactoring as many memory management issues had to be fixed; basically every allocated object had to be responsibility of some other object (previously these objects had shared ownership, or we can say "don't care" ownership). The refactoring took about a month to complete. In this article I share some lessons:

there are only poor c++ refactoring tools

There are no good c++ refactoring tools. Often in the middle of refactoring, the code does not compile (although it is not a good idea to let the code go too much "out of" compilation), and any refactoring tool dependent on a compiled code would not work.

Perhaps some time in the future, one can create a syntax-based tool for c++ refactoring. The main task was to replace every shared_ptr by a reference(&), and every -> operator by (.). It was a little complex task, but an "intelligent"/machine learning tool could "learn" the changes I was making. Meanwhile, I used the unix sed tool effectively.

The main reason for poor refactoring tools for c++, I consider, is because 1) c++ does not have reflection and 2) it is a quite complicated language. Java, for example, has much more productive refactoring tools. But these too require compiled code.

the code of the unit test of a class is worth the code of 9 classes

Some unexpected bugs cropped up when the refactoring was done. You know how I easily found them? By running the unit tests. If there were no unit tests, probably these bugs would have stayed hidden till much longer. It would have been much more difficult to find which part of the system has a problem. There have been no more bugs (touch wood) related to refactoring after all the unit tests passed (and I hope to see not many more).

PS: There are some aspects of refactoring still incomplete (and there may be some memory leaks) but this incompleteness is not too important for the purposes of this article.

1 comment:

  1. You can use an existing C++ parser, get AST and do all kind of modification to code :)

    sed is not panacea when it comes to semantics and contexts.

    Pure C++ does not have reflection. But Nokia Qt have MetaObject & moc compiler to emulate reflection. VCF C++ also has done well on reflection. I don't think that C++ will need reflection, it's an overkill and imposes performance hit.

    Still, I wish to have to write in pseudocode and have a MAGIC transformer that produces C++/Java/PHP/etc code from pseudocode. Then you don't need to worry about refactoring.

    ReplyDelete