November 22, 2022

On Monday, 21 November 2022 at 23:41:22 UTC, thebluepandabear wrote:

>

But why give a C++ code example? 🤨

It's a D code example and it even can't be compiled by a C++ compiler. Just add the missing main function:

void main()
{
  shared c = new Counter;
  c.incrementCounter;

  c.count = 12345; // haha, this isn't really private in D (unless the class
                   // is moved to a different module in its own personal file)

  writeln(c.displayCounter);
}

The counter member variable isn't really protected from rogue accesses (if these accesses are done by the code in the same source file) and this behavior differs from C++.

November 22, 2022

On Tuesday, 22 November 2022 at 00:46:34 UTC, Siarhei Siamashka wrote:

>

On Monday, 21 November 2022 at 23:41:22 UTC, thebluepandabear wrote:

>

But why give a C++ code example? 🤨

It's a D code example and it even can't be compiled by a C++ compiler. Just add the missing main function:

My bad.

November 22, 2022

On Tuesday, 22 November 2022 at 00:46:34 UTC, Siarhei Siamashka wrote:

>

..
The counter member variable isn't really protected from rogue accesses (if these accesses are done by the code in the same source file) and this behavior differs from C++.

module CounterTest;

//@concrete public synchronized class Counter // if only D has this property.
public synchronized class Counter
{
    static import core.atomic;

    private:
        int count = 0;

    public:
        void incrementCounter()
        {
            if ((count + 1) < 0)
            {
                // you might want to handle this
            }
            else
                core.atomic.atomicOp!"+="(this.count, 1);
        }

        int displayCounter()
        {
            return count;
        }
}

void main()
{
    import std;

    shared Counter c = new Counter;

    for (int i = 0; i < 5; i++)
        c.incrementCounter;

    c.count = 0; // not if your class is a @concrete class
    writeln(c.displayCounter);

}

unittest
{
    shared Counter c = new Counter;
    c.count = 0; // not if your class is a @concrete class
}
November 22, 2022

On Tuesday, 22 November 2022 at 02:11:20 UTC, {}() wrote:

>

maybe: @complete class

insteadof: @concrete class

November 22, 2022

On Tuesday, 22 November 2022 at 02:16:16 UTC, {}() wrote:

>

nevermind ;-) .. seems clear nobody wants something like this in D.

https://forum.dlang.org/post/kbl20f$2np9$1@digitalmars.com

and... 20 years later.... ... .. .

November 22, 2022

On Thursday, 17 November 2022 at 04:39:35 UTC, thebluepandabear wrote:

>

I am creating a TUI library and I have a class with the following constant fields:

class Label : Renderable {
    const string text;
    const TextAlignment textAlignment;
    const Color color;

    this(Dimensions dimensions, string text, TextAlignment textAlignment, Color color) {
        this.dimensions = dimensions;
        this(text, textAlignment, color);
    }

    this(string text, TextAlignment textAlignment, Color color) {
        this.text = text;
        this.textAlignment = textAlignment;
        this.color = color;
    }

    override Cell[] render() const {
        Cell[] cells;

        for (int x = 0; x < 0 + text.length; ++x) {
            cells ~= Cell(Coordinates(x, 0), text[x], color);
        }

        return cells;
    }
}

I am debating whether or not I should add getter methods to these properties. On one hand, it will inflate the codebase by a lot, on the other hand -- in other languages like Java it is a good practice:

class Label : Renderable {
    private const string text;
    private const TextAlignment textAlignment;
    private const Color color;

    this(Dimensions dimensions, string text, TextAlignment textAlignment, Color color) {
        this.dimensions = dimensions;
        this(text, textAlignment, color);
    }

    this(string text, TextAlignment textAlignment, Color color) {
        this.text = text;
        this.textAlignment = textAlignment;
        this.color = color;
    }

    string getText() const {
        return text;
    }

    TextAlignment getTextAlignment() const {
        return textAlignment;
    }

    Color getColor() const {
        return color;
    }

    override Cell[] render() const {
        Cell[] cells;

        for (int x = 0; x < 0 + text.length; ++x) {
            cells ~= Cell(Coordinates(x, 0), text[x], color);
        }

        return cells;
    }
}

It's not a lot of code that has been added but if you have a class with say 10 different fields, adding getter methods would definitely increase the code size by a lot, so what are you guys thoughts on this?

Obligatory note that boilerplate https://code.dlang.org/packages/boilerplate exists for just this reason:

class Label : Renderable {
    @ConstRead
    private const string text_;

    @ConstRead
    private const TextAlignment textAlignment_;

    @ConstRead
    private const Color color_;

    this(Dimensions dimensions, string text, TextAlignment textAlignment, Color color) {
        this.dimensions_ = dimensions;
        this(text, textAlignment, color);
    }

    override Cell[] render() const {
        Cell[] cells;

        for (int x = 0; x < 0 + text.length; ++x) {
            cells ~= Cell(Coordinates(x, 0), text[x], color);
        }

        return cells;
    }

    mixin(GenerateFieldAccessors);
    mixin(GenerateThis);
}
November 22, 2022

On Tuesday, 22 November 2022 at 03:04:03 UTC, {}() wrote:

>

On Tuesday, 22 November 2022 at 02:16:16 UTC, {}() wrote:

>

nevermind ;-) .. seems clear nobody wants something like this in D.

https://forum.dlang.org/post/kbl20f$2np9$1@digitalmars.com

and... 20 years later.... ... .. .

Based on this (not too old) post the idea remains the same and approved by Walter’s experience:
https://dlang.org/blog/2018/11/06/lost-in-translation-encapsulation/
I saw some posts at forum about private-class-scope, but community of core-D is fine with module-unit approach I think.

November 22, 2022

On Tuesday, 22 November 2022 at 10:10:48 UTC, Sergey wrote:

>

Based on this (not too old) post the idea remains the same and approved by Walter’s experience:
https://dlang.org/blog/2018/11/06/lost-in-translation-encapsulation/
I saw some posts at forum about private-class-scope, but community of core-D is fine with module-unit approach I think.

In the interest of 'critical thinking', it's important to point out, that one of the persons in this thread agreeing with the one-sided rant in the video link in this thread, is a co-author of that article.

It also seems, that article is primarly discussing encapsulation.

Encapsulation is not enough, as I've pointed out in this thread.

In D, one can no longer provide a static specification of a class type, let alone rely on the compiler to assure you of the correctness of that specification, in relation to the code surrounding it). Rather, in D, one must always include all the code in the module as being part of the static specification of the class (and the same is true for how ever many classes you have in that module). Even another class could form part of the specification of another class in the same module, even though they are both concrete classes. Wow!

I'm sorry, but that makes no sense to me.

The designers of the other languages mentioned in that article, seem to have the same opinion.

Whatever happened to the principle of least priveledge in D?

Of course, if you're against the us of private, against the use of getters and setters, and against the use of classes, in D, then sure, I can fully understand the decision to completely remove the perimeter for a class type, and hence that article makes complete sense.

Regardless, I fully support the concept that people should always form their own opinion - even on matters as absurd as this ;-)

November 22, 2022

On Tuesday, 22 November 2022 at 20:36:51 UTC, {}() wrote:

>

From a software engineering perspective, what justification can their possibly be, for allowing (by default, and with no language mechanism to prevent it) any code in the same module as this class (including a tightly coupled, but otherwise fully specificed class), to override the specification of this class? How does that enhance encapsulation, as argued in that article?

public synchronized class Counter
{
    static import core.atomic;

    private:
        int count = 0;

    public:
        void incrementCounter()
        {
            if ((count + 1) < 0)
            {
                // you might want to handle this
            }
            else
                core.atomic.atomicOp!"+="(this.count, 1);
        }

        int displayCounter()
        {
            return count;
        }
}
November 22, 2022

On Tuesday, 22 November 2022 at 21:00:58 UTC, {}() wrote:

>

"Being able to declare a “friend” that is somewhere in some other file runs against notions of encapsulation." (This is the motivation for that article it seems).

I completely disagree with the assertion.

C++ Friend notion does not, not by any means, run against the notion of encapsulation.

Sure, it expands the perimeter (i.e. it puts a door in the wall).

But, and this is my point, there is a guard standing at the door. And that guard knows who has been authorised to pass through it. The encapsulation remains. Only its perimeter has been expanded.

One could argue that D's approach is just that. It expands the perimeter to the module level. But there's no guard at the door in D.

Surely, this 'let anyone pass through' design, decreases encapsulation? How could it possibly increase encapsulation, as claimed, by the author of that article?

If there were a means in the language for controlled sharing within a module, that would increase encapsulation.