Michal, how much work do you estimate it would take us to implement method
modificator solution?

2016-09-07 14:01 GMT+02:00 Michał Brzuchalski <mic...@brzuchalski.com>:

> Hi,
>
> Frozing an immutable object after it's creation is most important feature
> of Immutable Classes.
> Without it you cannot have guarantee it's internal state is consistent as
> it was during creation.
> Having methods access to write is quite dangerous - think about CLosure
> binded to immutable object - there is a way to change internal state of
> such object, and you've broken immutability in it.
>
> Changing object state is reasonable only on clones, because you newer know
> what references to original object.
> There can be cloning objects as they are now - I don't see it usefull, but
> if somebody really want's it, why not.
>
> IMHO providing method modificator for changing object in context of newly
> created clone is the best solution. The keyword for it isn't chosen yet, we
> may discuss it or even vote for it. For now we can call it anyway while
> keeping in mind it may change during voting.
>
>
>
> 2016-09-07 12:43 GMT+02:00 Silvio Marijić <marijic.sil...@gmail.com>:
>
>> @Stephan
>>
>> I am against that any kind of method can make modification on original
>> object.
>>
>> Cloning can be allowed but for this use case where you would pass
>> properties that are changing, we would have to modify syntax of clone
>> On Sep 7, 2016 12:37 PM, "Stephen Reay" <php-li...@koalephant.com> wrote:
>>
>> > Hey Matheiu, Silvio,
>> >
>> > That is my main concern with the inability to clone from outside the
>> > class. I don’t think immutable should cause an error in this situation
>> - if
>> > you really don’t want to allow users to create objects they can’t modify
>> > (which I understand) could clone on an immutable object from outside the
>> > class, simply return the object itself ?
>> >
>> > Re: immutable only externally - yes, as I mentioned I can understand
>> that
>> > would be a deal-break for some. In that situation, I’d be happy with
>> some
>> > way to indicate that a method can make changes. Would this then mean
>> that
>> > such a method could modify the object itself, rather than the clone?
>> >
>> > Cheers
>> >
>> > Stephen
>> >
>> > > On 7 Sep 2016, at 17:09, Mathieu Rochette <math...@rochette.cc>
>> wrote:
>> > >
>> > >
>> > >
>> > > On 07/09/2016 11:28, Silvio Marijić wrote:
>> > >> Hi Stephen,
>> > >>
>> > >> Cloning is disabled at the moment in implementation because you would
>> > end
>> > >> up with a object that you can not change, so you have no use of that.
>> > I'll
>> > >> change that as soon as we find some good solution for handling that.
>> > Your
>> > >> example is not really clear to me. At what point we should
>> unlock/lock
>> > >> object based on your example?
>> > > what would happen if you tried to clone an immutable object, throw an
>> > error ?
>> > > it means that you might have to use reflection to check if the object
>> is
>> > immutable before cloning it. otherwise making a class immutable would
>> be a
>> > BC
>> > >>
>> > >> DateTimeImmutable does not prevent cloning because immutability is
>> > achieved
>> > >> by encapsulation, and we want to get rid of the need of
>> encapsulation in
>> > >> our implementation of immutable objects.
>> > >>
>> > >> Best,
>> > >> Silvio.
>> > >>
>> > >> 2016-09-07 11:05 GMT+02:00 Stephen Reay <php-li...@koalephant.com>:
>> > >>
>> > >>> (Sorry for any dupes, sent from wrong address originally)
>> > >>>
>> > >>> From a developer point of view, I would suggest that a feature
>> should
>> > aim
>> > >>> to be as clear to understand with as little “magic" as possible.
>> > >>>
>> > >>>
>> > >>> If the goal of an immutable class is to allow public properties to
>> be
>> > made
>> > >>> read-only, my expectation would be that:
>> > >>>
>> > >>> - write access to any public property from outside class context,
>> is an
>> > >>> error.
>> > >>>
>> > >>> This seems to be pretty much accepted by everyone
>> > >>>
>> > >>>
>> > >>> - clone still works as expected
>> > >>>
>> > >>> There has been some suggestion that clone $immutableObj should not
>> be
>> > >>> allowed. Unless there is some specific language/engine gain by that,
>> > what
>> > >>> is the point of having this behaviour?
>> > >>> Existing built-in immutable classes (like DateTimeImmutable) do not
>> > >>> prevent cloning, so why should this?
>> > >>>
>> > >>> - regular cloning from within class method(s) is the suggested way
>> to
>> > >>> provide “create a copy of the object with a new value”
>> functionality.
>> > >>>
>> > >>> This example was given before, effectively:
>> > >>>
>> > >>> public function withValue($val) {
>> > >>>         $clone = clone $this;
>> > >>>         $clone->val = $val;
>> > >>>
>> > >>>         return $clone;
>> > >>> }
>> > >>>
>> > >>>
>> > >>>
>> > >>>
>> > >>>
>> > >>>> On 7 Sep 2016, at 13:57, Michał Brzuchalski <
>> mic...@brzuchalski.com>
>> > >>> wrote:
>> > >>>> 06.09.2016 9:13 PM "Fleshgrinder" <p...@fleshgrinder.com>
>> napisał(a):
>> > >>>>> I understand the concerns of all of you very well and it's nice to
>> > see a
>> > >>>>> discussion around this topic. Fun fact, we are not the only ones
>> with
>> > >>>>> these issues: https://github.com/dotnet/roslyn/issues/159
>> > >>>>>
>> > >>>>> On 9/6/2016 6:01 PM, Larry Garfield wrote:
>> > >>>>>> How big of a need is it to allow returning $this instead of
>> $clone,
>> > >>>>>> and/or can that be internalized somehow as well?  With
>> > copy-on-write,
>> > >>>>>> is that really an issue beyond a micro-optimization?
>> > >>>>> I asked the same question before because I am also unable to
>> answer
>> > this
>> > >>>>> question regarding the engine.
>> > >>>>>
>> > >>>>> However, for me it is more than micro-optimization, it is about
>> > >>> identity.
>> > >>>>> final class Immutable {
>> > >>>>>   // ... the usual ...
>> > >>>>>   public function withValue($value) {
>> > >>>>>     $clone = clone $this;
>> > >>>>>     $clone->value = $value;
>> > >>>>>     return $clone;
>> > >>>>>   }
>> > >>>>> }
>> > >>>>>
>> > >>>>> $red = new Immutable('red');
>> > >>>>> $still_red = $red->withValue('red');
>> > >>>>>
>> > >>>>> var_dump($red === $still_red); // bool(false)
>> > >>>>>
>> > >>>>> This is a problem in terms of value objects and PHP still does not
>> > allow
>> > >>>>> us operator overloading. A circumstance that I definitely want to
>> > >>>>> address in the near future.
>> > >>>>>
>> > >>>>> But the keyword copy-on-write leads me to yet another proposal,
>> > actually
>> > >>>>> your input led me to two new proposals.
>> > >>>>>
>> > >>>>> # Copy-on-Write (CoW)
>> > >>>>> Why are we even bothering on finding ways on making it hard for
>> > >>>>> developers while the solution to our problem is directly in front
>> of
>> > us:
>> > >>>>> PHP Strings!
>> > >>>>>
>> > >>>> AFAIK CoW in case of objects would be impossible to implement.
>> > >>>>
>> > >>>>> Every place in a PHP program refers to the same string if that
>> > string is
>> > >>>>> the same string. In the second someone mutates that string in any
>> way
>> > >>>>> she gets her own mutated reference to that string.
>> > >>>>>
>> > >>>>> That's exactly how we could deal with immutable objects.
>> Developers
>> > do
>> > >>>>> not need to take care of anything, they just write totally normal
>> > >>>>> objects and the engine takes care of everything.
>> > >>>>>
>> > >>>>> This approach also has the advantage that the return value of any
>> > method
>> > >>>>> is (as always) up to the developers.
>> > >>>>>
>> > >>>>> (Cloning is disabled and results in an error as is because it
>> makes
>> > no
>> > >>>>> sense at all.)
>> > >>>>>
>> > >>>>> # Identity
>> > >>>>> This directly leads to the second part of my thoughts and I
>> already
>> > >>>>> touched that topic: identity. If we have two strings their binary
>> > >>>>> representation is always the same:
>> > >>>>>
>> > >>>>> var_dump('string' === 'string'); // bool(true)
>> > >>>>>
>> > >>>>> This is the exact behavior one wants for value objects too. Hence,
>> > >>>>> immutable objects should have this behavior since they identify
>> > >>>>> themselves by their values and not through instances. If I create
>> two
>> > >>>>> instances of Money with the amount 10 and the Currency EUR then
>> they
>> > are
>> > >>>>> always the same, no matter what. This would also mean that no
>> > developer
>> > >>>>> ever needs to check if the new value is the same as the existing
>> one,
>> > >>>>> nor does anyone ever has to implement the flyweight pattern for
>> > >>>>> immutable objects.
>> > >>>>>
>> > >>>>> A last very important attribute is that it does not matter in
>> which
>> > >>>>> thread an immutable value object is created because it always has
>> the
>> > >>>>> same identity regardless of it.
>> > >>>>>
>> > >>>>> This could easily be achieved by overwriting the object hashes
>> > >>>>> (spl_object_hash) with something that hashes based on the values,
>> and
>> > >>>>> predictably across threads (UUIDs?).
>> > >>>>>
>> > >>>>> # Full Example
>> > >>>>> <?php
>> > >>>>>
>> > >>>>> final immutable class ValueObject {
>> > >>>>>
>> > >>>>> public $value;
>> > >>>>>
>> > >>>>> public function __construct($value) {
>> > >>>>>   $this->value = $value;
>> > >>>>> }
>> > >>>>>
>> > >>>>> public function withValue($value) {
>> > >>>>>   $this->value = $value;
>> > >>>>> }
>> > >>>>>
>> > >>>>> }
>> > >>>>>
>> > >>>>> class A {
>> > >>>>>
>> > >>>>> public $vo;
>> > >>>>>
>> > >>>>> public function __construct(ValueObject $vo) {
>> > >>>>>   $this->vo = $vo;
>> > >>>>> }
>> > >>>>>
>> > >>>>> }
>> > >>>>>
>> > >>>>> class B {
>> > >>>>>
>> > >>>>> public $vo;
>> > >>>>>
>> > >>>>> public function __construct(ValueObject $vo) {
>> > >>>>>   $this->vo = $vo;
>> > >>>>> }
>> > >>>>>
>> > >>>>> }
>> > >>>>>
>> > >>>>> $vo = new ValueObject(1);
>> > >>>>>
>> > >>>>> $a = new A($vo);
>> > >>>>> $b = new B($vo);
>> > >>>>>
>> > >>>>> var_dump($a->vo === $b->vo); // bool(true)
>> > >>>>>
>> > >>>>> $a->vo->withValue(2);
>> > >>>>>
>> > >>>>> var_dump($a->vo === $b->vo); // bool(false)
>> > >>>>>
>> > >>>>> $a->vo->withValue(1);
>> > >>>>>
>> > >>>>> var_dump($a->vo === $b->vo); // bool(true)
>> > >>>>>
>> > >>>>> // :)
>> > >>>>>
>> > >>>>> ?>
>> > >>>>>
>> > >>>>> --
>> > >>>>> Richard "Fleshgrinder" Fussenegger
>> > >>>>>
>> > >>>
>> > >>> --
>> > >>> PHP Internals - PHP Runtime Development Mailing List
>> > >>> To unsubscribe, visit: http://www.php.net/unsub.php
>> > >>>
>> > >>>
>> > >>
>> > >
>> >
>> >
>>
>
>
>
> --
> regards / pozdrawiam,
> --
> Michał Brzuchalski
> brzuchalski.com
>



-- 
Silvio Marijić
Software Engineer
2e Systems

Reply via email to