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

>
>
> 2016-09-04 10:55 GMT+02:00 Fleshgrinder <p...@fleshgrinder.com>:
>
>> Hi Chris!
>>
>> On 9/3/2016 5:00 PM, Chris Riley wrote:
>> > - Properties can be declared immutable. Immutable properties may only be
>> > changed under two circumstances: a) In the objects constructor b) If
>> they
>> > are null (This enables setter injection if required)
>> >
>>
>> The constraint b) would make the object mutable and defeat the purpose
>> of the immutable modifier since any property could change at any time if
>> it was NULL at the beginning. Requiring syncing in concurrent
>> environments.
>>
>> On 9/3/2016 5:00 PM, Chris Riley wrote:
>> > - Arrays assigned to immutable properties would not be possible to
>> change
>> >
>>
>> Array support would definitely be very nice. I mean, we have constant
>> arrays already, hence, it is possible.
>>
>> On 9/3/2016 5:00 PM, Chris Riley wrote:
>> > - Objects assigned to immutable properties would be possible to change,
>> so
>> > long as the same object remained assigned to the property.
>> >
>>
>> This would once more lead to mutability and the constraint of
>> immutability would be violated.
>>
>> On 9/3/2016 5:00 PM, Chris Riley wrote:
>> > From a developer adoption point of view, I think these two points are
>> > important to making immutable classes generally useful. Without 1, it
>> will
>> > be a nuisance to use 3rd party libraries esp those which retain
>> > compatibility for PHP < 7.2. Without 2 you block the ability to use
>> setter
>> > injection, which I personally would be in favour of if it meant that
>> devs
>> > stopped using it - it wouldn't - they would simply not use immutable
>> > classes, loosing the benefits thereof.
>> >
>>
>> The adoption of the feature will be halted until 7.2 is widely available
>> in bigger projects. That is most certainly right. However, we should aim
>> for the best, most useful, and future proof solution and not towards the
>> one that's adopted very fast but lacks some important constraints.
>> Having truly immutable objects is required in concurrent scenarios and
>> such scenarios are in the future for PHP and not in the past.
>>
>> Regarding setter injection: I do not see the need for it at all in the
>> context of immutable objects. In the end we are talking about value
>> objects here and they should not have any optional dependencies. Maybe
>> you could come up with a use case to illustrate the need?
>>
>> On 9/3/2016 5:00 PM, Chris Riley wrote:
>> > Dealing with the clone issue some of my ideas since then were:
>> >
>> > - Seal/Unseal (As per Larry's suggestion)
>> > - Parameters to __clone; in this instance the clone method would be
>> allowed
>> > to change properties of the object as well as the constructor. This
>> feels
>> > like it may breach the principal of least surprise as cloning an object
>> no
>> > longer guarantees an exact copy.
>> > - A new magic method __mutate($property, $newvalue) called instead of a
>> > fatal error when a property is changed. This probably lays too many
>> traps
>> > for developers for it to be a good idea.
>> > - Implicitly returning a new object whenever a property is changed.
>> Similar
>> > reservations to the above.
>> > - A new magic method __with($newInstance, $args) and a keyword with
>> that is
>> > used in place of clone eg $x = $y with ($arg1, $arg2); in this instance,
>> > __with receives a clone of $y (after calling __clone) and an array
>> [$arg1,
>> > $arg2] the with magic method is allowed to mutate $newInstance and must
>> > return it. This is currently my favoured solution
>> >
>>
>> How does one know which property is to be mutated in the __with method?
>> You should also not underestimate the performance hit and the branching
>> since you only want to change the properties that changed based on the
>> data from the passed array.
>>
>> I have a third proposal after giving this some more thought. Inspired by
>> Rust's approach to mark mutation explicitly.
>>
>>   final immutable class ValueObject {
>>
>>     public $value;
>>
>>     public mutator [function] withValue($clone, $value): static {
>>       $clone->value = $value;
>>     }
>>
>>   }
>>
>>
> Providing `mutator` | `mut` keyword as method modifier sounds liek a good
> idea,
> althought passing `$clone` parameter as first additional param could break
> method declaration and would be misleading.
>
> Assuming mutator method is designed to  return mutated clone of immutable
> object
> having `$clone` variable could be handled internally without breaking
> method declaration.
>
> Such variable could be unlocked while in mutator method and locked on
> return.
> I was thinking about additional check if such mutator returns `$clone` but
> not `$this`
> but I don't see the need of it - assuming there is no what to change in
> some
> circumstances ther would be also possible to return `$this`.
>
> The return type declaration `self` could increase readability, but should
> not be required,
> as some developers doesn't already use return types.
>

It could look like in this gist
https://gist.github.com/brzuchal/e7b721e22a19cca42ec0d1f597a23baf


>
>
>> A mutator function always receives the mutable clone as first argument
>> and always returns that one. Users can have a return but they must
>> return the clone (hence the static return type declaration).
>>
>>   $vo1 = new ValueObject(1);
>>   $vo2 = $vo1->withValue(2);
>>
>> Calls are of course without the clone as it is handled by the engine.
>> There is no special branching necessary and no performance hit at all
>> while the logic is kept in the place where it is required.
>>
>> --
>> Richard "Fleshgrinder" Fussenegger
>>
>>
>
>
> --
> regards / pozdrawiam,
> --
> Michał Brzuchalski
> brzuchalski.com
>



-- 
regards / pozdrawiam,
--
Michał Brzuchalski
brzuchalski.com

Reply via email to