Earlier quoted context omitted.
Everything public versions poorly when you can't update all clients of your code after you change your implementation. It increases coupling in ways you can't control. It also doesn't work very well with code completion - implementation methods get mixed up with surface API - and usability by third parties suffers. If you're on a team of one, and you own the project for its whole lifetime, then you're fine.
The implicit contract is that anybody who uses m_ "intended to be private" members is responsible for fixing breakage.
C++ Patterns: The Badge
111–120 of 160 posts
Re: C++ Patterns: The Badge
#112Earlier quoted context omitted.
> I started doing everything all-public ala python (struct instead of class by default) with occasionally an m_ prefix for "intended to be private", and I've never looked back. This is the sort of accidental complexity that access specifiers eliminated, but somehow you managed to reintroduce by trying to reinvent the wheel. The 'm_' prefix only means "private member variable, don'access it" to you and you alone, and…
Python has a well-established convention of _underscore for intended-to-be-private members, with no enforcement, and it works fine. Just document your conventions. The horrors of some other programmer using it wrong seem overblown to me. In my IDE in c++ I can quickly refactor m_ to non-m to make it "semantically public" without having to edit header files, change struct packing order / ABI, etc. And most of the time…
Python does not have access modifiers. C++ does. It makes absolutely no sense to write Python code in C++ while entirely oblivious to basic, age-old C++ features just because your background lies somewhere else and you failed or refused to learn even the basics.
And you know what actually works instead of just "working fine"? Having the compiler throw an error if a careless programmer tries to access private variables.
> In my IDE in c++ I can quickly refactor m_ to non-m to make it "semantically public" without having to edit header files, change struct packing order / ABI, etc.
Don't you understand that's completely irrelevant? Just set the private member as private and it does not matter at all which naming convention you follow. Don't you understand that having to do nothing is better than expecting team members to be prescient about your convoluted and absurd naming convention used to avoid best practices?
> Besides, in c++ people can always cast your intricately-protected object to a void pointer and start manipulating it nefarioisly anyway.
Don't you understand that't entirely irrelevant? You're trying to argue that it's ok to ignore best practices such as using member access specifyers, which actually get the compiler to validate the code, if you stick with naming conventions, but arguing that it's technically possible to circumvent compiler checks under some specific circumstances is an absurd statement. Think about it: if you feel that enforcing a coding style is enough to enforce private member access then don't you agree that the same code review that is supposed to enforce your personal style can quite easily catch your hypothetical casts?
Re: C++ Patterns: The Badge
#113Earlier quoted context omitted.
> I also would guess that the compiler elides the Badge argument since it is never used. It's also zero width, so no temporaries, etc.
Problem is, nothing elides the presence of these obtrusive badge parameters in the source code . A few bytes of stack is the least of my concerns on some file system device registration function that is called five times when the system boots. If we imagine a software organization "going to town" with this badge approach so that there are badges all over the code base, it's not hard to imagine how it would be a nuisa…
Re: C++ Patterns: The Badge
#114I used to carefully design my C++ code with public / private / protected / friend (and the pointer-to-impl pattern for "compile time private") but a few years ago I started doing everything all-public ala python (struct instead of class by default) with occasionally an m_ prefix for "intended to be private", and I've never looked back. It's been great, made my programming life much easier. This badge thing is clever,…
> OOP also; I've seen so many crazy class architectures that could just be a handful of plain-old-functions, also, tons of "generic" numerical code with templates everywhere, where the only two possible instantiations are "float" and "double". Some people do really like to add useless complexity everywhere.
Re: C++ Patterns: The Badge
#115While this is a clever little pattern, I'd argue that if you have a method of class X that can only be called from class Y, that is a code smell.
Sometimes, clever little patterns like that are useful to get stuff done in time. However, it that case it definitely smells a lot. Also, the global singleton stinks. To me this is a violation of the Interface Segregation Principle. I think the author went the right way to fix it, but not far enough. He added a parameter to segregate the device registration operations from other operations. It works, but the segregat…
Re: C++ Patterns: The Badge
#116Earlier quoted context omitted.
And you can add yourself a public interface even if all you have is a compiled library, and header files. Flipping a "private:" to "public:" has no effect on the binary compatibility.
> Flipping a "private:" to "public:" has no effect on the binary compatibility. That's not the case on Windows. The access qualifier is part of the mangled name. https://en.wikiversity.org/wiki/Visual_C%2B%2B_name_mangling...
Re: C++ Patterns: The Badge
#117Earlier quoted context omitted.
yeah, python LOC > 5000 try to debugging it while some dude just modified your type instance's guts.
OP's approach works if all dudes involved read the code before chaning it and stay off private parts even if they aren't guarded by the language constructs.
For example, if we develop some framework to be used at multiple sites in the company, we can be 100% sure that at some point someone will assume that anything marked 'public' in the API is fair game to use (which IMO is a reasonable perspective). If they start using internal API's or depend on class internals that are only public just because the language did not provide us with a reasonable way to hide them, at some point we will change them and working systems could break elsewhere. In a similar fashion, misuse of private API's by violating preconditions that are completely opaque to users of your (intended) public API can lead to the worst kinds of bugs and unpredictable runtime failures.
Software development always seems so simple and pragmatic if you don't need to care about other people you have no control over.
Re: C++ Patterns: The Badge
#118Earlier quoted context omitted.
yeah, python LOC > 5000 try to debugging it while some dude just modified your type instance's guts.
OP's approach works if all dudes involved read the code before chaning it and stay off private parts even if they aren't guarded by the language constructs.
And that's only ever possible if you're the only "dude", and your codebase is like <10k loc
Re: C++ Patterns: The Badge
#119This is a typical example of a solution to an artificial, self-imposed problem created by C++'s assumptions. As a programmer, I would feel frustrated to have to figure this out instead of spending time on something a user would actually care about.
In this case, once you know what a Badge is, it’s obvious what it communicates about a function that takes one.
Re: C++ Patterns: The Badge
#120Earlier quoted context omitted.
Doesn't subvert Device badges for me. Complete sample: template class Badge { friend T; Badge() {} }; template Badge FakeBadge() { struct Stub {}; return reinterpret_cast >(Stub()); }; class Device { public: static Badge getBadge() { return Badge (); } }; void needDeviceBadge(Badge badge) { } int main() { needDeviceBadge(Device::getBadge()); // no error needDeviceBadge(FakeBadge ()); // error! return 0; } g++ errors:…
It does, however, work fine if you use a proper "* (Badge * )&stub" cast.