Jump to content
  • Advertisement
Sign in to follow this  
AlanSmithee

Encapsulation through anonymous namespaces

This topic is 1262 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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?

Share this post


Link to post
Share on other sites
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. Edited by SmkViper

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!