I am looking at the PSR-7 interfaces and thinking of a way on how to implement them.
I've also been reading this blog post. Apparently the objects that implement the PSR-7
interfaces must be immutable.
So if I implement the withProtocolVersion
method from MessageInterface
then it would look something like this:
public function withProtocolVersion($version)
{
if ( $this->protocol === $version )
{
return $this;
}
$new = clone $this;
$new->protocol = $version;
return $new;
}
My question really is, why immutable? Why not simply do a return $this;
?
It's not that I'm concerned about the amount of memory it allocates, I just really do not see any benefit in keeping it immutable.
Like the blog posts says, when you do this:
$request = $request
->withMethod('POST')
->withUrl(new Url('http://example.org/')
->withHeader('Content-Type', 'text/plain');
Then four copies are created, but the end result in $request
is the same as when I would simply use return $this
, right?
Why is the decision made to keep it immutable. So why do I have to do a clone $this
? What's the benefit of it?
I'm not really getting the idea begind it.
I suggest you to read this document, where all the design choices are explained in detail.
In particular you should read the Why value objects?
and the New instances vs returning $this
sections.
The key points are the following:
In essence, modeling HTTP messages as value objects ensures the integrity of the message state, and prevents the need for bi-directional dependencies, which can often go out-of-sync or lead to debugging or performance issues.
and
These operations can be accomplished with value objects as well, with a number of benefits:
- The original request state can be stored for retrieval by any consumer.
- A default response state can be created with default headers and/or message body.
If you want to dig deeper, I'd recommend to look in the history of the fig mailing list (you can find it here), where there was a lot of discussion regarding the immutability of the objects