Do not name a class the same as its namespace, Part Four

Do not name a class the same as its namespace, Part Four

Rate This
  • Comments 30

(This is part four of a four part series; part three is here.)

Part Four: Making the problem worse

I said earlier that the fundamental reason for namespaces in the first place was organization of types into a hierarchy, not separation of two things with similar names. But suppose you are putting something into a namespace because you have two things that are of the same name and need to be kept separate. Suppose you reason “I’m going to put List into its own namespace because List could conflict with another class named List. The user needs to be able to qualify that.”

OK, that’s fine; put List into MyContainers then. But why would you then repeat the process and put List into a child namespace in MyContainers? The most plausible reason is that the level of disambiguation achieved so far is insufficient; some other entity named List is going to be in scope in a code region where elements of MyContainers are also in scope.

Let us posit that as our cause for creating a new namespace MyContainers, and then creating a new sub-namespace, MyContainers.X, to be the declaration space of List. What name should we choose for X? If the whole point is that something else named List is in scope somewhere that elements of MyContainers are in scope, then choosing “List” for “X” is making the problem worse, not better! Before you had two things named List in scope. Now you have three things named List, two of which are in scope. This is making it more confusing without solving the problem at hand: that there are two things named List in scope.

Any one of these four reasons is enough to avoid this bad practice; avoid, avoid, avoid.

(This is part four of a four part series; part three is here.)

  • @Pavel: Eric's *other* claim to internet fame was having one of the earliest websites devoted to the works of J.R.R. Tolkien.  (I'm no expert on the life and times of Eric Lippert, but I have been reading through the Fabulous Adventures archives ... he's made reference to it at least once before.)

  • The way I discovered this issue was with the term 'Service'. I created a namespace to match the component, e.g. 'CustomerDataService' and then used that same name as the root implementation class, after it was the type that repesented the 'NT Service' concept. I ended up changing the component and namespace to 'CustomerDataServer' and left the class name alone. I toyed with other alternative like calling the class just 'Service', but it can be awkward in the IDE* when you have many files open all with the same name, e.g. Program.cs.

    *I'm not suggesting you name your classes just to satsify this issue.

  • Aye aye, nog.

    Say, does anybody know what happens when a class is declared not in a namespace?

    The grammar of the language requires that every class be declared in one of three places: in the global namespace (which has no name), in some other namespace, or as a nested class inside some other type declaration. Therefore every class is declared in a namespace, either directly, or indirectly via its outer types. Therefore I do not understand the question; can you clarify it? -- Eric

     

  • Reminds me of that immutable generic stack implementation you did some time back during the series of articles on immutability. I used that class in a depth-first topological sorter and had to change the name to ImmutableStack<T> so that it wouldn't conflict with System.Collections.Generic.Stack<T>.

  • On the topic of proper coding conventions, I could be wrong but it seems neither FxCop nor StyleCop meets my needs. Is there a way to have FxCop level of enforcement on non-compiled code? For example, ASP.NET source files, or anything that hasn't been built. StyleCop doesn't appear to be testing the same things, such as collection naming, for example.

  • Obligatory mention of buffalo.

  • namespace Buffalo {

     public class Buffalo {

       Buffalo.Buffalo buffalo(Buffalo.Buffalo Buffalo) { buffalo(Buffalo); }

     }

    }

    I think that actually ought to compile, although I haven't tried it. Infinite recursion when run, however.

  • oh no it doesn't compile, needs a "return" in there. Drat.

  • I was just wondering what happens to a class when you declare it without a surrounding namespace{}. It appears the answer is that it goes in the implicit global namespace.

    The first C# app I wrote was for .Net 1.1, and I forgot to put one of my classes in a namespace declaration. Well, it just so happened that when .Net 2.0 came out, it declared a class by the same name. When somebody ran my app on a computer with .Net 2.0 installed but not 1.1, it ran in the 2.0 CLR and got the new class of the same name.

  • One of the annoying (to me that is) characteristics of VSxxxx is that when you add a folder in a project, Visual Studio defaults classes in the folder to a namespace which ends with the name of the folder.  If a programmer is using the folders for physical (as opposed to namespace) organizational purposes, she/he either has to remove the folder name from the namespace of the new class or add a new using statement to include that folder.  In tools/options, the programmer should be able to limit the default namespace to the project.  

  • John: I like this feature because the folder structure and namespaces are two independent hierarchies, but this feature is try to make them similar, which is beneficial for project "complexity". Managing one hierarchy instead of two is huge benefit.

  • Is there any reason why System.Configuration.Configuration doesn't follow this rule? It's always painful to use in code. System.Configuration.Config (or something similar) would have been much better, like there isn't a System.Text.Regex.Regex for instance.

    My guess -- and I emphasize that this is a guess -- is that the class in question was invented *before* the framework design guidelines were written. -- Eric

  • The Los Angeles Angels ought to play nothing but doubleheaders.

  • Thanks, man. I just went and renamed my static GameEngine class to GameEngineUpdator. It was originally NewellHenryClark.GameEngine.GameEngine, but now I know better, all thanks to you :D

  • This does make it hard when you want namespaces like this:

    Doctor.Events, Doctor.Services, Doctor.BusinessObjects

    And then in Doctor.BusinessObjects you want a class called Doctor.

    Each namespace is a type of Doctor functionality, but you can't call them that and still have a Doctor class.

Page 2 of 2 (30 items) 12