Good news everyone! UPDATE
A proposal has been submitted to C++17 (or C++1z) for a better nested namespaces declaration! Read more
I was browsing over StackOverflow and found a great question regarding nested namespaces in C++. I have always been a huge user of nested namespaces, I had projects that grew to more than 5 nested namespaces.
What really called my attention was Jimmy J answer in which he says:
You're over-using them (and you'll get nothing in return).
Sorry, what? Nothing in return? Really? Well, I don't think this is even close to the truth.
Namespaces can be a documentation tool
Let's say you want to do some queries on the database. You could just type MyProject::Database::
and code completion would already give you sugestions like:
MyProject::Database::DatabaseService
MyProject::Database::Query
MyProject::Database::ResultSet
Now, you know exactly what classes belong to the database domain and you know all of them.
Alternatively, you could prefix classes with a "Database" tag, like:
MyProject::DatabaseService
MyProject::DatabaseQuery
MyProject::DatabaseResultSet
It is okay to do that (and I, myself, do that sometimes), but there are issues with this. Your class names become larger (namespaces makes only their qualifiers larger) and using
and using namespace
keywords become convoluted to use. Say you wanted to alias MyProject::DatabaseResultSet
as ResultSet
and MyProject::DatabaseQuery
as Query
. You know have to declare two definitions:
using ResultSet = MyProject::DatabaseResultSet;
using Query = MyProject::DatabaseQuery;
as opposed to using nested namespaces
using namespace MyProject::Database;
Later, you can even implement database driver inside namespaces MyProject::Database::MySQL
, MyProject::Database::SQLite
, instead of prefixing class names like MyProject::DatabaseMySQLQuery
you nest namespaces like MyProject::Database::MySQL::Query
and you can alias them as you want, and more importantly, with a single line.
Evenmore, if you have enum
s you can use simpler and shorter (yet meaningful!) names. C++11's enum class
solves some of this issues, worth saying, with a nested namespace for the enum.
enum class Color {
RED, GREEN, BLUE
}
myObject.setColor(Color::RED);
as opposed to the old
enum Color {
COLOR_RED, COLOR_GREEN, COLOR_BLUE
}
myObject.setColor(COLOR_RED);
Again, the compiler AND the IDE knows that Color should be and can autocomplete (or provide error messages) that help you a lot.
Things only get worse as the project grows. I don't see it "giving nothing in return".
Namespaces keeps the project modules well defined
Before I start here, I know that you can build a well designed, modular application without nested namespaces, the argument here is: it is better to use them than not.
Look at the Boost libraries, they use namespaces everywhere! First, there's a boost
namespace that wraps all libraries. Next, there's a library namespace such as boost::asio
things easily get as deep as boost::asio::ip::tcp
. That's just beatiful. You know immediatly that you are using TCP/IP. With a little thinking you can even deduce boost::asio::ip::udp
should be UDP/IP. Beautiful, beatiful.
Now, think about a game server, in which you have basically 6 big modules: Model, World, Network, Database and Event. (Note: I have used a similar architecture for my l2jserver2 server, in which world, network, database and event are build on top of a service oriented architecture).
The Event
module dipatches events that are created by World
services. The events are captured Network
services and send the relevant events back to to the client.
Nested namespaces can help you keeping this distinction in place: you should not use the GameServer::World
objects inside your network code. Neither you should use GameServer::Database
inside your network or event modules. You know that if you have any of those declarations inside your code, you have broke the rule.
The bad
The C++ standard comitee had made really hard to use nested namespaces
namespace Namespace1 {
namespace Namespace2 {
namespace Namespace3 {
// ...
}
}
}
This can be hard to setup in every header file you need nested namespaces. I only wish the standard would allow things like Namespace1::Namespace2::Namespace3
inside namespaces declarations.
namespace Namespace1::Namespace2::Namespace3 {
// ...
}
There are several opinions as to how to solve this:
- Skip indentation
- Use the C-Preprocessor to create macros like NAMESPACE1_NAMESPACE2_NAMESPACE3
- Do nothing about it
Solution #1 is ok but Xcode (which is the IDE I use) has issues with identation, if I copy and paste a code, it will paste with proper identation, which is not what I want. Solution #2 is the worst, it does can create subtle problems and you still have to declare the namesapces inside a #define
, which is a tediuous job. This leaves solution #3 as the one I choose -- it is not fast, but it is solid. Every C++ programmer will know what was done.
This difficulty comes from their unique initial purpose: avoid name clashes. I don't believe this should be ignored any longer -- nested namespaces are extremely useful and can help avoid complex or convoluted.
Aside from those small downsides to the nesting of namespaces in C++, I don't see any strong reason not to use them: they keep your code organized, modularized, and more importantly, simple. Remember that nested namespaces have an amazing side-effect: they improve your code documentation, it's kind of like some "auto-documenter" in which people don't have to read pages and pages of documentation to find what classes and methods they should use -- but hey, don't you dare stop writing documentation!