[Web API] Versionando nuestros servicios – Evolución de la representación por adición

Siempre que trabajamos con servicios HTTP (sean REST o no) un factor que nos preocupa es el del versionamiento del servicio, la constante evolución del mismo y como los distintos clientes interactuaran con este sin romper lo que se ha construido.

Esta evolución puede darse por distintos aspectos, uno de los más frecuentes es la evolución de nuestros recursos (que vienen a ser identificados por una URI). Estos recursos son conceptuales y la única manera de materializarlos es por medio de representaciones (html, json, xml…) y cada uno de los formatos que soportemos brindaran a cada petición de cada cliente una forma de obtener el mismo recurso, esto es lo que conocemos como negociación de contenido.

Si intentamos llevar esta conceptualización a un entorno con ASP.NET Web Api por ejemplo, tendríamos “entidades” que no son más que nuestros recursos, así podemos tener una clase Persona definida de la siguiente manera:

    public class Persona
    {
        public string Nombre { get; set; }

        public string Apellido { get; set; }
    }

Y un controlador que se encargue de entender las peticiones a la URI que identifica el recurso, así:

    public class PersonaController : ApiController
    {
        private static List<Persona> _personas = CreatePersonas();

        private static List<Persona> CreatePersonas()
        {
            return _personas ?? (_personas = new List<Persona>
                                                 {
                                                     new Persona
                                                         {
                                                             Nombre = "Nicolas",
                                                             Apellido = "Herrera"
                                                         }
                                                 });
        }

        // GET api/values
        public IEnumerable<Persona> Get()
        {
            return _personas;
        }

        // GET api/values/5
        public string Get(int id)
        {
            return "value";
        }

        // POST api/values
        public void Post([FromBody]string value)
        {
        }

        // PUT api/values/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/values/5
        public void Delete(int id)
        {
        }
    }

Y un cliente que se encarga de consumir esta información implementando la negociación de contenido que viene predeterminada en Web Api

        private static void Main(string[] args)
        {
            var httpClient = new HttpClient();
            httpClient.BaseAddress = new Uri("http://localhost:64186/api/persona");
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
            string json = httpClient.GetStringAsync(string.Empty).Result;
            var personas = JsonConvert.DeserializeObject<List<PersonaCliente>>(json);

            Console.WriteLine("Personas");
            foreach (PersonaCliente personaCliente in personas)
            {
                Console.WriteLine("Nombre y apellido: {0} {1}", personaCliente.Nombre,
                                  personaCliente.Apellido);
            }
            Console.ReadKey();
        }
    }

    public class PersonaCliente
    {
        public string Nombre { get; set; }

        public string Apellido { get; set; }
    }

Si nuestra entidad evolucionara adicionando una nueva propiedad sería lógico que su representación lo hiciera también y esta es la característica de versionamiento más pequeña que podemos encontrar, pues es muy común que necesitemos más información de una persona, información como por ejemplo la edad. Así:

    public class Persona
    {
        public string Nombre { get; set; }

        public string Apellido { get; set; }

        public int  Edad { get; set; }
    }

El primer approach y uno de los más usados es el versionamiento por la URI, y personalmente no es una solución que me agrade mucho, pues el concepto sigue siendo el mismo y no debería tener una nueva URI, pues esto significaría que es un nuevo concepto.

Cuando se le agregan elementos a la representación del recurso no debería afectar en nada a un cliente en específico porque en ese momento el ignora la existencia de ese elemento, en muchas ocasiones se rompe dicho contrato es porque se remueven elementos de la representación, elementos que desconocemos como los trabajaba cada uno de los clientes.

Teniendo esto presente a mi cliente de consola le dará igual que le agregué a la representación mientras el siga trabajando con dicha versión del API no rompo nada. Esta nueva propiedad será ignorada.

Ahora la pregunta es, como se apega mi cliente a una nueva versión si no estamos realizando peticiones a URIs distintas? La respuesta viene dada por la negociación de contenido y la cabecera accept por supuesto. Pero esto ya da para un segundo post que quiero escribir en mas detalle y no como un punto adicional de este.

Hasta el próximo post.

Anuncios
[Web API] Versionando nuestros servicios – Evolución de la representación por adición

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s