10

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?

  • If it's just the original request/response you need, we can store a clone of the object that gets set in the c'tor and then never gets touched again. You can mutate away but still access the original whenever needed. This probably would have been better IMO. – mpen Apr 20 '15 at 20:54
4

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?

  1. 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

  2. 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
    Thanks. Both answers were informative. I decided to accept yours because the notion of freezing objects helped to clarify my thinking. An immutable frozen response object get's created, as some point just prior to sending the object get's cloned and unfrozen. Bunches of delivery oriented headers (caches, cors etc) can be added. The object can then be frozen and sent on it's way. – Cerad Apr 8 '15 at 13:45
7

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.

  • 1
    One advantage which is also worth mentioning IMO is that when you have immutable objects you never need to ask yourself if you are working with a private copy you can change freely or a reference owned by another object where changes might affect other objects. – Philipp Apr 6 '15 at 14:37
  • @Philipp: IMHO, one of the biggest deficiencies in Java.NET is the lack of a convention to distinguish between methods that return references to new objects that the caller can change at will, versus those which return references which are attached to or encapsulate internal state that may be modified to manipulate that state, and those which return references to object which may or may be attached to internal state. It's not possible to write code that is robust and efficient without knowing what sorts of references things are supposed to return, but there's no convention to indicate that. – supercat Apr 6 '15 at 18:30
  • Thanks for the answer. It pretty much confirmed what I was thinking so it must be right. I decided to accept xmoyxr's answer because he raised the concept of freezing objects which I had not encountered before. – Cerad Apr 8 '15 at 13:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.