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




Reply via email to