Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread via Digitalmars-d-learn
On Saturday, 19 November 2022 at 23:05:30 UTC, thebluepandabear 
wrote:


..


btw. Although this thread has well and truly exhausted it 
usefulness, the question you posed primarly relates to 
encapsulation, and as such, I think Scott Myers provided a 
reasonable answer to your question - more than 2 decades ago:


"Encapsulation is a means, not an end. There's nothing inherently 
desirable about encapsulation. Encapsulation is useful only 
because it yields other things in our software that we care 
about. In particular, it yields flexibility and robustness."


https://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsuhttps://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197



Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread thebluepandabear via Digitalmars-d-learn

On Saturday, 19 November 2022 at 22:57:36 UTC, [] () {} () wrote:
On Thursday, 17 November 2022 at 04:39:35 UTC, thebluepandabear 
wrote:

...
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:




You really should, instead, be debating why your class has 
public member variables.


If you come to the conclusion that those member variables are 
completely ok being public, then making them private and thus 
needing to provide a simple getter/setter for getting/setting 
the raw value, well, that is just equivalent to making them 
public anyway, really.


So have you achieved nothing with that refactoring?

Well, only time (and 100's of users) will tell ;-)

Do I really need a fence around my house... well.. only time 
will tell.


I'm inclined to build the fence anyway.

Though it would be great if didn't need fences.


Ok... thank you.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread via Digitalmars-d-learn
On Thursday, 17 November 2022 at 04:39:35 UTC, thebluepandabear 
wrote:

...
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:




You really should, instead, be debating why your class has public 
member variables.


If you come to the conclusion that those member variables are 
completely ok being public, then making them private and thus 
needing to provide a simple getter/setter for getting/setting the 
raw value, well, that is just equivalent to making them public 
anyway, really.


So have you achieved nothing with that refactoring?

Well, only time (and 100's of users) will tell ;-)

Do I really need a fence around my house... well.. only time will 
tell.


I'm inclined to build the fence anyway.

Though it would be great if didn't need fences.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread via Digitalmars-d-learn

On Saturday, 19 November 2022 at 19:54:59 UTC, Ali Çehreli wrote:

On 11/19/22 01:05, [] () {} () wrote:

> All this because some programmer wanted to save a few key
strokes, or
> did not anticipate change, or did not anticipate the need to
ensure data
> is valid before assigning it, or returning it.
>
> So no. It's not overkill. It's called software engineering.

I disagree. Engineering is about applying different solutions 
to different problems. Blindly following guidelines whether it 
is fit for purpose would be dogmatic, not pragmatic.


Ali


Neither I, nor anyone in my team blindly follows anything, or 
anyone ;-)


What goes on inside an object, is the responsibilty of that 
object.


That's a guideline (i.e. encapsulation) that we accept as being 
an important principle in software *engineering*, for us, and for 
all of the reasons I've mentioned, and so we implement and follow 
it.


Not having that encapsulation would (and has) create major 
problems for us, and our customers.


Again, if you and/or your team have discovered something 
different (i.e. encapsulation is not that important afterall), 
then that's great, for you. But it wouldn't be great for us, or 
our customers, that much I do know.




Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread via Digitalmars-d-learn

On Saturday, 19 November 2022 at 19:59:20 UTC, Ali Çehreli wrote:

..
...
Ali


The 10 years was mentioned, because it was what I learnt over 
that period (well, long before that actually). It wasn't 
mentioned to demonstrate that I have some superior knowledge. 
Object data needs to be protected. It often needs its 
'invariants' altered.


There are far more reasons for inserting getters/setters and 
design stage, than leaving them out at design stage, in order to 
save some keystrokes, or code bloat.


How often do you design your class? How often to users use your 
class, and ask for changes? Better to anticipate change - the 
cost of that is much smaller  at design time.


If you learnt something different over your 30+ years, good for 
you, and your team, and your customers.


But in my experience, public member variables rarely make sense 
in a 'class' type, and I'd put protected in the same principle.


This is not a hard and fast rule. But it makes sense in most 
cases.


Perhaps you can direct me to a software engineering *team* that 
builds *class* library's for a living, and that also use public 
member variables in their classes. Perhaps they can teach me 
something I do not know. I'm happy to learn more.


Your post was mainly about struct types?? This thread is about 
the relevance of getters/setters in a 'class' type.


btw. If you can get away with using public member variables, you 
likely don't need a class type.




Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread via Digitalmars-d-learn

On Saturday, 19 November 2022 at 19:59:20 UTC, Ali Çehreli wrote:

On 11/19/22 01:43, [] () {} () wrote:

> do it your way for the next 10 years, and
> I bet you will eventually come to a different point of view
;-)

Hm... I am responding without reading the rest of the thread so 
I don't know whether you've mentioned the 10 years more but 
here it goes: I hope 11 years will be sufficient to stop 
following guidelines blindly. Especially this specific one 
where a posted video has shown how wasteful it can be.




You mention your 30+ years of programming, but at the same time, 
point out how 'correct' that one-sided rant is in that video.


I'm confused ;-)



Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Sergey via Digitalmars-d-learn

On Saturday, 19 November 2022 at 04:27:14 UTC, []() {}() wrote:
By making your class member variables public, it is not clear 
whether you forgot that you needed to validate incoming and 
outgoing values, or whether you don't need to do this (not 
ever).


If you did it because of the former, you're fired ;-)

If you did it because of the latter, you're also fired ;-)


Functional programming developers be like: "meh" :)


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Ali Çehreli via Digitalmars-d-learn

On 11/19/22 01:43, [] () {} () wrote:

> do it your way for the next 10 years, and
> I bet you will eventually come to a different point of view ;-)

Hm... I am responding without reading the rest of the thread so I don't 
know whether you've mentioned the 10 years more but here it goes: I hope 
11 years will be sufficient to stop following guidelines blindly. 
Especially this specific one where a posted video has shown how wasteful 
it can be.


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

I am a professional programmer and I do not write public accessors 
blindly. As stated before, they are written only when there is an 
invariant to protect.


> 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.

Agreed.

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

Agreed.

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

I am not working there! :) And what about structs? ;)

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

Thanks. :)

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

Mutual feelings there...

Ali



Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Ali Çehreli via Digitalmars-d-learn

On 11/19/22 01:05, [] () {} () wrote:

> All this because some programmer wanted to save a few key strokes, or
> did not anticipate change, or did not anticipate the need to ensure data
> is valid before assigning it, or returning it.
>
> So no. It's not overkill. It's called software engineering.

I disagree. Engineering is about applying different solutions to 
different problems. Blindly following guidelines whether it is fit for 
purpose would be dogmatic, not pragmatic.


Ali



Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Ali Çehreli via Digitalmars-d-learn

On 11/18/22 20:13, [] () {} () wrote:

> after 10 years of doing all that, you may well come to the conclusion
> that public member variables are not such a great idea afterall ;-)

It depends. Majority of my structs are pure data. When there is no 
invariant to protect, then there is no reason to write any accessor.


If 10 years is mentioned to prove a point, I currently have 33 years of 
professional programming experience (37 including pure hobby years), so 
I must be right. ;)


Ali



Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Ali Çehreli via Digitalmars-d-learn

On 11/18/22 19:35, [] () {} () wrote:

> I like to see an example, of a 'class type' with 'public' member
> variables, somehow magically converted into both getter and setter using
> UFCS, without breaking client code.

UFCS was mentioned before in the same context but I think what is meant 
was the D feature where functions can be called without parenthesis.


Let's say, we have a pure data type:

struct Point {
int x;
int y;
}

void clientCode() {
auto p = Point();
p.y = p.x + 42;
}

void main() {
clientCode();
}

It took me 20 years to first think that public access to members 
was extremely wrong to then realize that there may not be any problem 
with it at all. As you said, "business logic" (I prefer "invariants") 
warrants limiting access to members. Without anything to protect, it is 
just extra work for no reason at all. (I fully agree with the posted video.)



Ok, let's say that the business requirements changed and we wanted to 
perform some business logic. Thanks to D's pragmatism, clientCode() does 
not change at all:


struct Point {
int x_;// Rename
int y_;// Rename

auto x() {// Getter
return x_ + y_;
}

auto y(int value) {  // Setter
x_ = value * 2;
y_ = value / 2;
}
}

void clientCode() {
auto p = Point();
p.y = p.x + 42;
}

void main() {
clientCode();
}

There: clientCode() is not broken.

Ali



Re: "Little Scheme" and PL Design (Code Critique?)

2022-11-19 Thread Jack Pope via Digitalmars-d-learn
On Thursday, 17 November 2022 at 22:05:45 UTC, jwatson-CO-edu 
wrote:

[`Atom`](https://github.com/jwatson-CO-edu/SPARROW/blob/main/lil_schemer.d#L66) 
(unit of data), I throw it on the heap and never bother to delete it.  I 
understand that D does GC for me. I am interested in using either [timed 
GC](https://wiki.dlang.org/Memory_Management#Smooth_Operation) or a [free 
list](https://wiki.dlang.org/Memory_Management#Free_Lists) for finer control of 
GC.  Which is best for the application, do you think?



If you wish to automatically de-allocate the oldest atoms, one 
approach might be to put them in a ring buffer. Its size will 
affect the relative time needed for deleting and overwriting the 
oldest elements. You can hard code the size based on 
experimentation or allow ongoing automatic adjustment based on 
some formula.


I think there are some interesting ring buffer packages in the 
DUB registry.


Re: pointer escaping return scope bug?

2022-11-19 Thread Dukc via Digitalmars-d-learn
On Saturday, 19 November 2022 at 15:02:54 UTC, Nick Treleaven 
wrote:

On Saturday, 19 November 2022 at 14:52:23 UTC, ag0aep6g wrote:
That's essentially just a function that returns its pointer 
parameter. So the program boils down to this:


```D
@safe:
int* fp(return scope int* p) { return p; }
void main()
{
int* p;
{
auto lf = new int;
p = fp(lf);
}
assert(p != null); // address escaped
}
```

Which is fine, as far as I can tell. `lf` is not `scope`. And 
when you pass it through `fp`, the result is still not 
`scope`. So escaping it is allowed.


You do get an error when you make `lf` `scope` (explicitly or 
implicitly). So everything seems to be in order.


OK, so how do I make `lf` implicitly scope?


Have the `int*` inside it to point to a local, or assign another 
`scope int*` to it.




Re: pointer escaping return scope bug?

2022-11-19 Thread ag0aep6g via Digitalmars-d-learn
On Saturday, 19 November 2022 at 15:02:54 UTC, Nick Treleaven 
wrote:

OK, so how do I make `lf` implicitly scope?


By explicit/implicit I just meant this:


scope explicit = new int;
int x;
auto implicit = &x;


That's probably not helping with whatever you want to accomplish.


Re: pointer escaping return scope bug?

2022-11-19 Thread Nick Treleaven via Digitalmars-d-learn

On Saturday, 19 November 2022 at 14:52:23 UTC, ag0aep6g wrote:
That's essentially just a function that returns its pointer 
parameter. So the program boils down to this:



@safe:
int* fp(return scope int* p) { return p; }
void main()
{
int* p;
{
auto lf = new int;
p = fp(lf);
}
assert(p != null); // address escaped
}


Which is fine, as far as I can tell. `lf` is not `scope`. And 
when you pass it through `fp`, the result is still not `scope`. 
So escaping it is allowed.


You do get an error when you make `lf` `scope` (explicitly or 
implicitly). So everything seems to be in order.


OK, so how do I make `lf` implicitly scope?


Re: pointer escaping return scope bug?

2022-11-19 Thread Paul Backus via Digitalmars-d-learn
On Saturday, 19 November 2022 at 14:07:59 UTC, Nick Treleaven 
wrote:

Hi,
The following seems like a bug to me (reduced code, FILE* 
changed to int*):

```d
@safe:

struct LockedFile
{
private int* fps;

auto fp() return scope => fps;
}

void main()
{
int* p;
{
auto lf = LockedFile(new int);
p = lf.fp;
}
assert(p != null); // address escaped
}
```
There's no error with -dip1000.
I'll file this unless I overlooked something.


I think this is intended behavior, because you *do* get an error 
if you replace `new int` with a pointer to a stack variable; e.g.,


int local;
auto lf = LockedFile(&local);

The `return scope` qualifier on the method does *not* mean "the 
return value of this method is `scope`". It means "this method 
may return one of this object's pointers, but does not allow them 
to escape anywhere else." In other words, it lets the compiler 
determine that the return value of `lf.fp` has *the same* 
lifetime as `lf` itself.


Since, in your example, `lf` has global lifetime, the compiler 
deduces that `lf.fp` also has global lifetime, and therefore 
there is nothing wrong with assigning it to `p`.


Re: pointer escaping return scope bug?

2022-11-19 Thread ag0aep6g via Digitalmars-d-learn

On 19.11.22 15:07, Nick Treleaven wrote:

Hi,
The following seems like a bug to me (reduced code, FILE* changed to int*):
```d
@safe:

struct LockedFile
{
     private int* fps;

     auto fp() return scope => fps;
}

void main()
{
     int* p;
     {
     auto lf = LockedFile(new int);
     p = lf.fp;
     }
     assert(p != null); // address escaped
}
```
There's no error with -dip1000.
I'll file this unless I overlooked something.


Let me rewrite `fp` as a static method. It's easier (for me) to 
understand what's going on that way:



static int* fp(return scope ref LockedFile that)
{
return that.fps;
}


That's essentially just a function that returns its pointer parameter. 
So the program boils down to this:



@safe:
int* fp(return scope int* p) { return p; }
void main()
{
int* p;
{
auto lf = new int;
p = fp(lf);
}
assert(p != null); // address escaped
}


Which is fine, as far as I can tell. `lf` is not `scope`. And when you 
pass it through `fp`, the result is still not `scope`. So escaping it is 
allowed.


You do get an error when you make `lf` `scope` (explicitly or 
implicitly). So everything seems to be in order.


pointer escaping return scope bug?

2022-11-19 Thread Nick Treleaven via Digitalmars-d-learn

Hi,
The following seems like a bug to me (reduced code, FILE* changed 
to int*):

```d
@safe:

struct LockedFile
{
private int* fps;

auto fp() return scope => fps;
}

void main()
{
int* p;
{
auto lf = LockedFile(new int);
p = lf.fp;
}
assert(p != null); // address escaped
}
```
There's no error with -dip1000.
I'll file this unless I overlooked something.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Andrey Zherikov via Digitalmars-d-learn

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.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Andrey Zherikov via Digitalmars-d-learn
On Saturday, 19 November 2022 at 09:49:18 UTC, thebluepandabear 
wrote:

I am too dumb to know what ABI is


https://en.wikipedia.org/wiki/Application_binary_interface



Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Dukc via Digitalmars-d-learn
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.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Dukc via Digitalmars-d-learn
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:

```D
struct S{int field;}

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

This will break if S is rewritten as

```D
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


```D
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.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Dukc via Digitalmars-d-learn
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.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread via Digitalmars-d-learn

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).


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Andrey Zherikov via Digitalmars-d-learn

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.






Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread via Digitalmars-d-learn
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.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread thebluepandabear via Digitalmars-d-learn
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?


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Andrey Zherikov via Digitalmars-d-learn
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.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Andrey Zherikov via Digitalmars-d-learn
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.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Andrey Zherikov via Digitalmars-d-learn

On Saturday, 19 November 2022 at 09:05:42 UTC, []() {}() wrote:
Once you refactor your class (creating actual private member 
variables and creating getter/setter methods, you are almost 
certainly going to break binary compatability, and when you 
send your update compiler library to your customer, there code 
will stop working - cause they'll have to recompile it against 
the new library.


I think you are speaking about shipping dynamic library to users. 
I think compiler authors can clarify whether introducing 
getters/setters breaks ABI or not. On the other side if it breaks 
then it can be easily checked: create simple program that uses 
dynamic library, then change the latter to use getters/setters 
and run program again without recompiling.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread thebluepandabear via Digitalmars-d-learn
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 😂





Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread via Digitalmars-d-learn
On Saturday, 19 November 2022 at 04:47:57 UTC, thebluepandabear 
wrote:

..
Of course in C# this argument wouldn't exist because you could 
just do `{ get; set; }`, and I really wish D had something 
similar 😂


If D had C#'s 'automatic' property syntax, it would as 
meaningless in D as it is in C# ;-)


If you used such, you would still need to completely refactor 
your class when you decided to implement you business rules 
(within the getter/setter), since you cannot do anything more 
than get and set with auto property.


Once you refactor your class (creating actual private member 
variables and creating getter/setter methods, you are almost 
certainly going to break binary compatability, and when you send 
your update compiler library to your customer, there code will 
stop working - cause they'll have to recompile it against the new 
library.


All this because some programmer wanted to save a few key 
strokes, or did not anticipate change, or did not anticipate the 
need to ensure data is valid before assigning it, or returning it.


So no. It's not overkill. It's called software engineering.


Re: Is defining get/set methods for every field overkill?

2022-11-19 Thread Andrey Zherikov via Digitalmars-d-learn

On Saturday, 19 November 2022 at 04:13:33 UTC, []() {}() wrote:
oh. so i get it now. you have to refactor your class (change 
member variable names and also do it in all places where they 
are used througout the class. then add new methods, overloading 
them in this way and that way, all because you're initial 
design never factored in the possibility of change (or even 
some validation of the vale being returned to the client, or 
validation of value coming from the client).


You are not required to rename everything, just actual members.

D has nice feature to convert `foo.bar` to `foo.bar()` and 
`foo.bar = value` to `foo.bar(value)` that doesn't exist in C/C++ 
for example. This reduces some headache in planning the API ahead.


Let's we have this class and its usage:
```d
class Rect2D {
int width;
int height;

auto area() const { return width * height; }
}

Rect2D rect = new Rect2D();
rect.width = 5;
rect.height = 5;

writeln(rect.area);   // note that this is seamlessly translated 
to rect.area()

```

Then you decided that you want getters/setters so you add them 
without changing anything:

```d
class Rect2D {
int width_;
int height_;

auto width() const { return width_; }
void width(int w) { width_ = w; }

auto height() const { return height_; }
void height(int h) { height_ = h; }

auto area() const { return width * height; }   // no changes 
here - using getters

}

Rect2D rect = new Rect2D();
rect.width = 5;   // no changes here - using setter
rect.height = 5;  // no changes here - using setter

writeln(rect.area);
```

You can also use UFCS instead of class members but it has a 
caveat: plain `width`/`height` won't work within class so you 
have to either use `width_`/`height_` directly or 
`this.width`/`this.height`:

```d
class Rect2D {
int width_;
int height_;

auto area() const { return this.width * this.height; }  // 
UFCS calls to global width() and height() functions

}

// These functions have to be in global scope for UFCS to work
auto width(const Rect2D rect) { return rect.width_; }
void width(ref Rect2D rect, int w) { rect.width_ = w; }

auto height(const Rect2D rect) { return rect.height_; }
void height(ref Rect2D rect, int h) { rect.height_ = h; }

void main()
{
// Still no changes in user code
Rect2D rect = new Rect2D();
rect.width = 5;
rect.height = 5;

writeln(rect.area);
}
```