Live data from Hacker News

C++ Patterns: The Badge

awesomekling.github.io

11–20 of 160 posts

Re: C++ Patterns: The Badge

#11
post #2

A different pattern I have thought of would be to provide an accessor interface object, and certain functionality is limited to be accessible only through that object. Controlling who has access to that interface can be flexible (possibly returning it along with construction, or passing it in at creation time...) Albeit, this is not without overhead, and for that, Badge is actually better, in terms of performance, if…

Pretty sure you described the attorney-client pattern.

Re: C++ Patterns: The Badge

#14
I might be wrong, but doesn't it look like a way to enforce SRP violation? In the provided example we don't only let the device know how to register itself via VFS, but we also make sure there will be no future DeviceManager to do that. Unless we duplicate the entire interface with Badge tag. Am I missing any non-obvious benefits of this approach?

Re: C++ Patterns: The Badge

#15
post #11
post #2

A different pattern I have thought of would be to provide an accessor interface object, and certain functionality is limited to be accessible only through that object. Controlling who has access to that interface can be flexible (possibly returning it along with construction, or passing it in at creation time...) Albeit, this is not without overhead, and for that, Badge is actually better, in terms of performance, if…

Pretty sure you described the attorney-client pattern.

If it is, it's the first time I hear about it. It always gives me a kick when I make up a similar design pattern to some grey beard's invention. Alas, I should read up on those patterns to avoid reinventing stuff and sharing things with people with appropriate names.

Re: C++ Patterns: The Badge

#16
post #5
post #3

How can {} return a Badge object? Some kind of operator overload?

It's bracket initialization of a struct, in this case the struct has no variables - the type is implicit from the method declaration.

While it makes no difference in this case, it's worth noting that Badge is not an aggregate type because it has a user-provided constructor. Therefore the object is value initialized, i.e. the braces are equivalent to 'Badge()'.

edit: what this means is that even if the struct had data members, you couldn't brace initialize it like an aggregate type, and to achieve something syntactically similar, you would need a suitable constructor.

Re: C++ Patterns: The Badge

#17
post #7

I like it but is access restriction really a problem? In my years of C++ programming it always seemed to be a theoretical problem more than something that leads to crashes.

The C++ access restrictions exist solely to teach and enforce proper API usage by other developers.

They're supposed to trigger a reconsideration of the API when a new developer runs into a restriction, but more often in my experience the new developer will just add a new public interface.

Re: C++ Patterns: The Badge

#19
Could you make the badge the last argument and give it a default value, so you don't need the initialization at the function call? It looks a bit strange and would need an explanation for why the empty initialization list is there IMO.

I'm not sure if it would work, cppreference has this to say about default arguments:

> The names used in the default arguments are looked up, checked for accessibility, and bound at the point of declaration, but are executed at the point of the function call

https://en.cppreference.com/w/cpp/language/default_arguments

Re: C++ Patterns: The Badge

#20
post #7

I like it but is access restriction really a problem? In my years of C++ programming it always seemed to be a theoretical problem more than something that leads to crashes.

This solves a chronic architectural maintenance problem in complex C++ code bases, which I've also run into countless times.

Any visible interface, public or private (via friend), will eventually be used by other programmers for other than its intended use case simply because it is there and accessible. For the maintainer of an interface with a single intended purpose, what should be a clean, tidy modification within the scope of its intended use ends up breaking all kinds of unrelated code that the maintainer wasn't even aware of that is using the interface in ways the designer didn't anticipate. It is a common form of architectural rot. Reducing the incidence of this in large code bases is usually enforced by soft means, like sternly worded comments, vigorous policing, etc but that only goes so far. Ideally, an access policy would be in the code itself and enforced by the compiler.

The public/private labels don't address this. If you make things public, the world has the ability to do unseemly things with your interface. If you friend a bunch of classes so they can access private methods, those classes have the ability to do unseemly things with your private implementation details. Both cases embrittle the architecture. What you really want is fine-grained ACLs to class members to document both intent and dependencies.

This method of restricting usage of methods to specific classes at compile time is clever and provides good documentation of design intent, I haven't seen that pattern before. I also would guess that the compiler elides the Badge argument since it is never used.

Post reply on HN