Jonathan M Davis 
Posted in reply to Ali Çehreli
| On Sunday, July 13, 2025 1:45:01 PM Mountain Daylight Time Ali Çehreli via Digitalmars-d-learn wrote:
> On 7/12/25 5:35 PM, Jonathan M Davis wrote:
> > On Saturday, July 12, 2025 5:55:39 PM Mountain Daylight Time Ali
> Çehreli via Digitalmars-d-learn wrote:
> Anything can be a part of the implementtion without being behind the
> 'private' keyword. For example, I can name those details with an
> underscore and there: they are obviously not part of the public API.
Sure, and then folks use it anyway, and then they complain when you make changes to something that was supposed to be an implementation detail, and it breaks their code.
Practically speaking, if something is public, then someone will use it, and you're going to have to deal with breakage when you change it. And while in principle, you can argue that they shouldn't have used it, because it was undocumented, or it was documented as an implementation detail, or because it had a name starting with an underscore, in practice, it's pretty easy to get into a situation where you can't change the code, just because someone wrote code that used the symbol which was not supposed to be part of the API, and they did it in a code base that you can't afford to break (e.g. because it's in the code base of a company that you can't afford to say no to).
Some code works around this issue by providing header files which don't expose everything, but that doesn't work well with templates, and it can negatively affect optimizations. And when the code has to be exposed in order for someone to use it, it's necessary to have something like private in the language in order to prevent third parties from using symbols which are not supposed to be part of the API.
> > Exposing it means that you have to
> > deal with someone using it, you have to design its API for public
> use, and
> > you can't change it without breaking code.
>
> That's my main problem with this weird feature of programming languages. There are different categories of useful stuff in the languages: arrays, loops, unittest, etc.
>
> And then there is 'private'. Some programmer writes an implementation detail 20 years ago:
>
> 2005: Awesome code written by Alice without 'private'
>
> 2020: Bob found it useful to use some implementation detail
>
> 2025: The original code is changed by Charles
>
> 2025.01: Bob's code broke
>
> 2025.02: Today's Alice doesn't care; Alice of 20 years ago doesn't exist anyway
>
> Is that something a programming language should handle? Please compare it with other useful features of programming languages. They collectively make an engineering tool. 'private' does not contribute.
>
> Access specifiers have nothing to do with the behavior of the program. And I claim their improvement on code maintenance is a fallacy. I followed that gospel without any question for decades. Now I see that it was wasted neural bandwidth.
Well, I completely disagree. Access / Visibility modifiers play a key role in ensuring that third parties don't use code that's not supposed to be part of the public API. And we've already run into problems with Phobos in the past where we had trouble fixing things, because something was made public when it shouldn't have been - and that's made even worse when you have to deal with a stance like Walter's where the policy is that we should basically never be breaking anyone's code even if there's a good reason to.
If there isn't a way in the language to forcibly prevent folks from having access to a symbol, then you have to deal with the fact that someone will use that symbol. And at least with public libraries, that can be a big deal.
Also, in the case of D, private has an effect on overloading. If a symbol is private to an imported module, then it isn't included in any overload set, whereas if private weren't a thing, it would have to be. And even if everyone used underscores for symbols that weren't supposed to be part of the API, you'd still potentially have symbol conflicts from symbols in other modules that happened to have the same name. By having private, none of those symbols leak out, and they don't affect any code using those modules. It helps ensure that those symbols are actually implementation details rather than inadvertently causing problems when a module is imported.
So, the problem extends beyond just folks purposefully using symbols that weren't supposed to be part of the API. It helps ensure that you don't accidentally introduce conflicts into third party code (and thus break that code).
> Aside: I have similar feelings for 'const' because as soon as it interferes with what I'm trying to do, I replace it with 'auto'. Hm? What happened there? What was the value of 'const' then? Say, I made a variable 'const' yesterday but I want to change its value e.g. inside a loop today. Do you think I respect my decision from yesterday and create a separate variable to mutate? No: I replace 'const' with 'auto' and get things done. Seen from this angle, 'const' is another little friend of 'private' that cannot.
I tend to agree that const isn't worth it. I even wrote an article on it several years ago: https://jmdavisprog.com/articles/why-const-sucks.html
In C++, it's kind of a joke, because it doesn't provide real protections, and in D, it's restrictive to the point that it's useless in many situations. In principle, it's a nice idea, since it can prevent mutation when you want to guarantee that something isn't mutated (and thus in theory can prevent bugs), but in practice, it tends to cause a lot of trouble. And I'm not aware of any way for a language to both provide real guarantees with const and have it be useful in the general case (though it can certainly be used successfully in restricted scenarios).
immutable is far more valuable (if nothing else, because it helps with safely sharing data across threads), and const can help make it so that the same code can be used with both mutable and immutable data, but if you can templatize the code, then that works just as well.
Personally, I find a lot more value in private than const (and I almost never use const these days), but obviously, opinions can vary.
> More aside: I "grew up" in C++ circles and did follow many gospels there. It took me a while to see the light on religious guidelines.
>
> A stab at C++: "costexpr everything". Ha ha! My translation: "We continue to fail, so you should follow hundreds of guidelines to write correct programs."
Yeah. The guidelines are often good, but what happens in many cases is that someone learns a guideline and then applies it religiously without really understanding why it was a guideline. So, instead of it being a useful guideline, it effectively becomes a religious commandment, and I definitely agree that that's detrimental.
Guidelines are supposed to be guidelines - tools to help you write better code - not hard and fast rules. But doing that well often requires a good understanding, and too often, guidelines get pushed as rules to try to get less experienced developers to write good code. And while that _can_ help improve code quality, it also often leads to a mess, because the folks doing the coding just followed those rules blindly rather than coding intelligently.
> > private symbols are
> > implementation details which can be changed as necessary so long as those
> > changes don't break the functionality provided by the public symbols. So,
> > from the standpoint of code maintenance, there can be real value in
> keeping
> > symbols private.
>
> The different view point I have is that how such a feature is not necessary and is outside of the useful feature set a programming language provides. I can't imagine that Alice in the scenario above really wants to protect an unknown user in the future. A protection from a slight possibility that what that used found useful may change in the future. This is absolutely the wrong kind of focus on an engineering tool. It smells a lot like what C++ programmers tell each other to do religiously. And I strongly think gospel-style craftspersonship of programming is behind these mostly-unquestioned "features'.
At this point, I feel strongly about private based on personal experience. I can definitely agree that with closed source code, private is less useful (if nothing else, because you then typically control all of the code involved and can change it as needed), but with public libraries, I consider private to be a vital tool to protect myself from third parties using my code in a way that makes it so that I cannot fix or improve my library (or a library like Phobos) without breaking their code. And too often, relying on programmers to simply not use symbols that aren't explicitly part of the public API just doesn't work. Similarly, too often, the politics of the situation makes it so that you can't tell folks that they did something that wasn't supported, so they're on their own. Using private therefore heads off a whole set of issues by making it so that the restriction is more than a suggestion. And it also helps prevent unintended symbol conflicts by making it so that symbols that aren't part of the API aren't actually visible outside of the module.
But at the end of the day, if something is not explicitly intended to be part of a public API, then as far as I'm concerned, it was never intended for anyone else to use, and I have no interest in dealing with anyone else using it or with any of the issues that can come from that. That's why it's private. And if someone wants to use the private implementation for something else, they can (license willing) always just copy the code, at which point any issues are automatically their problem rather than mine.
In any case, from the sounds of it, we're probably just going to have to agree to disagree on this point. I certainly won't claim that everyone is intelligent about using private (e.g. some folks get obsessed with making member variables private and using getters and setters which do absolutely nothing but get or set the variable), but IMHO, it's a valuable tool for preventing folks from using parts of the library which are supposed to be an implementation detail.
- Jonathan M Davis
|