On Wednesday, May 1, 2024 5:52:30 AM MDT NotYouAgain via Digitalmars-d wrote:
> No doubt this will create controversy too.. why.. I don't know... but anyway....
>
> Declarations within a D module (other than import declarations)
> are public by default.
> This includes public by default in a class too btw.
>
> Programmers from many of the other major languages will have to deal with this surprise (in addition to the surprise of how private has taken on a completely new meaning in D).
>
> Not discussing private here! We all know what will happen if we do. So don't!
>
> Question 1 - is 'public by default' a sensible default for a language that is aiming to be safe by default?
>
> Here's an interesting article relating to Kotlin, where I believe public is also the default. It kinda sets the stage....
>
> https://discuss.kotlinlang.org/t/kotlins-default-visibility-should-be-intern al/1400
>
> Question 2 - if public is not a sensible default for a language that is aiming to be safe by default, is it too late to change it?
>
> Question 3 - if a change was made, what would become the new default?
>
> Please be respectful in your comments, if you have anything to say.
For the most part, public and private really don't have anything to do with @safe or memory safety. The primary exception would be when an @safe / @trusted public API is being presented, but the internals are doing @system stuff that has to be @trusted.
In such cases, if symbols are accidentally left public rather than private, then @trusted code could be making assumptions that are not valid if any external code accesses the symbols which were supposed to be private. But even then, anything @system which is done with those private symbols will be treated as @system, so the @safety system will prevent you from doing anything that isn't memory safe with those symbols. It's just that if @trusted functions make assumptions about the state of the symbols which are not necessarily valid if external code has access to those members, then @trusted would be treating stuff as @safe when it shouldn't, which could lead to memory safety problems.
So, in a case such as that, having a symbol accidentally marked as public could create @safety issues, but for the vast majority of code, it won't, and so @safety and symbol visibility are largely orthogonal concerns (just not 100% orthogonal).
Rather, I'd say that the bigger problem with public by default is simply that it makes it easier to have symbols that were supposed to be private end up in your public API. Then you can end up in a situation where something that you thought was private is being used by external code somewhere, and when you make a change that should only affect your code's internals, it could break user code.
So, there's definitely an argument to be had that private by default would be better, because then you have a lower risk of accidentally having symbols be part of your public API when you didn't intend for them to be. However, at the same time, it's quite trivial to just slap
private:
at the top of the module if that's a concern. And there are a number of folks who would argue that all symbols should be explicitly marked with public or private anyway (which I'm not a big fan of, but it does work better with maintainability and code reviews when the attributes affecting a symbol are directly on the symbol rather than somewhere else in the file).
Also, it's far more problematic to use
public:
because it will also affect imports, and you don't want to accidentally make imports public. So, having private as the default could lead to more issues with imports, because folks who wanted public on most of their symbols but didn't want to mark them individually would likely be inclined to put
public:
at the top of their module and would then likely run into problems as a result, whereas slapping
private:
at the top of the module isn't error-prone in the same way.
In many respects, I am inclined to think that it would be better for private to be the default (at least as long as public: is changed to not affect imports), but at the same time, in my experience, it's pretty rare that symbols end up being public when they weren't supposed to be, and even when they do, since they're undocumented, it's usually only a problem if someone goes spelunking in the code and starts using undocumented stuff that's public.
Ultimately both public by default and private by default work just fine, and the issues that you get with one or the other usually aren't a big deal. So, I don't think that it's all that big a deal which one a language goes with.
And if we wanted to be particularly concerned about it, then arguably, the correct solution would be to just require that visibility attributes be directly on the symbols to fix the problem, which would be annoying in some cases, but mass-applying attributes often has a tendency to cause problems, and public: in particular can be pretty bad because of how it affects imports.
- Jonathan M Davis
|