51

I've done a bunch of Java coding recently and have got used to very specific package naming systems, with deep nesting e.g. com.company.project.db. This works fine in Java, AS3/Flex and C#. I've seen the same paradigm applied in C++ too, but I've also heard that it's bad to view C++ namespaces as direct counterparts to Java packages.

Is that true, and why? How are namespaces/packages alike and different? What problems are likely to be seen if you do use deep nested namespaces?

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
  • What advantage(s) do you see in using deeply nested namespaces? –  Jan 21 '10 at 09:45
  • 1
    The same as in any other language like Java, AS3, C#,... I don't see the point of your question. – Mr. Boy Jan 21 '10 at 09:48
  • 2
    My point is that I can't see any, and would be interested to know what an obvious fan finds useful about them. –  Jan 21 '10 at 09:49
  • 2
    @Neil: it offers a great way of hierarchically structuring your code. It may not have caught on in C++ (yet!) but it is tremendously helpful. The finer-grained organization also helps to prevent name conflicts much better than flat namespaces. Namespaces/packages introduce a better modularity than can be achieved through header files alone. – Konrad Rudolph Jan 21 '10 at 09:52
  • 7
    Although I use namespaces in my own code, I have come across remarkably few cases where they actually do prevent a name clash, so there is no need for complex hierarchies to solve this problem. And I don't find hierarchies a very useful design tool in any case - if we have learned anything from OOP, it is that complex hierarchies are not the answer. –  Jan 21 '10 at 09:56
  • 2
    @Neil, "I have come across remarkably few cases where they actually do prevent a name clash" - I'd agree with that wrt *hierarchies* of namespace - but after working with C and Objective-C more recently I'm painfully reminded how big a problem it is when you lack namespaces *entirely*! The "solution" of giving everything a prefix is ugly and unnatural, IMHO, and exactly what namespaces are good for replacing. – philsquared Jan 21 '10 at 10:04
  • 1
    @Neil, that's not really the question being asked. I'm asking about the differences/similarities, not your personal preference for using such constructs in any language. – Mr. Boy Jan 21 '10 at 10:07
  • 1
    @John, you also asked, "I've also heard that it's bad to view C++ namespaces as direct counterparts to Java packages. Is that true, and why?", and, "What problems are likely to be seen if you do use deep nested namespaces?". If personal preferences for using such constructs are derived from answering similar questions yourself I think that's relevant. – philsquared Jan 21 '10 at 10:43
  • 1
    Java etc. use nested namespaces/package names to avoid name collisions. If you use package "mathFunctions", then you might colllide with some library you use which also uses it. But org.mycompany.util.mathFunctions is unique. Sun recommends to start the package name hierarchy with your (reversed) domain name, that way it's guaranteed to be unique. – sleske Jan 21 '10 at 11:11
  • 1
    @sleske A frequent convention in C++ is CompanyName::ProjectName, and this is usually enough (for commercial projects). Neither of them answer the question of what happens if code is aquired by another company. I suspect the common practice is that the namespace stays as is unless there is a conflict. – philsquared Jan 21 '10 at 11:44
  • @Phil... probably in reality. But search/replace would probably be _quite_ safe. – Mr. Boy Jan 29 '10 at 16:11
  • @John probably ;-) depends on the company name :-) – philsquared Jan 29 '10 at 17:43

6 Answers6

32

In C++ namespaces are just about partitioning the available names. Java packages are about modules. The naming hierarchy is just one aspect of it.

There's nothing wrong, per-se, with deeply nested namespaces in C++, except that they're not normally necessary as there's no module system behind them, and the extra layers just add noise. It's usually sufficient to have one or two levels of namespace, with the odd extra level for internal details (often just called Details).

There are also extra rules to C++ namespaces that may catch you out if overused - such as argument-dependent-lookup, and the rules around resolving to parent levels. WRT the latter, take:

namespace a{ namespace b{ int x; } }
namespace b{ string x; }
namespace a
{
  b::x = 42;
}

Is this legal? Is it obvious what's happening? You need to know the precendence of the namespace resolution to answer those questions.

philsquared
  • 22,403
  • 12
  • 69
  • 98
  • 1
    Interesting. Could you add some links about "dependent-lookup" and "resolving parent levels"? Never heard of it. – sleske Jan 21 '10 at 11:14
  • 4
    @sleske: the full explanation is much longer than what you can actually write in a comment. The basic idea is what when the compiler finds a non-fully-qualified identifier it will try to match it starting in the current namespace, and if not found it will try the enclosing namespace... all the way to the root. This is extended by ADL (Argument Dependent Lookup), so that if you call a function on a set of arguments, it will also try to match the method identifier in the arguments namespaces. `f( std::string(), ::ns::myclass() )` will also look for `f` in `std` and `ns` namespaces. – David Rodríguez - dribeas Jan 21 '10 at 11:52
  • Thanks for the explanations. As for ADL: that seems mindbogglingly complicated. I wonder if that was really necessary in the language's design. I prefer the Java approach (either unqualified, or fully qualified). Well, C++ has never been excused of being too simple... – sleske Jan 21 '10 at 16:56
  • The original idea behind ADL was to let you use operators that had been overloaded within the namespace that the first operand lived. When it was noticed that this led to an enhanced interface principle (declare things that "operate" on other objects within the same namespace) it was extended to any function. There is a certain elegance to it, but at the same time it is subtle and often surprising (and used to be sporadically supported) – philsquared Jan 22 '10 at 08:31
21

Java packages are not nested, they're flat. Any apparent nesting is nothing more than a naming convention.

For example, the package com.company.project.db has no relation whatsoever to com.company.project or com.company.project.db.x. Code in com.company.project.db has no more access to code in com.company.project.db.x than would code in a.b.c.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • Interesting, I'd never thought about it but assumed package-level scope/visibility would apply to sub-packages. So a package level class in a.b.c is invisible to a.b.c.d? – Mr. Boy Jan 21 '10 at 10:08
  • BTW, Java enforces nesting in the file structure, doesn't it? Not what you meant, but still important... java packages are not arbitrary text you can type in (IIRC) – Mr. Boy Jan 21 '10 at 10:09
  • 1
    @John: On your first point: correct. On your second point, java tools generally enforce a directory structure that looks like the package naming, yes, but again, it's nothing more than a convention, albeit a strong one. – skaffman Jan 21 '10 at 10:24
  • @skaffman: are you sure that it is only a convention? I believe that is enforced not by the tools but by the language itself. If you write `import a.b.c.D;` the compiler will require that somewhere in the classpath there is a directory structure `a/b/c` where class `D` resides. And class `D` must be within the `a.b.c` package. Once enforced by the language it is no longer a convention but rather a requirement. – David Rodríguez - dribeas Jan 21 '10 at 12:07
  • @David: The language does not require that, the tools do. In that respect, it may as well be fixed, but it's important to make the distinction. – skaffman Jan 21 '10 at 13:38
  • 2
    @skaffman: I think I must disagree. To quote "The Java TMVirtual Machine Specification", 2.7.5 Fully Qualified Names: "The fully qualified name of a named package that is a subpackage of another named package consists of the fully qualified name of the containing package followed by "." followed by the simple (member) name of the subpackage." So the JVM spec *does* explicitly mention package name hierarchy. – sleske Jan 21 '10 at 17:11
  • 4
    [cont] On the other hand, the JVM says "Each Java virtual machine implementation determines how packages, compilation units, and subpackages are created and stored[...]" so the rule of putting class files into a directory hierarchy is just a convention of the ClassLoader which Sun's runtime implementation happens to use. OK, enough nitpicking :-). – sleske Jan 21 '10 at 17:12
7

Here are some reasons why and how C++ namespaces are different than Java or C# namespaces.

Avoiding conflicts

In Java/C# languages, namespaces are intended to avoid conflicts between names in different parts of class libraries. You may have class called "Watcher" in 5 different places in namespace hierarchy in C#. In C++, if you have same named classes occurring in your library then you put inside another class instead of creating namespaces. Such nested classes are all fine and encouraged and in fact the syntax also treats as if class is a namespace using :: operator.

How much nested namespaces should be?

Popular libraries like Boost, Eigen and of course, STL provides good examples. these libraries typically have pretty much everything stuffed in to one namespace like std:: or boost:: or eigen::. Few components get their own namespace like std::ios or boost:filesystem. There is no consistent rules around when to use second level but it seems large or separately developed/maintained or optional components typically get their own namespaces. The third level is even more rare. Generally I use the structure company::project and for large independently usable subsystem of projects company::project::component.

Avoiding conflicts in external libraries

Now the big question: What if you get two libraries from two different people which has exact same namespaces and classes? This situation is fairly rare because most people tend to wrap their libraries at least in their project's name. Even if project names are same, its even rarer that you end up using libraries from both. However sometimes bad decisions are made for project names (ahm... "metro", "apollo" ...) or even namespaces are just not used at all. If that happens, you wrap #include for either or both libraries in to a namespace and conflict is resolved! This is one reason why people don't bother too much about conflicts because resolving them is trivial. If you follow the practice of using company::project then conflicts become super rare.

Differences in languages

Although C++ provides using namespace statement just like C#, its generally considered a bad practice to "import" everything in your own namespace. The reason for this is that a header can contain lots of "bad" stuff including redefining things that can totally surprise you. This is quite unlike C#/Java where you only get clean public interface when you do equivalent of using namespace. (side note: in C++ you can achieve the same thing by using Pimpl pattern but its usually too much of extra plumbing and few libraries actually do it). So you almost never want to do using namespace. Instead you do typedefs (or using name =) for what you actually want to use. This again makes deeply nested namespaces impractical to use.

Organizing code

In Java/C#, people tend to organize code in folders a lot. Typically as folder grows more than 20 or even 10 files, people would start thinking about folders. In C++, things are more diverse but for many large projects flatter directory structures are preferred. For example, standard library's std folder has 53 files and Facebook's folly project seems to go same route. I think one reason for this probably is the fact Java/C# folks use visual IDEs more and use mouse scrolls in folder navigation as opposed to console where you can use wild cards to find file in flat structure. Also C++ programmers absolutely don't shy away from putting multiple classes in single file and naming file as logical unit instead of same as class name unlike in C# or Java. This makes compilation faster which is very important for large projects. While there is no language-level requirement for having its own namespace for each folder many C++ developers prefers to assign its own namespace to each folder and keep folder hierarchy 2 or less levels deep.

Possible exception

In C++ you can refer to A::B::C::D as just C::D if you are already inside A::B. So if you have private code or less used classes that you want to push further down then you might do so while still keeping your own relative depth to 2 or so. In this case, you might also want to create folder for each level just so file locations are predictable. In general, there are no gold standards in this area but you do not want to go overboard with deeply nested namespaces mimicking C#/Java.

Related

Community
  • 1
  • 1
Shital Shah
  • 63,284
  • 17
  • 238
  • 185
0

You can have nested namespaces in C++.

They don't work the same as in java, though, obviously. Java packages are really much better defined and there is no real static init weirdness. With C++ namespaces are helpful but still have a fair bit of danger involved.

0

In C++, the basic unit of design and implementation is the class, not the namespace. Namespaces were intended as a means of preventing name clashes in large libraries, not for expressing concepts.

Classes have several advantages over namespaces:

  • they can have constructors and destructors
  • they can have private members
  • they cannot be re-opened

However, I would look twice at any deeply nested relationship. That is really not a good way of designing software, and leads to unreadable code, whether you juse classes or namespaces.

  • 1
    I think you’re comparing the wrong units. Packages are much more like header files in C++ than like classes. The basic unit of modularity in C and C++ is header files and compilation units, not classes. – Konrad Rudolph Jan 21 '10 at 09:56
  • 1
    "they cannot be re-opened" - some would see that as a disadvantage ;-) – philsquared Jan 21 '10 at 09:57
  • @Konrad - I'd be careful about comparing header files with modules. Header files are very much a pre-processor thing. If anything the most closely corresponding entity we have right now is the translation unit (cpp file) - although the symbols *are* usually exported via header files - but that is not a necessity – philsquared Jan 21 '10 at 09:59
  • @Phil You are not suggesting C++ embraces duck typing, I hope! –  Jan 21 '10 at 10:00
  • @Neil - where do you get that idea from? – philsquared Jan 21 '10 at 10:02
  • @Neil - oh, my "reopen classes" comment. I wasn't coming from the duck-typing angle (although it's a step in that direction) - just that it's often useful to be able to add to an existing class on an ad-hoc basis. I was dubious of the concept until I started using extension methods in C# and categories in Objective-C - both of which do it within a static-typing concept - and it leads to some neat solutions. – philsquared Jan 21 '10 at 10:08
  • @Neil... basic unit of design/OO is the class in all the other languages I mention too. In fact more so, since Java especially prevents procedural programming which C++ allows. – Mr. Boy Jan 21 '10 at 10:11
  • I don't think that class and namespaces are comparable entities at any level. Class is an OO concept, while namespace is a more general concept. You can have OO without namespaces, and you can have namespaces without OO. Namespaces (at least to me) are not just a name collision avoidance tool, but rather carry semantic information: they group related concepts together. The difference being that a class models an entity, and namespaces models groups of entities. – David Rodríguez - dribeas Jan 21 '10 at 10:36
  • I don't believe in the pure'OO paradigm, and in particular in 'utility classes' that synthetically bind stateless operations within a non-instantiable class... if they are completely stateless operations then they are better modeled with free functions, and grouping related operations into namespaces tells you that while they are free functions they are also related, and they relate to whatever the namespace name is (I am assuming that the namespace has a proper identifying name). – David Rodríguez - dribeas Jan 21 '10 at 10:39
  • @David I'm not sure they *carry* semantic information. They can be used to partition the namespace *along the lines of* groups of related concepts - but that's down to programmer discipline to maintain. – philsquared Jan 21 '10 at 10:40
  • @David - stateless classes are necessary in some cases, such as when you need a templated type for the whole "group" – philsquared Jan 21 '10 at 10:41
  • @Phil: I completely agree on the *carry* semantic information. I should have worded as 'it allows the programmer to group elements semantically' or something in that line. Then, on the 'stateless classes', well I was talking specifically about the concept of 'utility class' in OO, that refers to classes that just hold some utility functions together. There are cases where stateless classes make sense: traits for meta programming, and even in some cases a regular class can be stateless and still make sense as an entity, but those are not 'utility classes'. – David Rodríguez - dribeas Jan 21 '10 at 11:36
  • BTW, an example of utility class given in Wikipedia is the java Collections class, with only static methods in the line of `binarySearch`, `max`, `min`, `sort`... that are just algorithms applied to its arguments, and whose only relation is that they take 'collections' as arguments. In Java there are no free functions and you must rely in building utility classes to simulate free functions. In C++ you would have a namespace and a set of free (templated) functions. – David Rodríguez - dribeas Jan 21 '10 at 11:43
  • @ David - Agreed - Utility Class, as used here, is just a holder for what would be free functions, if available. – philsquared Jan 21 '10 at 11:47
0

I think there is something missing in the previous answers, and it is one of the reasons I really like C++.

Imagine you are programming a graphical application and suddenly you realize that there is something common among all your widgets. You want all of them to have a new function. What do you do?

1) Edit the base widget class? OK, but most likely you do not have access to it. Maybe there is a licensing problem that prevents you from doing your own modification. Even if you can just do it, if it is something that only makes sense for your project, the authors will not include it in their future release, and upgrading the toolkit will be more painful

2) Create an interface class / multi-inheritance? Depending on your existing code it will be more or less of a pain to update every single class related with a widget. Do this and your code will cost more to maintain because everyone defining a new class must know that they are suppose to inherit from your interface. Becoming dependent of other people discipline is really risky.

The wonderful thing of C++ namespaces here is that you have an extra way to encapsulate stuff within an already existing system. Not only you can encapsulate within already existing libraries that you cannot edit, you can encapsulate similar concepts that you cannot easily insert into your hierarchy of classes/objects.

Java forces you to focus more on a pure OOP design. Sure that I am telling you might be a dirty hack and not elegant, but there are lots of lazy people programming who do not spend time fixing their designs.

SystematicFrank
  • 16,555
  • 7
  • 56
  • 102