Wednesday, June 21, 2006

Cheeburger, Cheeburger, cheeps, pepksi

One of my coworkers doesn't have a blog, but he successfully identified another sacred cow that we're converting to cheeburgers on our project. Yet, he's so altruistic, he won't take credit for the idea, saying that it's Marjorie's idea instead. So that he can remain anonymous, I'll just call him Zak T. No, that's too obvious, let's call him Z Tamsen instead.

Zak's sacred cow is the convention in the .NET world of using Pascal casing for namespaces, which is a terrible idea. We've already run into situations where a namespace clashes with a class name, which is annoying. So, we've decided to make all our namespaces all lower case, ala Java, with underscores to separate logical names (very un-ala Java).

Namespaces in .NET are particularly broken, and not just the capitalization convention. This is one of the things that Java got really right, but in a very subtle way. One of the early annoyances for most Java developers is learning the concept of a root directory, and how the package names of your code must match up to the directory structure. Once you grok that concept, though, it makes perfect sense. Only much later do you figure out that this is one of the subtle elegances of the Java language. Because the package structure is tied to the underlying directory structure, it is difficult to create class names that overlap because the OS won't let you create 2 classes by the same name in the same directory. Score one for Java, leveraging the OS to prevent headaches for developers. Of course, with the advent of virtual directory structures in JAR files, you can now create conflicts, but it is thankfully still rare.

Namespaces in .NET have no such useful restrictions. It is trivially easy to create name conflicts because the namespace is just an arbitrary string. Most of the .NET developers I know (especially if they've done any Java) use the useful "namespace must match directory structure" convention (with less restrictions on the actual root folder). In fact, one of my colleagues, Yasser, has created a very useful utility called Namespacer that verifies that your .NET class' namespace matches the directory structure. After some use on our project, he's planning to open source it. Short of fixing namespaces in .NET, at least there is a way to verify the adherence to a useful convention.

10 comments:

Cory Foy said...

Great post Neal. It's definately something I've run into before.

More annoying is that when I get a patch, or have a source file and want to know what directory it is in, in Java I can just go to it. In .NET, I can't. It's particularly prevalent in NUnit, trying to figure out where the patches go before I commit them.

woolfel said...

I'd have to agree completely. The problem also occurs when there are multiple classes with the same name like Node, but have different namespace. To get around that, you have to setup directories in VS.NET, which is more annoying than not. Having all the files in the same physical directory is one short-sighted annoyance of VS.NET

Jason Gerard said...

The problem with forcing namespaces to match a directory structure as in Java is that the CLR is a language neutral platform. In fact, a language doesn't even have to support namespaces to be CLR compliant.

Neal Ford said...

That's true, but Java is a cross-platform language, and they still felt is was safe to assume hiearchical directory structure. The .NET guys are clever; they could have figured out a way to fix this glaring problem.

Daniel Root said...

What about case-insensitive languages like VB? It seems like following MS naming guidance and using a code checker like FxCop should catch most namespace conflict issues. I think PascalCase is way more readable than all-lowercase or using underscores.

Neal Ford said...

Excellent point, of which many .NET developers don't pay enough attention. .NET guidelines insists that you must accommodate case-insensitive languages. However, even in that case, Pascal case does you no good, and the underscores may help you. Sorry, but my_company.my_massive_project.unit_tests is much more readable than MyCompnay.MyMassiveProject.UnitTests. Maybe this is just an opinion thing.

Patrick Schriner said...

The greatest thing about Java´s restriction is about navigating in completely foreign code. Finding a source file in something as large as e.g. the Eclipse project is trival in Java. You know where to look.

Partial classes are imho one of the worst ideas for larger projects as well.

DavidK said...

I really disagree. IMO namespaces are there to allow the logical organization of classes to be completely independent of the physical structure of the files that implement them. If you want to keep them matched, you can, but I don't think it would be an enhancement to .NET to force that upon all developers. Nor do I think it would be a good idea to rely on the file OS to enforce naming collisions. IMO this objective would be an overcoupling concern from a framework design perspective, and we'd still have the potential for collisions to occur when namespaces are implemented in multiple assemblies each with separate root directories. IMO if a name collision comes up, the focus should be on why we have two classes with the same name. If they are the same object, perhaps they should be merged into one class. If they are different objects, perhaps they shouldn't have that same name. Personally, when the decision is mine, I generally prefer to have the class file name include the namespace prefix for larger systems, and I try to limit namespaces hierarchies to 3 or 4 levels tops.

As for namespace names clashing with class names, again I think the focus should be directed toward the underlying reason why. Is this really a valid subspace that will contain multiple classes? If so, then the name should probably convey more meaning than the name of a single class member.

All of this is really just MHO, I think one of the great things about the namespace implementation in .NET is that it gives us the freedom to do whatever organization makes the most sense to the developers of a given project.

Shane Sukul said...

I do not think that underscores are any more readable than Pascal casing. It definitely sounds like an opinion thing and I personally like the freedom that .Net offers. I will leave the rest to personal discipline.

Nguyen said...

I would say the directory thing has little to do with the clashing because within a project we hardly see this happens and for libraries they are usually jar files. Two reasons that it is hard to have naming clash in Java are: 1. Package names are lower-case. 2. Package names reflect the organization and project (e.g. org.apache.xxx or com.mycompany.erp etc.). Thus, workaround these 2 items are enough, no need to organize the directory structure (which I think too restrictive)