www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.ideas - Limited friend access

reply claptrap <clap trap.com> writes:
limited friend access

Ok everyone around here seems to think "friend classes" were a 
mistake in C++. But I think the reason they are a problematic is 
that they grant access carte blanche. It gives the friend 
unfettered access to everything. It's like giving a friend keys 
to your house, car, credit cars, account logins, power of 
attorney,  when you just want him to feed the cat while you're on 
holiday.

So what about just granting access to specific parts.

private friend(Foo):
// Foo can see what's here
private:
// Foo cant see anything now

private friend(Foo) void doSomething() {} // Foo can see this 
method

So you add "friend(ClassName,ClassName2...)" after an access 
modifier and it applies either just for that declaration, or 
until the next block modifier.

IE, you grant the class in question access only to specific 
parts. You can design a fully encapsulated private API only for 
the friend.

This would negate the need to put everything in one module, while 
also allow much more fine grained API exposure.
Nov 29
next sibling parent reply Peter C <peterc gmail.com> writes:
On Saturday, 29 November 2025 at 22:29:35 UTC, claptrap wrote:
 limited friend access

 Ok everyone around here seems to think "friend classes" were a 
 mistake in C++. But I think the reason they are a problematic 
 is that they grant access carte blanche. It gives the friend 
 unfettered access to everything. It's like giving a friend keys 
 to your house, car, credit cars, account logins, power of 
 attorney,  when you just want him to feed the cat while you're 
 on holiday.

 So what about just granting access to specific parts.

 private friend(Foo):
 // Foo can see what's here
 private:
 // Foo cant see anything now

 private friend(Foo) void doSomething() {} // Foo can see this 
 method

 So you add "friend(ClassName,ClassName2...)" after an access 
 modifier and it applies either just for that declaration, or 
 until the next block modifier.

 IE, you grant the class in question access only to specific 
 parts. You can design a fully encapsulated private API only for 
 the friend.

 This would negate the need to put everything in one module, 
 while also allow much more fine grained API exposure.
Fine-grained, cross-module friends would introduce a complex non-local access graph that would be difficult to understand and maintain. It would be a threat to local reasoning - the most crucial property of a maintainable encapsulation system! Tight coupling belongs locally, inside the D module. A 'Local Grant' model, like scopeprivate provides - in OpenD they call it private(this), is the proper architectural solution here. I think you're targeting the wrong problem. The real problem that needs to be addressed here, lies inside the D module -> a class cannot protect its internals even from its tightly coupled neighbors in the same file.
Nov 29
parent reply claptrap <clap trap.com> writes:
On Saturday, 29 November 2025 at 23:16:35 UTC, Peter C wrote:
 On Saturday, 29 November 2025 at 22:29:35 UTC, claptrap wrote:
 limited friend access
A 'Local Grant' model, like scopeprivate provides - in OpenD they call it private(this), is the proper architectural solution here.
If you want criticise my idea have at it. If you want to waffle about your own pet grievance start your own thread. If the former, then a hard requirement is the classes in separate modules.
Nov 30
next sibling parent Peter C <peterc gmail.com> writes:
On Sunday, 30 November 2025 at 10:15:10 UTC, claptrap wrote:
 On Saturday, 29 November 2025 at 23:16:35 UTC, Peter C wrote:
 On Saturday, 29 November 2025 at 22:29:35 UTC, claptrap wrote:
 limited friend access
A 'Local Grant' model, like scopeprivate provides - in OpenD they call it private(this), is the proper architectural solution here.
If you want criticise my idea have at it. If you want to waffle about your own pet grievance start your own thread. If the former, then a hard requirement is the classes in separate modules.
Fine. Good luck with your proposal ;-)
Nov 30
prev sibling parent reply Peter C <peterc gmail.com> writes:
On Sunday, 30 November 2025 at 10:15:10 UTC, claptrap wrote:
 If you want criticise my idea have at it.
 If you want to waffle about your own pet grievance start your 
 own thread.

 If the former, then a hard requirement is the classes in 
 separate modules.
You opened your DIP idea with: "limited friend access ..Ok everyone around here seems to think "friend classes" were a mistake in C++. But I think the reason they are a problematic is that they grant access carte blanche. It gives the friend unfettered access to everything. It's like giving a friend keys to your house, car, credit cars, account logins, power of attorney, when you just want him to feed the cat while you're on holiday." If you think about it, the D module does exactly that as well, only locally (do you disagree?). So my point was entirely valid as a response, as I'm on board with the same problem you've identified! So why are you critical of C++'s approach and not D's approach? The only difference in D, is that it is more localised.. but it's still grants access carte blanche. That is, in D, classes cannot collaborate via module-private fields, while still protecting sensitive state. It's not about hijacking your thread for a pet grievance. We're actually talking about the exact same problem .. "unfettered access to everything. " If you're 'hard requirement' is that classes be in separate modules, then that suggests to me they don't even need to be accessing each others internal anyway. So why would you want to negate the need to put them in the same module by introducing a complex relationship between classes in different modules, when the D module already provides this shared functionality, albeit, in a carte blanche way. The only useful (unoffical) addition to the D language for my use cases, has been scopeprivate. There is no other addition to the language that has even come close in terms of its usefulness to me. Without it, I would dump D immediately.
Nov 30
next sibling parent reply Kapendev <alexandroskapretsos gmail.com> writes:
On Sunday, 30 November 2025 at 21:36:13 UTC, Peter C wrote:
 On Sunday, 30 November 2025 at 10:15:10 UTC, claptrap wrote:
 The only useful (unoffical) addition to the D language for my 
 use cases, has been scopeprivate. There is no other addition to 
 the language that has even come close in terms of its 
 usefulness to me. Without it, I would dump D immediately.
This is the first time I have heard someone like `private` this much. Clearly we have all been distracted by minor things like [IES](https://dlang.org/spec/istring.html) and [ImportC](https://dlang.org/spec/importc.html). Anyway, about the DIP. Not sure really. I don't use `private` that often to have a good opinion about this.
Nov 30
parent Peter C <peterc gmail.com> writes:
On Sunday, 30 November 2025 at 23:57:06 UTC, Kapendev wrote:
 ..
 This is the first time I have heard someone like `private` this 
 much.
 Clearly we have all been distracted by minor things like 
 [IES](https://dlang.org/spec/istring.html) and 
 [ImportC](https://dlang.org/spec/importc.html).

 Anyway, about the DIP. Not sure really. I don't use `private` 
 that often to have a good opinion about this.
Neither istring nor importc is of any interest to me, personally, although i accept it interests others. As for private, well if you don't need to use private, so be it. But for those of us who see it as an engineering benefit, we do use it.. a lot. Inside a D module, where tightly coupled classes may well exist (and is the best place for them to exist), scopeprivate provides the means to preserve certain class invariants by not explosing those particular parts to other tightly coupled classes in the same module. This results in less accidental or unintentional coupling inside the module. It's actually good engineering - at least that's how I see it. It signals what is internal to the class, and what is shared, within the module. This drastically reduces the surface area of the class that developers need to worry about, making the code easier to read, understand, and use. So, I see both private and scopeprivatte, as providing a core engineering benefit. The alternative in D, without scopeprivate, is "unfettered access to everything.". I had actually suggested that C++ should have 'originally' done more or less what is being proposed by claptrap (although I can't find the forum reference as yet). But the problem claptrap hightlights for C++, is the problem I highlight for D. The only difference between claptrap and myself in this thread, is that I see the problem he is highlighting in C++, as the same problem 'inside' the D module - that is, "unfettered access to everything.". So we're sort of in agreement on what constitutes a problem here, but we're coming at it from very different perspectives and solutions. If something as simple as what scopeprivate cannot make it into 'official' D, after more that a decade of various people pushing for it - [and btw. it is already available in OpenD, as 'private(this) ], then claptraps proposal has ... what...more likelihood of succeeding?? claptrap and I are in agreement about the necessity for controlled sharing. We clearly just have different perspectives on how to solve it.
Nov 30
prev sibling parent reply claptrap <clap trap.com> writes:
On Sunday, 30 November 2025 at 21:36:13 UTC, Peter C wrote:
 On Sunday, 30 November 2025 at 10:15:10 UTC, claptrap wrote:

 The only useful (unoffical) addition to the D language for my 
 use cases, has been scopeprivate. There is no other addition to 
 the language that has even come close in terms of its 
 usefulness to me. Without it, I would dump D immediately.
LMFAO really? That is absolutely hilarious! **THATS** the killer feature you cant live without???
Nov 30
parent reply Peter C <peterc gmail.com> writes:
On Monday, 1 December 2025 at 00:18:18 UTC, claptrap wrote:
 On Sunday, 30 November 2025 at 21:36:13 UTC, Peter C wrote:
 On Sunday, 30 November 2025 at 10:15:10 UTC, claptrap wrote:

 The only useful (unoffical) addition to the D language for my 
 use cases, has been scopeprivate. There is no other addition 
 to the language that has even come close in terms of its 
 usefulness to me. Without it, I would dump D immediately.
LMFAO really? That is absolutely hilarious! **THATS** the killer feature you cant live without???
yep. It's how I write code - share what I need, protect what I must, and expose only what makes sense.
Nov 30
parent reply claptrap <clap trap.com> writes:
On Monday, 1 December 2025 at 05:11:02 UTC, Peter C wrote:
 On Monday, 1 December 2025 at 00:18:18 UTC, claptrap wrote:
 On Sunday, 30 November 2025 at 21:36:13 UTC, Peter C wrote:
 On Sunday, 30 November 2025 at 10:15:10 UTC, claptrap wrote:

 The only useful (unoffical) addition to the D language for my 
 use cases, has been scopeprivate. There is no other addition 
 to the language that has even come close in terms of its 
 usefulness to me. Without it, I would dump D immediately.
LMFAO really? That is absolutely hilarious! **THATS** the killer feature you cant live without???
yep. It's how I write code - share what I need, protect what I must, and expose only what makes sense.
Hmm i think maybe I still don't understand what you mean, could you explain it again?
Dec 01
parent reply Peter C <peterc gmail.com> writes:
On Monday, 1 December 2025 at 11:52:07 UTC, claptrap wrote:
 On Monday, 1 December 2025 at 05:11:02 UTC, Peter C wrote:
 On Monday, 1 December 2025 at 00:18:18 UTC, claptrap wrote:
 On Sunday, 30 November 2025 at 21:36:13 UTC, Peter C wrote:
 On Sunday, 30 November 2025 at 10:15:10 UTC, claptrap wrote:

 The only useful (unoffical) addition to the D language for 
 my use cases, has been scopeprivate. There is no other 
 addition to the language that has even come close in terms 
 of its usefulness to me. Without it, I would dump D 
 immediately.
LMFAO really? That is absolutely hilarious! **THATS** the killer feature you cant live without???
yep. It's how I write code - share what I need, protect what I must, and expose only what makes sense.
Hmm i think maybe I still don't understand what you mean, could you explain it again?
I'm not sure whether you're being sarcastic here, or whether you're saying that I've already overexplained myself (which is often the case). What's I'm referring to, is 'progressive exposure' - that is, a gradual increase in access to data and functionality, where privacy and encapsulation are carefully maintained at each stage. It's a deliberate design strategy I use, as my default. I do not accept D's defaults. So in D, that means my .d template has to look like this: module mymodule; // safe: private: class MyClass { scopeprivate: } Now any intention to share (either in or outside of this module) will be both progressive and explicit. It's not for everyone, but it works for me.
Dec 01
parent claptrap <clap trap.com> writes:
On Monday, 1 December 2025 at 22:45:42 UTC, Peter C wrote:
 On Monday, 1 December 2025 at 11:52:07 UTC, claptrap wrote:
 On Monday, 1 December 2025 at 05:11:02 UTC, Peter C wrote:
 On Monday, 1 December 2025 at 00:18:18 UTC, claptrap wrote:
 On Sunday, 30 November 2025 at 21:36:13 UTC, Peter C wrote:
 On Sunday, 30 November 2025 at 10:15:10 UTC, claptrap wrote:

 The only useful (unoffical) addition to the D language for 
 my use cases, has been scopeprivate. There is no other 
 addition to the language that has even come close in terms 
 of its usefulness to me. Without it, I would dump D 
 immediately.
LMFAO really? That is absolutely hilarious! **THATS** the killer feature you cant live without???
yep. It's how I write code - share what I need, protect what I must, and expose only what makes sense.
Hmm i think maybe I still don't understand what you mean, could you explain it again?
I'm not sure whether you're being sarcastic here, or whether you're saying that I've already overexplained myself (which is often the case). What's I'm referring to, is 'progressive exposure' - that is, a gradual increase in access to data and functionality, where privacy and encapsulation are carefully maintained at each stage. It's a deliberate design strategy I use, as my default. I do not accept D's defaults. So in D, that means my .d template has to look like this: module mymodule; // safe: private: class MyClass { scopeprivate: } Now any intention to share (either in or outside of this module) will be both progressive and explicit. It's not for everyone, but it works for me.
Genius!
Dec 01
prev sibling next sibling parent reply Peter C <peterc gmail.com> writes:
On Saturday, 29 November 2025 at 22:29:35 UTC, claptrap wrote:
...
 This would negate the need to put everything in one module, 
 while also allow much more fine grained API exposure.
To back up my previous post: What D really needs, is fine grained API exposure inside the module itself, not across modules. - Use scopeprivate for sensitive state that must remain strictly class‑internal. - Use private for module‑level cooperation between closely related classes. - Use public for safe, external APIs. The **principle**: - share what you need, protect what you must, and expose only what makes sense. I believe this would make the D module a far more suitable enclosure for strongly coupled types. Without scopeprivate, D forces developers into either the C++ friend‑like problem of overexposed internals, or awkward design contortions with extra modules. I am really surprised there isn't more demand for this. --- class Point { // sensitive state: only Point itself can access these.. scopeprivate { int x; int y; } // module-private: PointColor can access these.. private { int cachedMagnitude; } public { this(int x, int y) { this.x = x; this.y = y; cachedMagnitude = x * x + y * y; } int magnitude() { return cachedMagnitude; } void describe(PointColor pc) { // Access PointColor's module-private label writeln("Point(", x, ", ", y, ") has color label: ", pc.label); } } } public class PointColor { // sensitive state: only PointColor itself can access these.. scopeprivate { int r, g, b; } // module-private: Point can access these.. private { string label; } public { this(int r, int g, int b, string label) { this.r = r; this.g = g; this.b = b; this.label = label; } void colorizePoint(Point p) { // Use Point's module-private cachedMagnitude int brightness = p.cachedMagnitude % 256; writeln("Colorizing Point with brightness ", brightness, " using color (", r, ", ", g, ", ", b, ") and label ", label); } } }
Nov 29
parent reply Sergey <kornburn yandex.ru> writes:
On Sunday, 30 November 2025 at 05:29:57 UTC, Peter C wrote:
 What D really needs, is fine grained API exposure inside the 
 module itself, not across modules.
No thanks.
Nov 30
parent Peter C <peterc gmail.com> writes:
On Sunday, 30 November 2025 at 09:30:22 UTC, Sergey wrote:
 No thanks.
Thanks, for the thoughtful and well-reasoned response.
Nov 30
prev sibling next sibling parent reply Peter C <peterc gmail.com> writes:
On Saturday, 29 November 2025 at 22:29:35 UTC, claptrap wrote:
 ..
 So what about just granting access to specific parts.
So you want 'encapsulation with selective sharing'. Am I correct? As you've highlighted, you cannot have this in C++, because once you make class B a friend of class A, you've explicitly allowed B to access *ALL* of A's private members. The above is *exactly* the same within the D module. That is, the C++ friend concept has already been imported into D - it's just that it is scoped to the module. I'm troubled by the engineering consequences of your proposal to share selected private members with classes in another module. D deliberately avoids these engineering consequences by enforcing private to be private-to-the module. Any attempt to share even 'selected' private members with classes in other modules, will mean classes are harder to reason about, in terms what's truly internal vs. external, because 'friend-like' relationships can (and will) scatter across the codebase. Selective sharing of private class members across modules, will create obscure coupling, where class B in another module can depend on the internal representation of class A. If A changes its private layout, B breaks - even though they're supposed to be in separate modules. So no, selective sharing of private members across modules should NOT be allowed, and I reject your proposal. I'm also troubled by the engineering consequences of the status quo in D. That is, the C++ like 'all-or-nothing' friendship inside the D module. What should be enabled, is selective sharing *within* a D module. This solves your issue of wanting selective sharing, rather than the C++'s and D's all-or-nothing approach It also solves my issue of concern to your proposal -> the engineering consequences of obscure coupling. It also solves my other concern -> the engineering consequences of the status quo. So 3 birds to kill here, with one stone. (and no, do NOT stone birds!!!) Two (or more) classes that are tightly coupled, should be allowed to exist in the same module to let them share private members, while still allowing each class to maintain control over that sharing, when needed. This kind of solution would avoid the complexity of managing 'selective' friendship networks, maintain D's clean module boundary, and enable your desire (and mine) for selective sharing, without any negative cost to software engineering. Example code below (to demonstrate this principle): public class A { scopeprivate int secret; // A owns its secret! private int cache; // shared within module public int x; // visible everywhere public this(int x, int s) { this.x = x; secret = s; cache = x; } // Controlled exposure of secret public int revealSecret() { return secret; } } public class B { private int[] r; public this(int[] arr) { r = arr; } public void sync(A a) { r[0] = a.x; // public: always accessible r[1] = a.cache; // private: accessible in same module // r[2] = a.secret; // blocked: scopeprivate r[2] = a.revealSecret(); // allowed via A's public method } public void show() { writeln(r); } }
Nov 30
parent Serg Gini <kornburn yandex.ru> writes:
On Monday, 1 December 2025 at 07:42:10 UTC, Peter C wrote:

What is stopping you just use OpenD?
Nov 30
prev sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Saturday, 29 November 2025 at 22:29:35 UTC, claptrap wrote:
 limited friend access

 Ok everyone around here seems to think "friend classes" were a 
 mistake in C++. But I think the reason they are a problematic 
 is that they grant access carte blanche. It gives the friend 
 unfettered access to everything. It's like giving a friend keys 
 to your house, car, credit cars, account logins, power of 
 attorney,  when you just want him to feed the cat while you're 
 on holiday.

 [...]
What, in your opinion, is the problem with needing to put everything in one module in order to grant access?
Dec 01
parent reply claptrap <clap trap.com> writes:
On Monday, 1 December 2025 at 17:47:15 UTC, Atila Neves wrote:
 On Saturday, 29 November 2025 at 22:29:35 UTC, claptrap wrote:
 limited friend access

 Ok everyone around here seems to think "friend classes" were a 
 mistake in C++. But I think the reason they are a problematic 
 is that they grant access carte blanche. It gives the friend 
 unfettered access to everything. It's like giving a friend 
 keys to your house, car, credit cars, account logins, power of 
 attorney,  when you just want him to feed the cat while you're 
 on holiday.

 [...]
What, in your opinion, is the problem with needing to put everything in one module in order to grant access?
In general nothing, in the specific case I have now, I just want to keep platform specific code each in it's own module.
Dec 01
parent reply Peter C <peterc gmail.com> writes:
On Monday, 1 December 2025 at 21:41:38 UTC, claptrap wrote:
 .. I just want to keep platform specific code each in it's own 
 module.
If you want to keep platform-specific code isolated in separate modules, while also maintain a clean design architecture, then you may simply need to do some refactoring. Perhaps the visitor design pattern and/or the dependency injection design pattern, would be a suitable solution here? Remember, that these patterns support the implementation of a well-thought-out design, but good design comes first. You must still combine them with good architectural principles.
Dec 01
parent reply claptrap <clap trap.com> writes:
On Monday, 1 December 2025 at 22:34:51 UTC, Peter C wrote:
 On Monday, 1 December 2025 at 21:41:38 UTC, claptrap wrote:
 .. I just want to keep platform specific code each in it's own 
 module.
If you want to keep platform-specific code isolated in separate modules, while also maintain a clean design architecture, then you may simply need to do some refactoring. Perhaps the visitor design pattern and/or the dependency injection design pattern, would be a suitable solution here? Remember, that these patterns support the implementation of a well-thought-out design, but good design comes first. You must still combine them with good architectural principles.
I don't like those solutions. Do you have any alternatives?
Dec 01
next sibling parent reply Peter C <peterc gmail.com> writes:
On Monday, 1 December 2025 at 23:08:06 UTC, claptrap wrote:
 On Monday, 1 December 2025 at 22:34:51 UTC, Peter C wrote:
 On Monday, 1 December 2025 at 21:41:38 UTC, claptrap wrote:
 .. I just want to keep platform specific code each in it's 
 own module.
If you want to keep platform-specific code isolated in separate modules, while also maintain a clean design architecture, then you may simply need to do some refactoring. Perhaps the visitor design pattern and/or the dependency injection design pattern, would be a suitable solution here? Remember, that these patterns support the implementation of a well-thought-out design, but good design comes first. You must still combine them with good architectural principles.
I don't like those solutions. Do you have any alternatives?
Sure. Just keep on pushing for your 'Limited friend access'... maybe someone will take it seriously.
Dec 01
parent claptrap <clap trap.com> writes:
On Tuesday, 2 December 2025 at 05:40:38 UTC, Peter C wrote:
 On Monday, 1 December 2025 at 23:08:06 UTC, claptrap wrote:
 On Monday, 1 December 2025 at 22:34:51 UTC, Peter C wrote:
 On Monday, 1 December 2025 at 21:41:38 UTC, claptrap wrote:
 .. I just want to keep platform specific code each in it's 
 own module.
If you want to keep platform-specific code isolated in separate modules, while also maintain a clean design architecture, then you may simply need to do some refactoring. Perhaps the visitor design pattern and/or the dependency injection design pattern, would be a suitable solution here? Remember, that these patterns support the implementation of a well-thought-out design, but good design comes first. You must still combine them with good architectural principles.
I don't like those solutions. Do you have any alternatives?
Sure. Just keep on pushing for your 'Limited friend access'... maybe someone will take it seriously.
The last thing I want is for anyone to take anything I say seriously.
Dec 02
prev sibling parent reply Peter C <peterc gmail.com> writes:
On Monday, 1 December 2025 at 23:08:06 UTC, claptrap wrote:
 On Monday, 1 December 2025 at 22:34:51 UTC, Peter C wrote:
 On Monday, 1 December 2025 at 21:41:38 UTC, claptrap wrote:
 .. I just want to keep platform specific code each in it's 
 own module.
If you want to keep platform-specific code isolated in separate modules, while also maintain a clean design architecture, then you may simply need to do some refactoring. Perhaps the visitor design pattern and/or the dependency injection design pattern, would be a suitable solution here? Remember, that these patterns support the implementation of a well-thought-out design, but good design comes first. You must still combine them with good architectural principles.
I don't like those solutions. Do you have any alternatives?
Well, if you're determined to access private members from outside the module in which they are declared, then..yeah ...here's another solution for ya. You'll need to use an older version of the compiler though (prior to 2.079) - or, do some modifications to a more recent version. module myModule; import std.stdio; import myDataModule; // see below as to what that module looks like. void main() { writeln("PrivateKey is: ", myDataModule.secretKey); // fine! } /+ module myDataModule; private string secretKey = "12345-HIDDEN-67890"; +/ // compile: dmd myDataModule.d myModule.d
Dec 01
parent reply claptrap <clap trap.com> writes:
On Tuesday, 2 December 2025 at 07:42:46 UTC, Peter C wrote:
 On Monday, 1 December 2025 at 23:08:06 UTC, claptrap wrote:
 On Monday, 1 December 2025 at 22:34:51 UTC, Peter C wrote:
 On Monday, 1 December 2025 at 21:41:38 UTC, claptrap wrote:
 .. I just want to keep platform specific code each in it's 
 own module.
If you want to keep platform-specific code isolated in separate modules, while also maintain a clean design architecture, then you may simply need to do some refactoring. Perhaps the visitor design pattern and/or the dependency injection design pattern, would be a suitable solution here? Remember, that these patterns support the implementation of a well-thought-out design, but good design comes first. You must still combine them with good architectural principles.
I don't like those solutions. Do you have any alternatives?
Well, if you're determined to access private members from outside the module in which they are declared, then..yeah ...here's another solution for ya. You'll need to use an older version of the compiler though (prior to 2.079) - or, do some modifications to a more recent version. module myModule; import std.stdio; import myDataModule; // see below as to what that module looks like. void main() { writeln("PrivateKey is: ", myDataModule.secretKey); // fine! } /+ module myDataModule; private string secretKey = "12345-HIDDEN-67890"; +/ // compile: dmd myDataModule.d myModule.d
What about just using "package"? Simple no?
Dec 02
parent reply Peter C <peterc gmail.com> writes:
On Tuesday, 2 December 2025 at 08:52:34 UTC, claptrap wrote:
 What about just using "package"? Simple no?
That sounds just like the C++ friends problem to me. I prefer a consistent mental model -> the 'module' is the fundamental boundary of encapsulation in D. With that mental model, it becomes much easier to reason about where and how internals are shared. It also avoids the chaos that will come with loosely coupled, overly shared internals. Shared internals outside of the module, should immediately set off the warning alarm/lights: "Ding Ding! Breach of Modularity! Breach of Modularity!". I think a good design must impose strict control over shared internals. So for me, the best place for controlled sharing of internals, is inside the D module. That is also why I need (and have) scopeprivate. As without that, you do not have controlled sharing inside the module - it's all or nothing.
Dec 02
parent reply claptrap <clap trap.com> writes:
On Tuesday, 2 December 2025 at 22:13:42 UTC, Peter C wrote:
 On Tuesday, 2 December 2025 at 08:52:34 UTC, claptrap wrote:
 What about just using "package"? Simple no?
That sounds just like the C++ friends problem to me. I prefer a consistent mental model -> the 'module' is the fundamental boundary of encapsulation in D. With that mental model, it becomes much easier to reason about where and how internals are shared. It also avoids the chaos that will come with loosely coupled, overly shared internals. Shared internals outside of the module, should immediately set off the warning alarm/lights: "Ding Ding! Breach of Modularity! Breach of Modularity!". I think a good design must impose strict control over shared internals. So for me, the best place for controlled sharing of internals, is inside the D module. That is also why I need (and have) scopeprivate. As without that, you do not have controlled sharing inside the module - it's all or nothing.
I just still don't get it, sounds awfully complicated.
Dec 02
parent Peter C <peterc gmail.com> writes:
On Tuesday, 2 December 2025 at 23:04:58 UTC, claptrap wrote:
 On Tuesday, 2 December 2025 at 22:13:42 UTC, Peter C wrote:
 On Tuesday, 2 December 2025 at 08:52:34 UTC, claptrap wrote:
 What about just using "package"? Simple no?
That sounds just like the C++ friends problem to me. I prefer a consistent mental model -> the 'module' is the fundamental boundary of encapsulation in D. With that mental model, it becomes much easier to reason about where and how internals are shared. It also avoids the chaos that will come with loosely coupled, overly shared internals. Shared internals outside of the module, should immediately set off the warning alarm/lights: "Ding Ding! Breach of Modularity! Breach of Modularity!". I think a good design must impose strict control over shared internals. So for me, the best place for controlled sharing of internals, is inside the D module. That is also why I need (and have) scopeprivate. As without that, you do not have controlled sharing inside the module - it's all or nothing.
I just still don't get it, sounds awfully complicated.
Honestly, if you're just writing code that only you need to understand and maintain, then do whatever you please - I mean really, nobody should care less what you do in that case. And it that is the case, then I couldn't care less ;-) It's when you want others to understand your code, or help maintain it, that you'll need to make better design decisions. Although, even when the code is for you and you alone, good design decisions will benefit you as well, because what you can understand, you can modify and extend. Unfortunately, D's default of everything public, puts good design decisions not at the beginning of your coding, but well after you've started .. if ever. The reason people don't like OOP, are the same reasons people like public by default - i.e. you can just start coding, and think about the important stuff later on... Perhaps you would feel more comfortable, with this as your default .d template: module mymodule; package: class MyClass { package: }
Dec 02