Encapsulation through anonymous namespaces

Started by
23 comments, last by AlanSmithee 9 years, 2 months ago

Hello.

When programming in C++ I often (always) use some method of data encapsulation.

This used to mean defining a class, declaring variables and helper functions private and supplying a public interface of member functions:


class A
{
    public:
        int PublicFunction() { return _privateVariable; }
    
    private:
        int _privateVariable;
};

Any user of this class can create an instance of the class and use its public members.

Should implementation specific details happen to change, the public interface of the class can stay the same. This is all fine.

Howeverm, the more I code, the more I find myself in situations where there only needs to (or only should) ever be one instance of a class.

There are many solutions to this, such as the singleton pattern, classes with static member functions etc.

But somehow these designpatterns have always felt wrong to me. It feels like trying to fit the problem to the solution, where the solution always is some form of a class, be it a singleton or whatever.

This led me to eventually just stop using any "formal" way of data encapsulation in those situations and instead use free functions grouped in a namespace. This approach got rid of the above mentioned "problem", but introduced another problem, which is that variables and methods that should be private were now a part of the public interface*. This is obviously a far bigger issue then not liking a certain design pattern.
Recently, however, I stumbled across anonymous namespaces, which seems to take care of the above mentioned problem:

namespace // private, not accessable from outside this source file
{
    int privateVariable = 54;
 
    int PrivateHelperFunction()
    {
        // can change this to whatever i want without breaking the public interface
        return 123;
    }
}
 
namespace PublicInterface
{
    bool PerformSomeAction()
    {
        // Can access "private" varaibles and functions from here:
        return PrivateHelperFunction() == privateVariable;
    }
}
This seems like a great alternative to using singletons and static classes, and I am using this approach a lot now.
I would like to ask though, if there are any obvious drawbacks or pitfalls that I should be aware of.
One thing that makes me slightly worried is that I have been programming for quite a while in C++ and I never see this coding style being used in examples or even being talked about, which makes me think that there is something "wrong" about it.
potential issues that I can think of:
  • bad (or incorrect) use of namespaces
  • cannot seperate implementation over many source code files (would you even want to do this?)
  • could it make code less reusable maybe?
Thanks in advance for your help!
*if making dll's etc. I guess you could just not export those parts - but this is not the situation I am talking about here
Advertisement
There's nothing wrong with this, and it's what anonymous namesakes are for. BTW, it's the same as:
static int privateVariable = 54;
 
    static int PrivateHelperFunction()
    {
        // can change this to whatever i want without breaking the public interface
        return 123;
    }
This style used to be quite common in C code, and you might even call it an ADT instead of a public interface if you came from those circles...

However, the 'there can only be one' and thus the singleton/global-state is a code smell. Why dictate that the library has to have a single global state and restrain it like that if you don't have to?

BTW, it's the same as:

Not entirely: there's an important difference between names with static linkage and names with extern linkage. For example, templates can only be instantiated with names of extern linkage. Names with extern linkage get involved in link-time resolution, names with static linkage do not (so giving things static linkage where possible can speed up build times, sometimes remarkably).

Names at namespace level (including the :: namespace and the anonymous namespaces) by default have extern linkage. Adding the 'static' keyword gives them static linkage instead.

Still, it is the traditional C way of encapsulating things, used since the early 1970s. There are worse things to reinvent.

Stephen M. Webb
Professional Free Software Developer

Thanks guys!



However, the 'there can only be one' and thus the singleton/global-state is a code smell. Why dictate that the library has to have a single global state and restrain it like that if you don't have to?

This is something I have been thinking about a lot.
For example; in a thread discussing something related, someone talked about using multiple instances of a rendering engine for debugging purposes.
This is a very valid point and I am taking this into consideration.
One approach I am considering is encapsulating all state-related information into a class or struct, say "Renderer", and leave the public interface as free functions (with anonymous "helper" namespace):

namespace // private helper methods and variables (constants etc)
{
    int DrawHelper(const RenderAPI::Renderer& renderer)
    {
        return renderer.GetSomething();
    }
}
 
namespace RenderAPI // public renderer API
{
    class Renderer
    {
        public:
            int GetSomthing() { return _something; }
 
        private:
            int _something;
    };

    Draw(const Renderer& renderer)
    {
        DrawHelper(renderer);
    }
};
Which seems like a good tradeoff to me.. Think this would be overengineering?
Global (mutable) data is generally a bad idea, even if inside an anonymous namespace. This is because your functions then are depending on something that the user can't see, and which may change their behavior in unexpected ways - not to mention that the whole scheme breaks down entirely when threads are involved.

Singletons are also generally frowned upon for the same reasons - there is usually no benefit to having a singleton vs. making an instance of a class and passing it around. And singleton classes can make it easy to create invisible dependencies. They also make it incredibly hard to "mock" for doing testing.

I'm not sure what you're getting at with your example with the renderer though. Classes are designed to be a mechanism which allows you to encapsulate data and modify it only though an approved interface. Your "DrawHelper" function in this case has no purpose.

It is also unclear where you are sticking these anonymous namespaces. They serve little to no purpose in headers where anyone who includes the header gets instant access to them - not exactly "private".

Anyway.

To try to get a little bit on topic - encapsulation is what classes are for. So use classes. Anonymous namespaces are not for encapsulation, they are for avoiding name collisions in translation units (cpp files) that are linked together. Free functions are used whenever you do not need access to a class' private members. Singletons and mutable global state have little to no use in modern C++ - you can almost always make cleaner, more maintainable, and more testable code without them.

Hi, thanks for your input.

Yes, ofcourse the anonymous namespace would be in the source file, and the example was only to show what I mean.

I do understand your reasoning though and I agree that if I am going to use classes or structs, the need for anonymous namespaces more or less goes away.

Global (mutable) data is generally a bad idea, even if inside an anonymous namespace. This is because your functions then are depending on something that the user can't see, and which may change their behavior in unexpected ways - not to mention that the whole scheme breaks down entirely when threads are involved.

True, but the functions themselves are stateless. Free functions is not the same thing as global state. Sometimes it makes a lot of sense to have free functions that are associated with a class but do not belong to it. For instance, you could use free functions to promote encapsulation by doing what AlanSmithee suggested where free functions would be the public interface and the actual class would be a hidden implementation detail, similar to how C's FILE structure is used.

Anonymous namespaces don't really contribute to that, though. As you say, they're more for fixing naming collisions.

Global (mutable) data is generally a bad idea, even if inside an anonymous namespace. This is because your functions then are depending on something that the user can't see, and which may change their behavior in unexpected ways - not to mention that the whole scheme breaks down entirely when threads are involved.


True, but the functions themselves are stateless. Free functions is not the same thing as global state. Sometimes it makes a lot of sense to have free functions that are associated with a class but do not belong to it. For instance, you could use free functions to promote encapsulation by doing what AlanSmithee suggested where free functions would be the public interface and the actual class would be a hidden implementation detail, similar to how C's FILE structure is used.

Anonymous namespaces don't really contribute to that, though. As you say, they're more for fixing naming collisions.


You're basically saying the same thing smile.png I was trying to point out that if you have mutable global state, then a function could use it, thereby changing its behavior based on the changing state that is not passed into the function itself, or necessarily visible to the user.

If a function only operates on public-facing members of a class, then it should not be a part of the class smile.png

If a function modifies or uses modifiable global variables, then it's really a class member of a class you can't see, don't know about, and can't predict.

Another point worth making here is that you seem to have gone down this path because firstly, "everything is a class" (which leads to singleton thinking), and secondly that you had some sense that having non-member functions as part of the interface was somehow icky (and hence wanting to put at least some of them in this anonymous namespace).

You're correct in the first case that "everything is a class" is generally harmful -- its requirement is the biggest part of my distaste for Java -- but you're mistaken that non-member functions are bad or harmful. In fact, you should prefer in general to implement any "method" of a class that you can as a non-member, non-friend function because it decreases coupling, reduces the size of the class's essential interface (which is especially good when that class might be inherited from), and encourages less code duplication. As an example, I have a set of classes for vectors and matrices -- only the operators and usual arithmetic functions that modify the self-same instance (+=, *=, normalize(), etc) are actual member functions, the non-modifying versions of all of those functions are non-member, non-friend functions in the parent namespace, and they're all implemented in terms of the self-modifying operators using the canonical pattern. These non-member, non-friend functions in the same namespace as the class they relate to actually are a part of the class's interface every bit as much as its member functions, and Koenig Lookup ensures that the right thing happens WRT overload resolution and such.

Anonymous namespaces are useful when you want to restrict visibility to the file as you've identified. Its the right tool if that's the thing you want. But in the general case when you have a free function that deals with a particular class, you do want them to live in the same namespace; sometimes you might want to put such functions that are infrequently-used and numerous into a different namespace (such as a 'utilities' namespace) though, or into several namespaces demarcated by different problem domains, although the new inline namespaces feature of C++11 might be a better choice here.

Also as other's have said, any state in an anonomous namespace is still shared state -- its a less-global global, but a global in some measure just the same. It suffers all the same ills as any global, its just that its effects are generally limited to having influence over less code. Be cautious, however, of the fact that just because something has file-scope and can't be directly touched by outside code does not mean its entirely hidden; If a change to its state can be observed indirectly through an interface that's available to outside code, then it still has an affect outside what you would assume its sphere of influence to be (The same is true of private member variables). Again, this is not a bad thing and more-hidden is almost always better than less-hidden -- its just that usually what we want form hiding something is not hiding for its own sake, but hiding as a means of maintaining invariants -- private members achieve this at the granularity of a class, while things with (private) namespace scope achieve this at the level of a namespace, and things with file-scope achieve this at the granularity of a file (which might define a system of otherwise unrelated classes).

throw table_exception("(? ???)? ? ???");

Hi!

Thanks to everyone for contributing, I have learnt a few things.

Ravyne, you are pretty much spot on with everything you say, except me being against the idea of having free functions as a part of the interface - this is actually what I want to achive - sorry if I was unclear. What I did have a problem with was hiding away things that should not be in the public interface. This was a problem to me, because I was not using any form of formal encapsulation (like a class). I was essentially moving from one extreme (using classes for everything) to another extreme (don't use classes at all). I think that was what was making it "not feel right".

So, gathering what has been said in this thread, this is the current solution I am considering: (psuedo code example)


// Public interface of texture manager
namespace TextureManager
{
    class Instance
    {
        public:
            void ChangeTheStateOfThisInstance()
            {
                 ++_secretVariable;
             }
 

            void ChangeTheStateOfThisInstanceTwo()
            {
                 --_secretVariable;
             }
 

            void ChangeTheStateOfThisInstanceThree()
            {
                 _secretVariable *= _secretVariable;
             }
 
         private:
             int _secretVariable = 0;
    };
 
    void IAmAPartOfTheTextureManagerInterface(Instance textureManager)
    {
        textureManager.ChangeTheStateOfThisInstance();
        textureManager.ChangeTheStateOfThisInstanceTwo();
        textureManager.ChangeTheStateOfThisInstanceThree();
    }
};
 
// Usage
int main()
{
    TextureManager::Instance textureManager;
 
    TextureManager::IAmAPartOfTheTextureManagerInterface(textureManager);
 
    // and/or
 
    textureManager.ChangeTheStateOfThisInstanceTwo();
   
    ...
 
    return 0;
}

This feels good to me, and if I am consistent with how I provide the public interface of different functionality, I think it could work well.

I do however realize that not all will agree with the usage of namespaces or the naming conventions used in the above example.

No need for any anonymous namespace here atleast. Should the need arise, it would be another tool in the toolbox though.

Naming conventions aside, I think this is pretty much what Ravyne is talking about?

Any feedback on this approach?

Thanks again!

This topic is closed to new replies.

Advertisement