How to use namespaces in structuring a project

Started by
11 comments, last by jillion 7 years, 4 months ago
I know that namespaces are useful to avoid naming conflicts. Like if a user is including three "Biology" projects in their project, then it wouldn't be simple to access specific functions in a certain "Biology" project. However, I don't know how to structure namespaces throughout my project.
Should I put the entire project under one namespace and that's it? Hope exactly would I use namespaces throughout classes etc?
Advertisement

In my experience, there are generally three camps on this. One says that namespaces should never be used as an architectural device, but solely to disambiguate symbols and avoid collisions. Another says that the namespace is a great tool for creating a modular hierarchy. Those in the third camp take no position either way and do just whatever feels right at the time.

So the advice I give to you is: do whatever you'd like. Companies that use C++ will have in-house coding guidelines that will (or should) specify how they want you to use namespaces. On your own time, as there's no One True Way here, you can do as you please. If that means not using namespaces at all, that's fine, too. Though, I do advise that if you're considering releasing a library for general consumption and the user experience is important to you, then you should first take a look at existing popular libraries in that domain to see what they do.

Generally I use namespaces to write libraries for use in other projects. A single multipurpose library (such as STL) could be one namespace, or a single focused library could be.

For example, if you were to write a stand-alone image loading library that reads various file types and provides the data in various formats, that's something that could benefit from a namespace. You could use names freely within your namespace without worrying about creating collisions for your users (even if it's just yourself).

Within a single monolithic project namespaces are generally not necessary. I'd go as far as to say that if you're having name collisions with yourself then it's probably a code smell.

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.
So when working with others there will be guidelines so I don't need to worry about it.
And in my own projects, let's say I have code that may or may not have code that will be reused elsewhere out even turned into a public library, I should just put the whole project under one namespace but never for anything else such as classes etc?

I have code that may or may not have code that will be reused elsewhere out even turned into a public library, I should just put the whole project under one namespace but never for anything else such as classes etc?
Euhm, I think no.

Putting everything in a single name space, is just like having everything at the global name space, except you write "namespace Foo { ... };" around all code (the syntax may be wrong, but I hope it's clear wrapping a name space around all code isn't doing much). It does avoid name clashes with the now-empty global name space though :)

Instead, don't consider code to be static.

You should use a name space for a well-defined part, such as a library that is being used at several places. However, don't do that until it actually is a library. That takes work. Just taking "random" existing code, and declaring "this is a library now" is unlikely to give a nice result. In general, you want to make a clean separation between library code and non-library code, a clean API, generalize some functions, make it complete, unify how you talk to the library in naming of parameters and function names. You want to document the functions, or how one is supposed to use the library. Treat the library as a new entity that has no direct link with how the old code was used before. (A good library should be generally usable, not exactly once in a specific project.)

After having done that, the library code is a proper library, a separate piece of code (with its own name space). Your project now has a lot of duplicated functionality. Fix the project. take out all the duplications, and modify it to talk to the new library, just like you do when you add an external library to your project. (During the cleanup operation, you changed the API slightly, so usually some adaption is required.)

I have code that may or may not have code that will be reused elsewhere out even turned into a public library, I should just put the whole project under one namespace but never for anything else such as classes etc?

Euhm, I think no.

Putting everything in a single name space, is just like having everything at the global name space, except you write "namespace Foo { ... };" around all code (the syntax may be wrong, but I hope it's clear wrapping a name space around all code isn't doing much). It does avoid name clashes with the now-empty global name space though :)

Instead, don't consider code to be static.
You should use a name space for a well-defined part, such as a library that is being used at several places. However, don't do that until it actually is a library. That takes work. Just taking "random" existing code, and declaring "this is a library now" is unlikely to give a nice result. In general, you want to make a clean separation between library code and non-library code, a clean API, generalize some functions, make it complete, unify how you talk to the library in naming of parameters and function names. You want to document the functions, or how one is supposed to use the library. Treat the library as a new entity that has no direct link with how the old code was used before. (A good library should be generally usable, not exactly once in a specific project.)

After having done that, the library code is a proper library, a separate piece of code (with its own name space). Your project now has a lot of duplicated functionality. Fix the project. take out all the duplications, and modify it to talk to the new library, just like you do when you add an external library to your project. (During the cleanup operation, you changed the API slightly, so usually some adaption is required.)

Thanks everyone! You all are really helpful!

So basically:

1. for my own projects (other than libraries), never use namespaces unless I think I need to (which is when exactly?)

2. Use namespaces only when publicly distributing the code by putting the whole project in a namespace and then for classes?

My share;

I'm definately in camp 2, they enable me to structure my codebase and show directly where I need which 'systems'.

In my case a system is a namespace. You can also use VS filters in line with the namespaces.

namespaces1.jpg

namespaces2.jpg

namespaces3.jpg

crealysm11_design_v0.6.jpg

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

So basically:

1. for my own projects (other than libraries), never use namespaces unless I think I need to (which is when exactly?)

2. Use namespaces only when publicly distributing the code by putting the whole project in a namespace and then for classes?

Euhm, I think no.

(And yes, I know I appear to contradict myself, and technically I am, but I mean the above "no" in a different manner.)

Your summary gives me the impression that you're looking for simple rigid rules that you can globally apply. It doesn't work like that.

A programming language gives you a lot of features, and you can basically use them in any way you desire. At best, the manual gives you a few ideas on how some feature is intended to be used, but it does not give hard rules "this is what you should do".

In fact, in software, such rules hardly exist. Instead, the common approach is to find "the best solution I can think of so far" for each feature. You do this by understanding what a feature does exactly (ie what can it solve for me), and by identifying the situations in your work where using the feature is beneficial.

Basically, everybody is using the feature in some way, under the assumption that better solutions exist, you just haven't found them yet. To find better solutions, you should stay critical against how you use a feature, and stop using it if the feature is not beneficial, or adopt new uses if you find it helps. Blindly and rigidly applying some rules because some weirdo at a forum told them, makes you blind for the better solutions when they arrive at your doorstep. ("Oh, this is different than my standard solution, therefore it's bad." doesn't help in finding a better rule set.)

A second consideration in finding a good rule set is to try reduce complexity as much as possible. We have a natural tendency to use everything that we find. All food must be eaten, all pieces of the puzzle must be needed, the entire desk must be cleaned, all tourist attractions must be visited, etc. It's very hard to decide not to use something in some case if that's better.

Like you, I am looking for the best possible solution. In my journey, I have accepted the above rules as useful guidelines for me, for now. However, as I almost never write a library, my current policy mostly says "never use name spaces" to me. I have no idea whether that is a good thing. On the other hand, I have not run into major trouble due to not using name spaces either. As such, I have yet to find a counter-example that fails. When that happens, I think it's time to reconsider my namespace-usage policy. Likewise, if I ever read about a different policy that is not in conflict with my ideas, and it sounds like a good idea, I may just adopt it.

This also how you can deal with your questions. The questions are good ones. Think about them, and find a rule that you see now as "best". Use the name space feature as you have decided, while keeping an open eye for things that fail or things that can be improved on. In time, the questions become useful guidelines that work for you.

Most people use namespaces even for personal projects. Oh, maybe not the C++ construct designed for that purpose, but look at the names of various classes and functions and how they'll often have a prefix or suffix that indicates a common property of the object (savegame_open(), savegame_close() etc). That's all a namespace is, and the C++ namespace construct is just a formalism for doing that (which is why it can be represented in the C linkage domain simply by mangling the object name with a bijective mapping).

I like to have a namespace hierarchy matching my source folder hierarchy. I like that because I can then build a convenience (static) library as a standalone project that gets used with (a) my game (2) unit tests and (iii) tools, each of which is or can be a separate executable entity. The API is in headers namespace with the folders (#include "mygame/world/map.h") that match the object namespace (::MyGame::World::Map). I can create mocks and fakes for testing with similar names. I can filter symbols with regex for visibility (to reduce link time). I can have functions with similar purpose but different domains named appropriately (World::generate(), Character::generate()). Using the C++ facility actually catches some errors for me at compile time this way.

Once you get used to it, you may find the spaghetti method of organization gets harder to navigate by comparison.

Anyway, that's how I do it in my personal projects. At work, my team goes way overboard with namespaces (and cryptic namespace aliases) and multiple levels of indirection and interfaces and abstractions and it's a nightmare to follow logic, so also be careful about taking it too far.

Stephen M. Webb
Professional Free Software Developer

@[member='cozzie'], Thank you for sharing some great images!

Developer with a bit of Kickstarter and business experience.

YouTube Channel: Hostile Viking Studio
Twitter: @Precursors_Dawn

This topic is closed to new replies.

Advertisement