June 07, 2022

On Tuesday, 7 June 2022 at 09:09:52 UTC, zjh wrote:

>

On Tuesday, 7 June 2022 at 09:05:36 UTC, Ola Fosheim Grøstad wrote:

>

TLDR; I strongly disagree.

Class encapsulation is a must for ordinary c++ people!

I am «ordinary C++ people». I also learned OOP from the people who created OOP! I should be terribly biased towards Simula's take on «private», but I am not. Why?

Encapsulation is just a reminder. Encapsulation has no effect on the final executable. This is why Beta could take encapsulation out of the language semantics and do it on the level of the language grammar through what they called «the fragment system» (or something like that).

>

I am not an expert. I only know that class encapsulation is very cool, at least more comfortable than module encapsulation.

Pick up a book on language design, it is fun to read about, and you seem interested! Then we can talk more. (Without basic knowledge about language design principles it is easy to reach conclusion that has proven to be not so good).

June 07, 2022

On Tuesday, 7 June 2022 at 09:17:17 UTC, Ola Fosheim Grøstad wrote:

>

Pick up a book on language design, it is fun to read about, and you seem interested! Then we can talk more. (Without basic knowledge about language design principles it is easy to reach conclusion that has proven to be not so good).

What I care about is that the code will not inadvertently destroy my class code .
This is the meaning of encapsulation .
I don't care about other designs.

June 07, 2022

On Tuesday, 7 June 2022 at 09:22:13 UTC, zjh wrote:

>

What I care about is that the code will not inadvertently destroy my class code .
This is the meaning of encapsulation .
I don't care about other designs.

For me, 'minimum encapsulation' is a matter of principle and cannot be changed!
But 'd' does not encourage 'minimum encapsulation'!
Then you talk with me about designing language?

June 07, 2022

On Tuesday, 7 June 2022 at 09:31:20 UTC, zjh wrote:

>

For me, 'minimum encapsulation' is a matter of principle and cannot be changed!

I see. If you have lots of principles then D will be a challenge for you. It is not a very principled language.

>

But 'd' does not encourage 'minimum encapsulation'!
Then you talk with me about designing language?

Not exactly sure what you mean. You can do fine without any formal encapsulation using conventions. A common convention in languages without encapsulation is to prefix private variables with underscore, then let the IDE provide warnings when "encapsulation" is broken.

This works perfectly well in practice. I've never had a problem with it. The reason is that encapsulation is «just a reminder» and that works well unless you insist on being stupid. Stronger encapsulation is only essential if you redesign larger programs or have teams with disloyal programmers who are taking shortcuts.

Encapsulation is not absolute in D, and can never be. You can just cast the pointer to a different type and you'1l get full access to everything from anywhere.

June 07, 2022

On Tuesday, 7 June 2022 at 10:13:35 UTC, Ola Fosheim Grøstad wrote:

>

Encapsulation is not absolute in D, and can never be. You can just cast the pointer to a different type and you'1l get full access to everything from anywhere.

Also interfaces break visibility with joy. If an interface implementer implements one of the func as private, you can still use it, whatever is the call site.

June 07, 2022
On Tuesday, 7 June 2022 at 10:13:35 UTC, Ola Fosheim Grøstad wrote:
>
> This works perfectly well in practice. I've never had a problem with it. The reason is that encapsulation is «just a reminder» and that works well unless you insist on being stupid. Stronger encapsulation is only essential if you redesign larger programs or have teams with disloyal programmers who are taking shortcuts.

I disagree with your assertions here. I don't think you've fully grasped the benefits of encapsulation in terms of decomoposition.

In any case, you simply cannot encapsulate the semantics of an object (within a class definition) in D, since code surrounding it can get at any part of its specification. But wait. There's more. D 'insists' on not giving you the means to protect that encapsulation. D just does not have the language construct to do that - intentionaly, by design even!

Putting the class in its own module does not change this fact - i.e. you still need to ensure there is no other code surrounding it (including unit test), for it to have a kind of pseudo encapsulation.

The simple fact is, that a class in D is a weak type, since violations of its contract from other code in the module, cannot be detected during compilation.

Instead, it deliberately, intentionally, proudly, leaves this important aspect in software development to the programmer(s).
June 07, 2022

On Tuesday, 7 June 2022 at 10:40:41 UTC, Basile B. wrote:

>

Also interfaces break visibility with joy. If an interface implementer implements one of the func as private, you can still use it, whatever is the call site.

Example? This gives an error:

interface I {
	void f();
}
class C : I // error
{
	private void f(){}
}

privifaceimp.d(4): Error: class privifaceimp.C interface function void f() is not implemented

June 07, 2022

On Tuesday, 7 June 2022 at 12:47:36 UTC, forkit wrote:

>

I disagree with your assertions here. I don't think you've fully grasped the benefits of encapsulation in terms of decomoposition.

Hi, the benfits of encapsulation is obvious, but you can encapsulate without having language support. If you want class-private, just choose the convention that "_fieldname" means class-private. Every time you see "obj._fieldname" you will realize that this is not what you want to do. If that is not enough, use static analysis.

The reality is, encapsulation does not have to be in the language at all in order for you to have encapsulation. It can be a mental thing/code review thing, it can be a grammar thing, it can be a linter issue.

Python does not provide in-language encapsulation at all. Yet I encapsulate my classes in Python all the time. And I have external tools to check for it if I want.

Beta did not provide in-language encapsulation at all, but the fragment system for source code composistion did.

This aspect of D does not limit you as a programmer. Memory management issues do, however. How about focusing on stuff that truly matters and that is likely to change?

>

D 'insists' on not giving you the means to protect that encapsulation. D just does not have the language construct to do that - intentionaly, by design even!

There are lots of things D insists on, and this is the least problematic one… How about focusing on things that you cannot fix yourself with an external tool?

If this was to change then the only sensible thing would be to adopt what is common in other languages, but allow "protected" access to module members. This is unlikely to happen, and the last thing D needs is more @noise in the syntax. So the least problematic choice is to keep it as is.

>

The simple fact is, that a class in D is a weak type, since violations of its contract from other code in the module, cannot be detected during compilation.

All C derivatives have weak type systems across the board.

June 07, 2022

On Tuesday, 7 June 2022 at 14:04:27 UTC, Ola Fosheim Grøstad wrote:

>

Hi, the benfits of encapsulation is obvious, but you can encapsulate without having language support. If you want class-private, just choose the convention that "_fieldname" means class-private. Every time you see "obj._fieldname" you will realize that this is not what you want to do. If that is not enough, use static analysis.

The reality is, encapsulation does not have to be in the language at all in order for you to have encapsulation. It can be a mental thing/code review thing, it can be a grammar thing, it can be a linter issue.

Python does not provide in-language encapsulation at all. Yet I encapsulate my classes in Python all the time. And I have external tools to check for it if I want.

What you are speaking here about is encapsulation by convention (naming rules for the members). This is good approach especially when everyone follows it. Unfortunately people don't. They tend to code their own way. As a result, for the languages that don't provide encapsulation (like Python), people started adding corresponding checks to static analyzers/linters to force the encapsulation. So the convention became more complex: in addition to naming rules, now you should also run static analyzer/linter. This means that the code that violates encapsulation is valid but breaks some convention rules.

For the languages that have encapsulation forced by compiler, you have a guarantee that it's not broken. In this case the code that violates encapsulation is not valid and must be fixed.

Just to summarize, both approaches (no encapsulation and forced encapsulation) are equally good. We all have our habits in coding and it doesn't mean that everyone should do the things in the only one way.

As for me, I'd like to see class/struct level encapsulation in D. Let me share my D experience to clarify the benefit. I started writing a (single module) library that can be used by others. At that point I wanted to separate public API from internal code so I used private for everything internal and public for public API. At some point during active development, the module became so large so I decided to convert it to a package and split into logical components (modules). So I can easily enforce clear interaction between logical components by package and private. Now I want to enforce clear interaction between physical components (structs and classes) within a logical component. Ideally, I want to be able to mark specific members as "real" private so nothing else except struct/class itself can access them. This is what I see as a benefit of this feature for me.
Unfortunately, D gives me two options: put every struct/class into its own module (sub module of a logical component), or leave it as is. Since I am not a fan of having dozens of small files (one per struct/class), I decided to leave it as is.

Regarding implementation. I don't like @private as people will be confused a lot with @private<->private. IMHO the ideal solution would be having module to mark module privates and private for real privates but this is not backward compatible. So the better solution might be extending syntax for private having something like private(symbol[, symbol ...]) where symbol is a symbol that has access to the member For example: this means current struct/class; this.foo or <typeof(this)>.foo means foo member in the current struct/class.

June 07, 2022

On Tuesday, 7 June 2022 at 18:07:34 UTC, Andrey Zherikov wrote:

>

What you are speaking here about is encapsulation by convention (naming rules for the members). This is good approach especially when everyone follows it. Unfortunately people don't. They tend to code their own way. As a result, for the languages that don't provide encapsulation (like Python), people started adding corresponding checks to static analyzers/linters to force the encapsulation.

The general convention is to use underscore as a prefix for internals, that is pretty universal across languages and has been so for many decades. I believe even PyCharm will recognize this.

But it is easier to build a linter for D than for Python, so if you want it, then you can build it. You can also use user defined attributes in D if you don't like underscores?

Having a linter-eco system is something all languages will benefit from, so having something worthwhile to trigger people to build their own linters is not necessarily a disadvantage. If people want "@private" badly then it is great if they build a linter that they share with others. If enough people use it then that can trigger inclusion in the language.

This is how languages ought to evolve:

1a. First try a library solution (like OP), if you cannot do it…
1b. …try to build a generator of some sort, if you cannot do it…
1c. …try to build an analyzer of some sort etc…

  1. Collect feedback from users of your solution.

  2. Consider writing a DIP if the solution is working, but would benefit greatly from compiler support.

  3. Find a compiler dev willing to cowrite the DIP.

Then use that as a proof of concept for the DIP. If enough people use your solution when the DIP is evaluated then it obviously will be a much stronger candidate for inclusion!

>

compatible. So the better solution might be extending syntax for private having something like private(symbol[, symbol ...]) where symbol is a symbol that has access to the member

How would users know that this private means something different?

It is very difficult to get good usability as long as most users coming from other languages have a rather firm interpretation of what private means. With the current setup private means «the strongest encapsulation» which at least is somewhat consistent with other languages.

You could introduce internal as a keyword, but that doesn't overcome the confusion of D'internal = C++'private and D'private ≈ C++private&friend.

So no matter what you do, usability will suffer. Thus a breaking change is the only good alternative from a usability POV. And that won't happen in D2.

3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19