Re: Passing reference data to class and incapsulation

2014-11-28 Thread bearophile via Digitalmars-d-learn

Uranuz:

Same situation happens when I assign reference data to 
properties.


Someone has suggested to solve this problem with an attribute, 
like owned, that forbids to return mutable reference data owned 
by a class/struct instance.


Bye,
bearophuile


Re: Passing reference data to class and incapsulation

2014-11-28 Thread mark_mcs via Digitalmars-d-learn
Same situation happens when I assign reference data to 
properties. I can check or do something with data at the moment 
of assignment, but I can't control that someone will modify 
using initial reference from outside. So do you copy reference 
data in constructors or properties? Should it be? Or call site 
should be responsible for not escaping reference somewhere 
outside and not modifying these data badly?


I'd probably do one of three things:
*  Clone a private copy;
*  Pass the parameter as an immutable ref;
*  Change the method signature to take a std.typecons.Unique!T
to express the fact that I want transfer of ownership.

Try to encode as much information as you can into the method
signature to describe your intentions.


Re: Passing reference data to class and incapsulation

2014-11-28 Thread Daniel Kozák via Digitalmars-d-learn
V Fri, 28 Nov 2014 06:19:37 +
Uranuz via Digitalmars-d-learn digitalmars-d-learn@puremagic.com
napsáno:

 In D we a several data types which are passed by reference: 
 dynamic arrays, associative arrays. And sometimes we need to pass 
 these reference data to class instance to store it inside. One of 
 the principles of object-oriented programming is incapsulation. 
 So all class data should be only modyfiable via class methods and 
 properties. But I we pass reference data to class (for example as 
 parameter in constructor) we still can change these data from 
 initial code and break some internal logic of class for modifying 
 these data. Example:
 
 class Foo {
  this(int[] b) { bar = b; }
  private int[] bar;
  //Some methods
 }
 
 void main() {
  int[] bar = [1,2,3,4,5];
  Foo foo = new Foo(bar);
  //There I could do some logic with class
  bar[2] = 6; //I modify class without some checks from class
  //And there I might pass *bar* somewhere outside and break 
 incapsulation
 }
 
 Same situation happens when I assign reference data to 
 properties. I can check or do something with data at the moment 
 of assignment, but I can't control that someone will modify using 
 initial reference from outside. So do you copy reference data in 
 constructors or properties? Should it be? Or call site should be 
 responsible for not escaping reference somewhere outside and not 
 modifying these data badly?
 
 There also possible some situations when these data should be 
 shared between different pieces of code (for example different 
 class instance could reference the same memory area). But I think 
 this is not very good and safe approach and should be avoided if 
 possible.
 
 But I think storing reference to class inside another class could 
 be good approach because there could be different type of 
 relations between classes. For plain data types we often have 
 types of relations: *ownership* or *aggregation*. But classes can 
 usualy have more types of relations: *usage* or when one class 
 subscribes for events of another.
 
 Is there some good links to read for these questions that you 
 could advice. After several hours of googling I haven't found 
 good topics about these problems. And I have not enough time for 
 reading big book.

You can wrap type and add suport for copy on write, something like this:

struct CoW(T:E[], E) {
T data;
bool change = false; 
alias data this;

this(T v) {
data = v;
}

this(this) {
change = false;
}

void opIndexAssign(E v, size_t p)
{
if (change is false) {
data = data.dup;
change = true;
}
data[p] = v;
}
}

alias cowIntArr = CoW!(int[]);

class Foo {
this(cowIntArr b) { bar = b; }
private cowIntArr bar;

void printBar() {
writeln(bar);
}

}

void main(string[] args)
{
cowIntArr bar = [1,2,3,4,5];
auto foo = new Foo(bar);
bar[2] = 6;
writeln(bar);
foo.printBar();
}




Re: Passing reference data to class and incapsulation

2014-11-28 Thread Uranuz via Digitalmars-d-learn

On Friday, 28 November 2014 at 08:31:26 UTC, bearophile wrote:

Uranuz:

Same situation happens when I assign reference data to 
properties.


Someone has suggested to solve this problem with an attribute, 
like owned, that forbids to return mutable reference data 
owned by a class/struct instance.


Bye,
bearophuile


Yes. Problem is even if you have property that controls correct 
assignment. If you have getter that returns mutable reference 
type and you try to access some fields of it or apply index 
operator (for arrays or AA) *host* cannot control corectness of 
these assignments or cannot react to these changes (in order to 
do some changes in model).


The way I see is to create my own type of Array for this that can 
notify *host object* about changes so it could refresh the model 
or do some checks.


Another way is to write interfaces in a way so we cant't escape 
uncontrolled references to mutable data.


What do you think of it? Is there any patterns that could help to 
solve such problems?


I think that writing your own type every time when you need to 
enforce consistency and safety is not very good))


Re: Passing reference data to class and incapsulation

2014-11-28 Thread mark_mcs via Digitalmars-d-learn
Yes. Problem is even if you have property that controls correct 
assignment. If you have getter that returns mutable reference 
type and you try to access some fields of it or apply index 
operator (for arrays or AA) *host* cannot control corectness of 
these assignments or cannot react to these changes (in order to 
do some changes in model).


The way I see is to create my own type of Array for this that 
can notify *host object* about changes so it could refresh the 
model or do some checks.


Another way is to write interfaces in a way so we cant't escape 
uncontrolled references to mutable data.


What do you think of it? Is there any patterns that could help 
to solve such problems?


I think that writing your own type every time when you need to 
enforce consistency and safety is not very good))


In my opinion, this is an application design problem; not a 
language design problem.


Getters break encapsulation: they expose an object's internal 
representation to client code. I tend to try and confine them to 
DTOs, which are generally immutable anyway.


If you're worried about encapsulation, why not add a method to 
the object that modifies its own internal state?


Passing reference data to class and incapsulation

2014-11-27 Thread Uranuz via Digitalmars-d-learn
In D we a several data types which are passed by reference: 
dynamic arrays, associative arrays. And sometimes we need to pass 
these reference data to class instance to store it inside. One of 
the principles of object-oriented programming is incapsulation. 
So all class data should be only modyfiable via class methods and 
properties. But I we pass reference data to class (for example as 
parameter in constructor) we still can change these data from 
initial code and break some internal logic of class for modifying 
these data. Example:


class Foo {
this(int[] b) { bar = b; }
private int[] bar;
//Some methods
}

void main() {
int[] bar = [1,2,3,4,5];
Foo foo = new Foo(bar);
//There I could do some logic with class
bar[2] = 6; //I modify class without some checks from class
//And there I might pass *bar* somewhere outside and break 
incapsulation

}

Same situation happens when I assign reference data to 
properties. I can check or do something with data at the moment 
of assignment, but I can't control that someone will modify using 
initial reference from outside. So do you copy reference data in 
constructors or properties? Should it be? Or call site should be 
responsible for not escaping reference somewhere outside and not 
modifying these data badly?


There also possible some situations when these data should be 
shared between different pieces of code (for example different 
class instance could reference the same memory area). But I think 
this is not very good and safe approach and should be avoided if 
possible.


But I think storing reference to class inside another class could 
be good approach because there could be different type of 
relations between classes. For plain data types we often have 
types of relations: *ownership* or *aggregation*. But classes can 
usualy have more types of relations: *usage* or when one class 
subscribes for events of another.


Is there some good links to read for these questions that you 
could advice. After several hours of googling I haven't found 
good topics about these problems. And I have not enough time for 
reading big book.