Thursday, April 15, 2004

Scoping Doesn't Save You.
Large projects and type names.

There seems to be a bit of a misconception out there. People act like namespaces mean they don't have to think too hard about type names anymore. Type names are local in scope, so you don't have the same collision problems that you used to get in large projects.

"Gone are the days when we need to carefully craft a symbol name" they cheer. "If each library has it's own namespace, we are in the clear!".

Not so.

Think about maintenance. We are 600 lines into a 1500 line file, one of 20 in this library, one of several hundred in the project. We are looking for code that is instantiating the class "Bank::Branch::Acct::BalanceInfo" which we have just modified. We want to be thorough and make sure you aren't messing anyone up. At line 600, we find something like this:

BalanceInfo newBalance(5,5,5);

Now, is this something we need to be worried about? A quick glance at the top of our file and we see,

namespace Bank {
namespace Branch {

So, we're close to the same scope, but is it the same one? To find out, we essentially need to track down the one that the compiler ends up using. At first glance, it doesn't look like it, our BalanceInfo is in the "Bank::Branch::Acct" namespace. However, we might have a magical "using namespace" lying around to cover for that. So, it's back to grepping through the code. Luckily we find a type that is "Bank::Branch::BalanceInfo", which would hopefully mean that the one we've got there isn't what we are looking for. I say hopefully because we can't be sure about the using, and the compiler doesn't maintain a global symbol table for the namespace, only the ones it finds during the compile of that specific file. In other words, it depends on which files are included in the compilation of that file.

In this case, the developer wasn't completely derganged, and there wasn't a hidding "using", so we had the correct one.

I don't really see an easy way around this other than careful design. We need to ensure that types with the same name contain the same information. Even to the point that there is an implied inheritance structure.

For example instead of

class Bank::Branch::BalanceInfo;


class Bank::Branch::Acct::BalanceInfo;

we would have

class Bank::Branch::BalanceInfo;


class Bank::Branch::Acct::BalanceInfo public class Bank::Branch::BalanceInfo;

Might save some hassle later...