Loading ...
Sorry, an error occurred while loading the content.

Re: [rest-discuss] API versioning

Expand Messages
  • Keith Hassen
    First of all, thanks for the replies and perspective on REST. Backing up to the original question it seems like your particular take on it is that there s no
    Message 1 of 13 , Jan 8, 2013
    • 0 Attachment
      First of all, thanks for the replies and perspective on REST.

      Backing up to the original question it seems like your particular take on it is that there's no need to version URIs or the resource representations provided that a cautious approach is taken to resource evolution.

      To be honest I'm still not sure how this would be handled if two clients diverge in their understanding of the same resource.  Perhaps that divergence leads us to different concepts and thus different resources and I've just been thinking about the problem incorrectly. :)

      Back to your most recent response...

      This seems to be a recommended practice that I've encountered in
      reading about RESTful implementations.


      Perfectly good HTTP API practice; REST, not so much.  The point of
      media types is to provide loose coupling based on shared understanding
      of how the representation is to be decoded.  

      I think I'm actually talking about loose coupling, but this area seems a little fuzzy.  Comprehensive coverage of media type seems to be missing from Fielding's dissertation.  The media type I specified was definitely too specific (vnd.example.com might be a better choice rather than vnd.example.com.order, the latter effectively binding the media type to the representation and starts smelling like RPC modelling rather than the loose coupling promoted by the RESTful style).

      So how tight should this coupling be?  And what about versioning?  I'm tempted to say that if versioning is required, do so in the URi rather than the media type.  The media type seems to be more of an assertion/expectation regarding application context rather than a specification of the resource.

      It's amazing (or maybe not at all amazing) how divided this subject appears to be on the web.  This: http://www.informit.com/articles/article.aspx?p=1566460 is a pretty typical example.

      Thanks again for the feedback.

      K


      On 2013-01-08, at 12:57 AM, Eric J. Bowman wrote:

      Keith Hassen wrote:

      This seems to be a recommended practice that I've encountered in
      reading about RESTful implementations.


      Perfectly good HTTP API practice; REST, not so much.  The point of
      media types is to provide loose coupling based on shared understanding
      of how the representation is to be decoded.  Not tight coupling based
      on interpreting the content of the representation.  I've never seen an
      order API that couldn't be represented as HTML; despite any number of
      variations on this theme (or versions within), the media type doesn't
      vary between more order APIs on the Web than I can count.

      REST has no notion of resource "type" let alone of exposing same on the
      wire, so I've never understood why this solution is so prevalent in REST
      discussions.  Just media types, which are agnostic as to what "type" of
      resource is being represented (with rare exceptions as parameters).


      Anything else is up to the user-agent to work out.  This is actually
      easier for m2m than h2m; a v1 m2m client should already ignore any
      hypertext it doesn't understand, rolling out v2 can then re-use any
      non-deprecated bits of the API already present plus the new stuff,
      and ignore the deprecated stuff.  Can't it?

      Not always, at least not in my experience. :)  I have found that
      while breaking changes don't happen often, they *do* happen.  Add to
      this the possibility of different types of API consumers that start
      off implementing your APIs the same way, but slowly (or rapidly!)
      diverge over time.  In some cases new resources (and thus new URIs)
      will suffice, but in other cases what we are doing is very
      specifically *evolving* the resource representation to accommodate
      new requirements.


      Then design for graceful degradation (or progressive enhancement) using
      client-side feature detection.  Just saying there's no need to swing
      the conneg hammer to turn this particular screw.

      -Eric

    • Alexander Johannesen
      Hiya, ... I think there needs to be made some distinctions between a shared understanding of models and a shared understanding of a resource in that model.
      Message 2 of 13 , Jan 8, 2013
      • 0 Attachment
        Hiya,

        To be honest I'm still not sure how this would be handled if two clients 
        > diverge in their understanding of the same resource.

        I think there needs to be made some distinctions between a shared understanding of models and a shared understanding of a resource in that model. Very often the model stays the same, and so the entities of that models shouldn't change, or at best, provide a framework for dealing with small changes (like backwards compatibility of models).

        What many confuse as an API change in terms of REST is really a model change, not a change to the language itself, which is REST. Even if the internal representation of a resource changes, its place in the model most often does not, and neither does the interface. True REST (TM) is representational through hyperlinks, and applications should be guided through the model rather than having knowledge of it, at least in an ideal world (but people tend to think the overhead is too great for the world of computing to deal with). There's no point in changing the interface nor the model if only representation changes. That is probably better dealt with through content negotiation, or, at worst, inside the representation level itself.

        What's being stressed here is that the separation of interface, model and internal representation most often do not require versioning, at least not on the model and interface level. So;

           /user/johnson
           /invoice/1023
           /process/345/participants

        These are URIs that probably don't change with "versions". So why version them at this level? The model is probably fine, only semantics and representations change, so why not deal with it at that level instead?

        Hope that makes sense. :) If not, gives us some examples of a change from one version to the next, and let's talk about various ways to deal with the changes in question.


        Regards,

        Alex








        On Wed, Jan 9, 2013 at 4:25 PM, Keith Hassen <keith.hassen@...> wrote:
         

        First of all, thanks for the replies and perspective on REST.

        Backing up to the original question it seems like your particular take on it is that there's no need to version URIs or the resource representations provided that a cautious approach is taken to resource evolution.

        To be honest I'm still not sure how this would be handled if two clients diverge in their understanding of the same resource.  Perhaps that divergence leads us to different concepts and thus different resources and I've just been thinking about the problem incorrectly. :)

        Back to your most recent response...

        This seems to be a recommended practice that I've encountered in
        reading about RESTful implementations.


        Perfectly good HTTP API practice; REST, not so much.  The point of
        media types is to provide loose coupling based on shared understanding
        of how the representation is to be decoded.  

        I think I'm actually talking about loose coupling, but this area seems a little fuzzy.  Comprehensive coverage of media type seems to be missing from Fielding's dissertation.  The media type I specified was definitely too specific (vnd.example.com might be a better choice rather than vnd.example.com.order, the latter effectively binding the media type to the representation and starts smelling like RPC modelling rather than the loose coupling promoted by the RESTful style).

        So how tight should this coupling be?  And what about versioning?  I'm tempted to say that if versioning is required, do so in the URi rather than the media type.  The media type seems to be more of an assertion/expectation regarding application context rather than a specification of the resource.

        It's amazing (or maybe not at all amazing) how divided this subject appears to be on the web.  This: http://www.informit.com/articles/article.aspx?p=1566460 is a pretty typical example.

        Thanks again for the feedback.

        K


        On 2013-01-08, at 12:57 AM, Eric J. Bowman wrote:

        Keith Hassen wrote:

        This seems to be a recommended practice that I've encountered in
        reading about RESTful implementations.


        Perfectly good HTTP API practice; REST, not so much.  The point of
        media types is to provide loose coupling based on shared understanding
        of how the representation is to be decoded.  Not tight coupling based
        on interpreting the content of the representation.  I've never seen an
        order API that couldn't be represented as HTML; despite any number of
        variations on this theme (or versions within), the media type doesn't
        vary between more order APIs on the Web than I can count.

        REST has no notion of resource "type" let alone of exposing same on the
        wire, so I've never understood why this solution is so prevalent in REST
        discussions.  Just media types, which are agnostic as to what "type" of
        resource is being represented (with rare exceptions as parameters).


        Anything else is up to the user-agent to work out.  This is actually
        easier for m2m than h2m; a v1 m2m client should already ignore any
        hypertext it doesn't understand, rolling out v2 can then re-use any
        non-deprecated bits of the API already present plus the new stuff,
        and ignore the deprecated stuff.  Can't it?

        Not always, at least not in my experience. :)  I have found that
        while breaking changes don't happen often, they *do* happen.  Add to
        this the possibility of different types of API consumers that start
        off implementing your APIs the same way, but slowly (or rapidly!)
        diverge over time.  In some cases new resources (and thus new URIs)
        will suffice, but in other cases what we are doing is very
        specifically *evolving* the resource representation to accommodate
        new requirements.


        Then design for graceful degradation (or progressive enhancement) using
        client-side feature detection.  Just saying there's no need to swing
        the conneg hammer to turn this particular screw.

        -Eric




        --
         Project Wrangler, SOA, Information Alchemist, UX, RESTafarian, Topic Maps
        --- http://shelter.nu/blog/ ----------------------------------------------
        ------------------ http://www.google.com/profiles/alexander.johannesen ---
      • Jørn Wildt
        If you work with generic media types like plain XML, JSON and(X)HTML (and others) then there is absolutely no reason to version those through the content-type
        Message 3 of 13 , Jan 8, 2013
        • 0 Attachment
          If you work with generic media types like plain XML, JSON and(X)HTML (and others) then there is absolutely no reason to version those through the content-type and content negotiation. I mean, when did the processing rules for XML and JSON last change? Oh, well, the rules for HTML does change - but this is not handled through the media type, but rather through a versioning mechanism inside the payload (the DOCTYPE).

          "Unfortunately" there is a lot of domain specific media types out there - and since domains changes regularly over time, well, you start thinking that versioning must be done through the media type. And this is where things start to break down. If you avoid domain specific media types (like vnd.order+xml and so on), then you can avoid versioning through the media type.

          But, of course, your application still evolves over time. Then what?

          Try these guidelines (and check also Nottingham's blog http://www.mnot.net/blog/2011/10/25/web_api_versioning_smackdown):

          - Do not expose your internal business objects directly on the wire (for instance by JSON serializing them directly). Do wrap your business objects in a (more) stable external format, such that you are free to change the underlying business objects without the public facing format changing too. Keep that transformation in sync with your internal changes.

          - Don't make breaking changes to your public format.

          - Add versioning information inside the payload.

          - If you have to introduce breaking changes then create a new resource for the new version.

          - Put links to never versions of the resource into the original resource (for instance using the Link header). Never clients can look for these links and move on to the new and improved version.

          - Introduce new links, in addition to the old ones, where other resources are linking to your resource (if possible), using new link relation names or similar mechanism. Newer clients will know which of the links to follow - older clients will continue with the link that they have always used.

          - URLs are not identities for your business data - they are identities for various representations of your business data. I mean, api-v1.example.com/person/1234 is obviously not the same resource as api-v2.example.com/person/1234 - but it can certainly represent exactly the same piece of business data.

          (and, yes, this is quite the opposite of what I argued in my first post in this thread)

          /Jørn


        • Keith Hassen
          Yeah we definitely make the distinction between the internal representation and the representation exposed to clients. The changes I m thinking about are
          Message 4 of 13 , Jan 9, 2013
          • 0 Attachment
            Yeah we definitely make the distinction between the internal representation and the representation exposed to clients.  The changes I'm thinking about are those dictated by consumers, so in my case I'm thinking of a scenario where two consumers start with the same requirements for a representation of a resource (the thing that is returned to the client when issuing a GET on a certain resource), but then diverge over time.

            I'm actually having a hard time thinking of a *breaking* change for consumers that can't be accommodated by some kind of additive transformation to the original.  In the worst case, you may have data duplication, for example a user might start off being:

            { name:"John Smith", address:"123 nowhere ave." }

            but due to changing requirements needs to change to:

            { name:"John Smith", address:{street_address:"123 nowhere ave.", postal:"12345", phone:"555-5555"}}

            In which case the new "address" representation could be added to the original representation using a different name:

            { name:"John Smith", address:"123 nowhere ave.", full_address:{...}}

            This allows for compatibility between old and new client requirements.


            On 2013-01-09, at 12:48 AM, Alexander Johannesen wrote:

            Hiya,

            To be honest I'm still not sure how this would be handled if two clients 
            > diverge in their understanding of the same resource.

            I think there needs to be made some distinctions between a shared understanding of models and a shared understanding of a resource in that model. Very often the model stays the same, and so the entities of that models shouldn't change, or at best, provide a framework for dealing with small changes (like backwards compatibility of models).

            What many confuse as an API change in terms of REST is really a model change, not a change to the language itself, which is REST. Even if the internal representation of a resource changes, its place in the model most often does not, and neither does the interface. True REST (TM) is representational through hyperlinks, and applications should be guided through the model rather than having knowledge of it, at least in an ideal world (but people tend to think the overhead is too great for the world of computing to deal with). There's no point in changing the interface nor the model if only representation changes. That is probably better dealt with through content negotiation, or, at worst, inside the representation level itself.

            What's being stressed here is that the separation of interface, model and internal representation most often do not require versioning, at least not on the model and interface level. So;

               /user/johnson
               /invoice/1023
               /process/345/participants

            These are URIs that probably don't change with "versions". So why version them at this level? The model is probably fine, only semantics and representations change, so why not deal with it at that level instead?

            Hope that makes sense. :) If not, gives us some examples of a change from one version to the next, and let's talk about various ways to deal with the changes in question.


            Regards,

            Alex








            On Wed, Jan 9, 2013 at 4:25 PM, Keith Hassen <keith.hassen@...> wrote:
             

            First of all, thanks for the replies and perspective on REST.

            Backing up to the original question it seems like your particular take on it is that there's no need to version URIs or the resource representations provided that a cautious approach is taken to resource evolution.

            To be honest I'm still not sure how this would be handled if two clients diverge in their understanding of the same resource.  Perhaps that divergence leads us to different concepts and thus different resources and I've just been thinking about the problem incorrectly. :)

            Back to your most recent response...

            This seems to be a recommended practice that I've encountered in
            reading about RESTful implementations.


            Perfectly good HTTP API practice; REST, not so much.  The point of
            media types is to provide loose coupling based on shared understanding
            of how the representation is to be decoded.  

            I think I'm actually talking about loose coupling, but this area seems a little fuzzy.  Comprehensive coverage of media type seems to be missing from Fielding's dissertation.  The media type I specified was definitely too specific (vnd.example.com might be a better choice rather than vnd.example.com.order, the latter effectively binding the media type to the representation and starts smelling like RPC modelling rather than the loose coupling promoted by the RESTful style).

            So how tight should this coupling be?  And what about versioning?  I'm tempted to say that if versioning is required, do so in the URi rather than the media type.  The media type seems to be more of an assertion/expectation regarding application context rather than a specification of the resource.

            It's amazing (or maybe not at all amazing) how divided this subject appears to be on the web.  This: http://www.informit.com/articles/article.aspx?p=1566460 is a pretty typical example.

            Thanks again for the feedback.

            K


            On 2013-01-08, at 12:57 AM, Eric J. Bowman wrote:

            Keith Hassen wrote:

            This seems to be a recommended practice that I've encountered in
            reading about RESTful implementations.


            Perfectly good HTTP API practice; REST, not so much.  The point of
            media types is to provide loose coupling based on shared understanding
            of how the representation is to be decoded.  Not tight coupling based
            on interpreting the content of the representation.  I've never seen an
            order API that couldn't be represented as HTML; despite any number of
            variations on this theme (or versions within), the media type doesn't
            vary between more order APIs on the Web than I can count.

            REST has no notion of resource "type" let alone of exposing same on the
            wire, so I've never understood why this solution is so prevalent in REST
            discussions.  Just media types, which are agnostic as to what "type" of
            resource is being represented (with rare exceptions as parameters).


            Anything else is up to the user-agent to work out.  This is actually
            easier for m2m than h2m; a v1 m2m client should already ignore any
            hypertext it doesn't understand, rolling out v2 can then re-use any
            non-deprecated bits of the API already present plus the new stuff,
            and ignore the deprecated stuff.  Can't it?

            Not always, at least not in my experience. :)  I have found that
            while breaking changes don't happen often, they *do* happen.  Add to
            this the possibility of different types of API consumers that start
            off implementing your APIs the same way, but slowly (or rapidly!)
            diverge over time.  In some cases new resources (and thus new URIs)
            will suffice, but in other cases what we are doing is very
            specifically *evolving* the resource representation to accommodate
            new requirements.


            Then design for graceful degradation (or progressive enhancement) using
            client-side feature detection.  Just saying there's no need to swing
            the conneg hammer to turn this particular screw.

            -Eric





            --
             Project Wrangler, SOA, Information Alchemist, UX, RESTafarian, Topic Maps
            --- http://shelter.nu/blog/ ----------------------------------------------
            ------------------ http://www.google.com/profiles/alexander.johannesen ---

          • Keith Hassen
            Thanks, the link below is interesting. I think the rules you listed below are good ones and generally make sense. Maybe it is *almost* always true that we
            Message 5 of 13 , Jan 9, 2013
            • 0 Attachment
              Thanks, the link below is interesting.  I think the rules you listed below are good ones and generally make sense.  Maybe it is *almost* always true that we can find a way to either a) make the change non-breaking or b) create a new resource.  In the rare cases where it must be done, then specifying a version in the URI might be necessary, but should be limited to very exceptional cases that I'm having a hard time devising. :)

              K


              On 2013-01-09, at 1:45 AM, Jørn Wildt wrote:

              If you work with generic media types like plain XML, JSON and(X)HTML (and others) then there is absolutely no reason to version those through the content-type and content negotiation. I mean, when did the processing rules for XML and JSON last change? Oh, well, the rules for HTML does change - but this is not handled through the media type, but rather through a versioning mechanism inside the payload (the DOCTYPE).

              "Unfortunately" there is a lot of domain specific media types out there - and since domains changes regularly over time, well, you start thinking that versioning must be done through the media type. And this is where things start to break down. If you avoid domain specific media types (like vnd.order+xml and so on), then you can avoid versioning through the media type.

              But, of course, your application still evolves over time. Then what?

              Try these guidelines (and check also Nottingham's blog http://www.mnot.net/blog/2011/10/25/web_api_versioning_smackdown):

              - Do not expose your internal business objects directly on the wire (for instance by JSON serializing them directly). Do wrap your business objects in a (more) stable external format, such that you are free to change the underlying business objects without the public facing format changing too. Keep that transformation in sync with your internal changes.

              - Don't make breaking changes to your public format.

              - Add versioning information inside the payload.

              - If you have to introduce breaking changes then create a new resource for the new version.

              - Put links to never versions of the resource into the original resource (for instance using the Link header). Never clients can look for these links and move on to the new and improved version.

              - Introduce new links, in addition to the old ones, where other resources are linking to your resource (if possible), using new link relation names or similar mechanism. Newer clients will know which of the links to follow - older clients will continue with the link that they have always used.

              - URLs are not identities for your business data - they are identities for various representations of your business data. I mean, api-v1.example.com/person/1234 is obviously not the same resource as api-v2.example.com/person/1234 - but it can certainly represent exactly the same piece of business data.

              (and, yes, this is quite the opposite of what I argued in my first post in this thread)

              /Jørn



            Your message has been successfully submitted and would be delivered to recipients shortly.