Dec 31 2008

Refactor for C++ – addendum

Category: Programming, toolsMaciek Talaska @ 6:01 pm

A few days ago I have written a short note in which I have enclosed some of my thoughts about freely available Visual Studio 2005/2008 plugin for C++ developers (DevExpress Refactor for C++). I have pointed out that Refactor had some problems with simple refactorings in one of my projects. The simplified code snippet I have provided is not good enough to help understand the problem (the snippet seems to be too simple, and it is impossible to encounter the issue I was writing about). I have spent some of my spare time to find the code that caused problems and try to analyze it and provide a code snippet that illustrates the issue. The following code is very close to the one that I have checked to be error-prone:

// forward declaration    					//(1)
void functionEx( );    						//(2)
typedef void( *void_function_pointer)(void);			//(3)

class SimpleClass
{
private:
	void (*function_pointer)( );				//(4)
	void_function_pointer func_ptr;

	void SetCallBack( void (*function_pointer)(void) )
	{
		this->function_pointer = function_pointer;	//(5)
	}

public:
	void function( )
	{
		printf("\n");
	}

	void Prepare( )
	{
		SetCallBack( functionEx );
	}

	void Invoke( )
	{
		function_pointer();
	}

};

SimpleClass *externalObject;

void functionEx( )
{
	externalObject->function();				//(6)
}

int _tmain(int argc, _TCHAR* argv[])
{
	externalObject = new SimpleClass();
	externalObject->Prepare();				//(7)
	externalObject->Invoke();				//(8)

	return 0;
}

First three lines (marked with (1), (2) and (3)) are just simple forward declarations of global function and pointer to the function that takes no arguments and does not return anything (’procedure’ in some languages). Declared function pointer is used inside SimpleClass (4) and SetCallBack assigns argument value (function pointer) to variable inside SimpleClass (5). Global function ‘functionEx’ (6) does nothing more than calling ‘function’ from object of type ‘SimpleClass’. Where’s the problem here? It seems everything is simple, right? Right. But it is the simplified version of the code I have after I manually renamed function names. The code I was working on was not object-oriented at all – at the beginning. Let’s imagine, that the name of global function is not ‘functionEx’ but ‘function’. Code does not compile. Ok. Lets use Refactor C++ to rename the name of the global ‘function’ to anything that will be different than the name of the method inside SimpleClass. The problem is, Refactor tries to rename things that shouldn’t be renamed, and skip those, we would like to have renamed. Moving cursor to ‘Prepare’ function, selecting ‘function’ (remember, we do not have any ‘functionEx’ in our code!) makes something strange: refactor tries to rename ‘function’ but… it renames the name of the method inside SimpleClass instead of the global function. And now imagine, that the code is a bit more complex, that there are a couple of files inside the projects – headers and .cpp files… This ‘unwanted’ refactoring makes more harm than good (in this case). You may say, that it is because of the code, that looks the way it does… I do not think so. I would expect refactoring tool to be much more ‘intelligent’, but still it is better to have anything (even not the state-of-the-art refactoring tool) than to be forced to make all editing by hand.

I was very interested if the mentioned earlier Whole Tomato’s Visual Assist X will be intelligent enough to cope with renaming the ‘function’. Well, Visual Assist X provides its own mechanism for renaming (not so well integrated with Visual Studio editor as in case of Refactor for C++) and it is much easier to perform renaming, because Visual Assist X shows what actions it is going to perform (and you may uncheck those, you don’t want to happen). Visual Assist X by default wanted to rename the method inside SimpleClass – just like Refactor for C++. So it seems that there is no perfect solution, and one has to be very careful while refactoring anything that contains any non standard pieces of code. Just be aware that something like the issue I have described above may happen, and that’s it.

Happy coding in 2009 :)

Tags: , , , ,