8

I'm infected by Java, C# and AS3, I keep wanting to use C++ namespaces in the same way but I keep reading that they're not really designed with this in mind.

Is there a correct way to use namespaces? For instance in a codebase consisting of a dozen library projects (let's say things like graphics, sound, math, etc) and a couple of application projects, what to do? Is it right/wrong/developer-preference:

  • To put everything a top-level MyCompanyName or MyProjectName namespace?
  • To have a (sub-)namespace for each library

Are there official rules/guidelines as part of C++, or only recommendations which people tend to follow?

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
  • 5
    @close-voter: This is a very clear question that has a definite answer. Nothing about it is subjective or argumentative. – Björn Pollex Nov 02 '10 at 09:41
  • What? I'd say it is extremely subjective. Of course we *could* be pedantic and say that literally speaking, he's asking a simple "yes/no" question: No there are no official guidelines, and yes, there are unofficial recommendations that people tend to follow. But what he really wants to know is what those guidelines *are*, what the right way to approach namespaces *is*. And that is subjective. **But** of course, that doesn't mean it should be closed. The question can be answered, and the answers can have value, and be good or bad, even though they are subjective. – jalf Nov 02 '10 at 11:20
  • 1
    So yes, it is subjective, but no, it's not argumentative (which is really the important part, as far as close votes go) and no, it doesn't deserve to be closed. :) – jalf Nov 02 '10 at 11:20
  • Very few questions have a yes/no answer. That doesn't mean there's not a 'right answer' either based on official language guidelines or as a de facto standard – Mr. Boy Nov 02 '10 at 11:39

3 Answers3

15

As I mentioned in a comment on @Nim's answer, the key is really to come up with a structure that is practical.

If you look at, say, the .NET framework, its namespaces have long names and are deeply nested (Say, System.Collections.Generic.List<T>). The same applies to Java. You have hugely long names for hugely nested namespaces with no effect whatsoever.

The first time I create a List class, I'm going to run into name collisions, which is what namespaces were supposed to prevent. (Since this seemed to give a commenter the wrong idea, of course I am able to create my own List class. But every time I use it, I risk running into a conflict. The "standard" List, or its namespace, are both very commonly used, so there's a good chance I'll have a using on that namespace, which means that, if I also want to refer to my own List class in the same file, I get a conflict)

By contrast, the C++ standard library puts nearly everything in a simple std namespace (and a few things in std::ios)

In practical terms, the .NET namespaces are really a waste of effort. They have no effect. Every code file starts out with a long list of using X; using Y; using Z, so the net effect is that none of the namespaces are actually in effect when you write your code. In order to create a list of ints, I just do List<int>. The namespace is basically gone.

In C++, people are discouraged from using using namespace std, so in order to use a standard library symbol, we use the std prefix: std::vector<int>.

Boost uses something similar: nearly everything is in a boost root namespace. A few complex libraries are then placed in sub-namespaces, such as boost::filesystem. or boost::mpl, and some libraries have "internal use only" namespaces typically named aux, but they're intended to be invisible (or at least ignored) by the user.

This preserves the advantage of namespaces much better: they avoid naming conflicts. I can (and people often do, since vector can have several somewhat different meanings) define my own vector class, and it won't conflict with std::vector.

So how deeply nested should your namespaces be? I tend to go with something like the standard library, plus a bit. Don't invent new namespaces for everything, and keep namespace names short.

Perhaps all your company's code uses a common root namespace, say, Cpy.

Under this you might have a namespace for each product, say, Prod. And past that? Well, you might have a namespace for each major component (Comp), and that's basically it.

The important thing here is that you virtually never have to refer to the outermost namespaces. The code you write will be inside Cpy::Prod, so the only namespace prefix you're going to have to type out is Comp::, which is short and concise, like the standard library std. I virtually never have to write Cpy::Prod::Comp, because all my code is already inside the first two namespaces. If that wasn't the case, the namespace structure would be too long and too deeply nested.

Then I sometimes do like Boost, and create small "internal" helper namespaces, typically called Aux or Util or similar. These should be small, and should only ever be accessed from their immediate parent namespace. A specific component might have a few classes that are for internal use only. So they are tucked away in a small Aux namespace, mainly to keep them hidden from others that reference our component.

Of course, you might ask yourself what purpose the outermost "company" namespace really has. Isn't it a given that all our code is, well, our companys'? And third-party code will typically (hopefully) be inside its own namespace (say, boost::), so even without the company namespace, we shouldn't risk any conflicts. You might want to delete that one.

Another thing to consider is that if you're writing library components for external use, then the namespace structure should be even shorter. Inside the company, you can assume that everyone is already writing code inside the "company" namespace, so they never have to type out the namespace prefix. It's basically "free". But if external users have to refer to your code, it is an additional layer of namespaces they have to type out, which gets old fast. An overall "product" namespace is probably unavoidable (similar to std or boost), but then you might want to avoid the "product" namespace as often as possible. (Again, like both of these, which only rarely create sub-namespaces below the root namespace)

The bottom line is really that your namespaces have to be practical and usable. If you force users to type out more than, say, 8 characters in the namespace prefix, it gets annoying, and they'll just start putting using namespace X everywhere. You only really need namespaces where you might otherwise get name collisions. Code you control should never share a namespace with third-party code, because you have no control over what names they add (and usually, third-party libs take care of this by putting their library inside a common root namespace, such as boost). But among the code you control, there there aren't going to be that many collisions. So don't define more namespaces than you actually need.

jalf
  • 243,077
  • 51
  • 345
  • 550
  • In C#, there aren't any name conflicts if you do `using System.Collections.Generic` and define your own `List` class. Hell, you won't even get a name conflict if you have a namespace List and a class List in the same scope. `using` doesn't "eliminate" the namespace. C++ coders are only discouraged from `using namespace std` in header files. There is rarely a disadvantage to using it in source files; the full namespace name (or an alias) should only be used when you actually need to disambiguate something. – Steve M Nov 02 '10 at 11:52
  • 3
    @Steve: if I refer to the "standard List in my code file, I typically put a `using System.Collections.Generic´ at the top of it, yes? And if, in the same file, I need to refer to the List I defined myself in `Jalf.SomeOtherNamespace`, then I'll also put a `using Jalf.SomeOtherNamespace` at the top of the file. Now, if, in the body of the file, I type `List`, I get a name collision. The identifier `List` is ambiguous. So yes, I get name conflicts in C# because namespaces are selectively disabled any time they would actually be useful. – jalf Nov 02 '10 at 12:02
  • oh whoops, I really screwed up the formatting there... Hope it's still readable. ;) – jalf Nov 02 '10 at 12:19
  • Well argued answer. However I don't agree the C#/Java setup is 'useless'. It's not a directly comparable language feature – Mr. Boy Nov 02 '10 at 12:19
  • It may be ambiguous, but there is no collision - the namespaces are still present and are not "disabled." You just have to disambiguate List with the full name every time you use it, which is what namespaces are for and is exactly what you're doing when you write `std::` all over the place in C++. C# has namespace aliases, too, so it's not like you have to fill your screen with long namespaces in this situation. – Steve M Nov 02 '10 at 12:25
  • 2
    @Steve: how can it be ambiguous if there is no collision? ;) Anyway, as you say, one of the most realistic options developers have is to type out the *full* qualified name, which, on those platforms, is *ridiculously long*. And .NET allows you to define aliases for *individual* classes, but not for an entire namespace, which again may make it a chore. If their namespace structure wasn't so overcomplicated, it would be easier to deal with, was really my point. The cost of these workarounds is much lower in C++ where I just have to add a `std::` prefix, than the mile-long prefixes common in .NET – jalf Nov 02 '10 at 12:31
  • It would be a collision if there were nothing you could do about it. `using` can be used to alias a namespace _or_ a type: http://msdn.microsoft.com/en-us/library/sf0df423(VS.80).aspx – Steve M Nov 02 '10 at 12:56
  • @Steve: there *is* nothing you can do about it. As long as it is there, you have an error. The only thing you can do is to rewrite your code in one way or another so the problem doesn't occur. (otherwise, nothing would *ever* constitute a collision, would it? There is *always* something you can do about it). Anyway, interesting that `using` can alias namespaces too. For some reason I've never been able to get that working, but I never looked it up either, so I just assumed it couldn't be done. Thanks. :) – jalf Nov 02 '10 at 13:20
  • @jalf, "not that many collisions" I think this depends on *how* your codebase is being ultimately contributed to. If you have lots of developers developing structurally the same, but functionally different code, it's hard to avoid collisions without using namespaces or some mangling (YUCK) scheme. – Nim Nov 02 '10 at 15:29
3

I think this is very subjective, and you are likely to receive lot's of different opinions, so here's mine! :)

Nested namespaces - good. One large namespace - horrible.

The above is with real world in mind (i.e. very large code bases). For the sake of preventing RSI, consider short namespace names! ;)

EDIT: An example, and it's highly subjective, other people will have different approaches...

let's say you work for company foo, in Java, typically you start with com, so instead use foo

namespace foo
{

}

Now all your company's code is in one namespace, next consider any shared stuff:

namespace foo
{
  namespace com
  {
    // any communication stuff goes here
    namespace msg
    {
      // let's say you have some form of messages that you send
    } // msg
    namespace con
    {
      // wraps all your connectivity
    } // con
  } // com

  namespace util
  {
    // utilities
    // you may not need to break this up further
  } // util
} // foo

Now let's say you have project bob, give it it's own namespace in projects

namespace foo
{
  namespace proj
  {
    // all projects are here
    namespace bob
    {
      // all bob's stuff is here, break it up as you need (though I wouldn't bother unless you have hundred's of classes where collisions are likely), I'd rather organise the files in the file system appropriately and keep the classes in the same namespace.
    } // bob

  } // proj
} // foo
Nim
  • 33,299
  • 2
  • 62
  • 101
  • 3
    Since you can easily create short aliases for namespaces when using them, it is totally fine to give you namespaces long names (if that serves the clarity of the code). – Björn Pollex Nov 02 '10 at 09:40
  • ... very true... I think fundamentally it comes down to a little common sense... :) – Nim Nov 02 '10 at 09:45
  • But to organize namespaces by project or what? And what level of nesting... in Java you tend to have 4-5 levels very commonly – Mr. Boy Nov 02 '10 at 09:50
  • And can you maybe add an example structure? By the way, I never knew about NS aliasing. A big +1. – Mr. Boy Nov 02 '10 at 09:56
  • Consider whether your projects are independent or will re-use lots of code, may be have a root which is company, then within that a level to indicate project (and also namespaces for shared stuff - lets say communication, db access, utilities etc.) and then within each project, break it up as you see fit. About three levels is usually enough I find, any more I think is a bit much... – Nim Nov 02 '10 at 09:57
  • I think this is a bit too simple. Nested namespaces are fine, as long as the nesting level is low. Once it gets too deep, it just becomes an invitation to use `using namespace ...` all over the place. `foo::proj::bob::myclass` is really stretching it. The key is that the namespaces have to be *practical*. T – jalf Nov 02 '10 at 10:55
  • 1
    @jalf - hence the encouragement to use aliases... (as an example to John `namespace p_bob = foo::proj::bob;` then `p_bob::myclass...` ) – Nim Nov 02 '10 at 11:06
  • @Nim: fair enough. But then why do we need the namespace hierarchy in the first place? What purpose does each level serve? And is it a purpose best served by namespaces, as opposed to some other grouping or scoping mechanism? – jalf Nov 02 '10 at 13:15
  • @jalf - clarity for one, collision is another, however you could work around that with naming - then it boils down to a matter of preference, I'd prefer to have bob::Time and kim::Time rather than bobTime and kimTime and having to remember to do that each time I need a Time class in a project (stupid example, but hopefully you get the idea!) - but like I said above, you need to apply a little common sense... – Nim Nov 02 '10 at 15:19
  • ... but the syntax in c++ is bad, because the nesting and indent goes deep when using multiple namespaces. – Beachwalker Jul 06 '12 at 08:08
0

For me, simply put I have no problem with using namespaces in index files, but I will never hardly use them in .h or header files because alot of times things get changed or added on so having one big namespace may be a big mistake. However for smaller seperate files having smaller seperate namespaces isn't too harmful I dont think.