I think it’s safe to say that most web applications are based on the request/response paradigm. PHP has never had a formal abstraction of these objects. One group is trying to change this: https://github.com/php-fig/fig-standards/blob/master/proposed/http-message.md
However, they sort of got side tracked on the issue of immutability. On the one hand, request/response object generally need very little change during their life cycle. On the other hand, the response object in particular often needs HTTP headers to be added.
Furthermore, immutability has never really caught on in the land of PHP.
What advantages do people see in using immutable request/response objects?
Let’s suppose you are returning a json object.
$response = new JsonResponse($item);
Nice and simple. But it turns out that the request was a Cross-Origin Resource Sharing(CORS) request. The code that generates the response should not care but somewhere downstream is a process that will add the necessary Access-Control headers. Any advantage to keeping the original response and creating a new one with the additional headers? Or is it strictly a question of programming style.
The request object is a bit more interesting. It starts off the same:
$request = new Request('incoming request information including uri and headers');
The initial information should not need to be changed. However, as the request get’s passed along there is often a need to add additional processing information. For example, you may have a url matcher which decides what action should be executed for a given request.
$request->setAttribute('action',function() {});
Actually executing the action is the responsibility of a down stream process. You could have a mutable RequestAttributesCollection which wraps the immutable request but that tends to be a bit awkward in practice. You could also have a request that’s immutable except for an attributes collection. Exceptions tends to be awkward as well. Any experience on dealing with these sorts of requirements?
1
What advantages do people see in using immutable request/response objects?
I agree with @MainMa’s statement “I’m not sure if the slight benefit of readability compensates the possible lack of flexibility” and personally I don’t see any practical and useful aspects of forcing PHP HTTP Request
temporary objects or PHP HTTP Response
temporary objects to be immutable
Any experience on dealing with these sorts of requirements?
-
Microsoft’s
Windows Presentation Foundation
framework introduces concept of freezable objects. Once frozen, such objects become- immutable (throw exceptions when modification is attempted),
- faster to use (property getters don’t need to do any fancy “what’s my value?” decisions any more),
- consuming less memory (internal helper data structures and caches etc. can be reduced to their most time & space efficient representation)
- and shareable
Although it is used as GUI speed optimization, the concept itself is applicable also elsewhere, including it’s benefits
-
Nancy
(“Lightweight, low-ceremony, framework for building HTTP based services on .Net and Mono”) describes benefit of immutability in one of commit comments as…we can assume our caches are immutable if they’re off, which means we have no locks so faster performance (although the hit isn’t massive)…
I did not find any other noteworthy comments about immutability, but the benefit of reusable, cacheable response objects may apply to
PHP
as well
The above may look like off-topic answers, but I’m not aware of anything else and that’s why I think the immutability requirement is an artificial problem and rather matter of preference or coding style etc.
1
Immutable objects in general have several benefits.
-
The most important one is how easy is to use immutable objects in code executed in parallel. This also explains why “immutability has never really caught on in the land of PHP”.
-
State consistency is easier to obtain.
-
Objects are easy, more natural to work with.
The essential thing is how much the object should change during its life time—every change to an immutable object requires to create an additional instance, which can quickly be too expensive in terms of memory (and probably CPU cycles as well). This is also why most programming languages where string
is immutable ends up having another class for some sort of mutable strings, such as StringBuilder
in C#, to respond to situations where strings are concatenated from many small parts, each part added dynamically.
In a client-side library (sending an HTTP request and receiving a response), it makes sense to make HTTP request and response immutable: while some requests could be build with a fluent interface, this is not the major usage. The response won’t be changed anyway, so immutability makes sense.
In a server-side library (receiving an HTTP request and sending a response), while the request can be immutable, I’m not sure if the response can be. The data itself can be a stream (which, for some people—see below—forces the response object to be mutable), and the headers themselves can be added “on the fly” during the execution of the script, until the response starts to be sent to the client.
In both cases, given that there is no execution in parallel, I’m not sure if the slight benefit of readability compensates the possible lack of flexibility.
Make sure you also read a more complete article by Evert Pot about PSR-7. The article explains, among others, than one of the cases where such immutability is problematic is for long responses which should be streamed. Personally, I don’t see the point: IMHO, nothing forbids an immutable object to contain a stream (for instance, a FileReader
object can be immutable even if it reads a file which can change over time). Python’s Flask framework uses a different approach when it comes to large responses (or responses which take time to generate) by returning an iterator.
3