November 19, 2022

On Saturday, 19 November 2022 at 09:12:26 UTC, thebluepandabear wrote:

>

That's the point many people have given here which is not convincing him, even though it is quite great.

I think we all know the answer here 😂

IMHO you are both right :)
You are speaking about API compatibility, []() {}() speaks about ABI compatibility. The latter makes sense in long-running production software. So we know that there are no issues in API compatibility but we don't know anything about ABI.

November 19, 2022

On Saturday, 19 November 2022 at 09:14:33 UTC, thebluepandabear wrote:

>

I respectfully disagree... It is not just a couple of keystrokes but rather thousands of lines that can be saved.

Let's just agree to disagree.

Well, as I've already stated.. do it your way for the next 10 years, and I bet you will eventually come to a different point of view ;-)

if you're just a hobyist programmer, then you're really free to do as you please.

but if you are a software engineer employed by a company, within a team of other software engineers, then you have to a have framework that you all work against.

anyone who says otherwise, doesn't know what they're talking about.

In my team, 'classes' do not have public member variables. not ever.

another team is free to do as it pleases of course ;-)

but members of that team will have a hard time getting into my team.

November 19, 2022

On Saturday, 19 November 2022 at 09:26:49 UTC, Andrey Zherikov wrote:

>

On Saturday, 19 November 2022 at 09:12:26 UTC, thebluepandabear wrote:

>

That's the point many people have given here which is not convincing him, even though it is quite great.

I think we all know the answer here 😂

IMHO you are both right :)
You are speaking about API compatibility, []() {}() speaks about ABI compatibility. The latter makes sense in long-running production software. So we know that there are no issues in API compatibility but we don't know anything about ABI.

I am too dumb to know what ABI is,does anyone who is more experienced have any info on whether or not this is actually a problem in D?

November 19, 2022

On Saturday, 19 November 2022 at 09:26:49 UTC, Andrey Zherikov wrote:

>

On Saturday, 19 November 2022 at 09:12:26 UTC, thebluepandabear wrote:

>

That's the point many people have given here which is not convincing him, even though it is quite great.

I think we all know the answer here 😂

IMHO you are both right :)
You are speaking about API compatibility, []() {}() speaks about ABI compatibility. The latter makes sense in long-running production software. So we know that there are no issues in API compatibility but we don't know anything about ABI.

no. in C# it breaks ABI. that is why its not acceptable in my team.

I expect it would also break ABI in D.

so again, getters/setters will almost certainly have value, even if you initially see no value in the few extra keystrokes needed to implement them.

the alternative case being presented is to just make class member variables public so clients can set/get them directly .... well... good luck with that.

that's the end of my input on this thread.

November 19, 2022

On Saturday, 19 November 2022 at 09:51:09 UTC, {}() wrote:

>

no. in C# it breaks ABI. that is why its not acceptable in my team.

Every company works differently. Yours are using .net and (I guess) ships dlls so you must care about ABI with existing software. In my company we use static linking so the only ABI compatibility we care about is with libc.

>

I expect it would also break ABI in D.

I'd like to know the answer so I hope someone from D core step in and shed a light on it.

November 19, 2022

On Saturday, 19 November 2022 at 09:51:09 UTC, {}() wrote:

>

...
no. in C# it breaks ABI. that is why its not acceptable in my team.

of course that's not the reason we don't use public member variables in classes.

the reason we don't use them, is because (1) we always anticpiate change including the need to implement (and change) business rules associated with the objects data (using setter/getters), and (2) we always prioritise the stability of the public interface of a class at the time of design.

if neither of those are your concern, in production-level code, I'd be really surprised (and shocked).

November 19, 2022

On Saturday, 19 November 2022 at 03:52:41 UTC, thebluepandabear wrote:

>

Say you want to write 'SET' now whenever someone sets a width/height value for the rect (as an example), and 'GET' when someone gets the width/height value for the rect, what you could do is do this:

class Rect2D {
    int rectWidth;
    int rectHeight;

    int width() {
        writeln("GET");
        return rectWidth;
    }

    void width(int rectWidth) {
        writeln("SET");
        this.rectWidth = rectWidth;
    }

    int height() {
        writeln("GET");
        return rectHeight;
    }

    void height(int rectHeight) {
        writeln("SET");
        this.rectHeight = rectHeight;
    }
}

Honestly, it may not be a magic bullet, but still useful.

Yes, this is what I meant. I did use the UFCS name inaccurately: I believe UFCS means the ability to write y.x(z) in place of x(y, z), and maybe the ability to write y.x = z in place of y.x(z), but it does not mean the ability to omit empty parenthesis in a function call. The latter is what enables getters that don't break the API.

November 19, 2022

On Saturday, 19 November 2022 at 09:26:49 UTC, Andrey Zherikov wrote:

>

On Saturday, 19 November 2022 at 09:12:26 UTC, thebluepandabear wrote:

>

That's the point many people have given here which is not convincing him, even though it is quite great.

I think we all know the answer here 😂

IMHO you are both right :)
You are speaking about API compatibility, []() {}() speaks about ABI compatibility. The latter makes sense in long-running production software. So we know that there are no issues in API compatibility but we don't know anything about ABI.

Yes, this is a good summary. Redefining a raw field as a getter/setter pair keeps the API but breaks the ABI, so in some cases conservative getters/setters can be justified.

Another problem with raw fields:

struct S{int field;}

@safe clientCode()
{   auto s = new S();
    doSomething(&s.field);
}

This will break if S is rewritten as

struct S
{   int field_;
    auto field(){return field_;}
    auto field(int val){return field_ = val;}
}

I though at first that breakage could still be avoided by instead writing

struct S
{   int field_;
    ref field(){return field_;}
}

...but I tested and actually it does not work because in this case &s.field takes the address of the getter function, not the field.

Now, despite all this I don't think it'd be a good idea to write everything to getters/setters just in case. The binary interface issue is frankly secondary: most structs and classes are just compiled along with their client code. And even separately compiled libraries only have to do this if they strive to provide a stable ABI between releases, which is not nearly always the case. Nor needs to be.

But still the pointer problem in the above example stands, so conservative getters/setters are justified in an API that's used widely enough. But probably not for something internal to a ten thousand line long package.

November 19, 2022

On Saturday, 19 November 2022 at 09:49:18 UTC, thebluepandabear wrote:

>

On Saturday, 19 November 2022 at 09:26:49 UTC, Andrey Zherikov wrote:

>

On Saturday, 19 November 2022 at 09:12:26 UTC, thebluepandabear wrote:

>

That's the point many people have given here which is not convincing him, even though it is quite great.

I think we all know the answer here 😂

IMHO you are both right :)
You are speaking about API compatibility, []() {}() speaks about ABI compatibility. The latter makes sense in long-running production software. So we know that there are no issues in API compatibility but we don't know anything about ABI.

I am too dumb to know what ABI is

ABI is short for application binary interface. Where API means how you use another module in source code, ABI means how you would use that module in assembly langauge or machine code.

If two versions of a library have the same ABI, the program using the library does not have to be recompiled, only relinked to the new library (which happens at runtime if it's a dynamically linked library).

It tends to be of less importance in D than in C or C++. First, D modules usually compile quickly enough that premade binaries (which would be hard to keep up to date with the source code headers) don't make sense. Second, DUB standardises the build process so binaries aren't needed for user convenience either. Maybe the most important remaining use case is building a library that can be used from other languages.

November 19, 2022

On Saturday, 19 November 2022 at 10:17:19 UTC, {}() wrote:

>

On Saturday, 19 November 2022 at 09:51:09 UTC, {}() wrote:

>

...
no. in C# it breaks ABI. that is why its not acceptable in my team.

of course that's not the reason we don't use public member variables in classes.

the reason we don't use them, is because (1) we always anticpiate change including the need to implement (and change) business rules associated with the objects data (using setter/getters), and (2) we always prioritise the stability of the public interface of a class at the time of design.

if neither of those are your concern, in production-level code, I'd be really surprised (and shocked).

We don't use public members either in most cases - we use them in simple structs. We have teams that do care and prioritize stability of public interface because they ship their libraries to end-users. Other teams care much less because all their users are internal so they can fix whatever they break.

Regarding ABI compatibility: it's usually driven by what dependencies your software has. In your case (as far as I got) you ship .dll that is used by already deployed software so your library must be ABI compatible with it. In our case, our software has only system-level dependencies like C runtime, WinSocks so we don't have such a thing as ABI incompatibility between different parts of our software but we care about system-level ABI.