"OpenAPI, estandarizando los contratos de las API". Entrevista a Pedro J. Molina

07/09/2018
Artículo original

Openapi Portada

El café humea en la mesa, mientras el tono de llamada del Hangout se repite en mis auriculares, y repaso las preguntas que quiero hacerle a Pedro J. Molina; uno de los mayores expertos en OpenAPI de nuestro país.

Es miembro del ISA – Grupo de investigación de Ingeniería de software aplicada- de la Universidad de Sevilla, liderado por Antonio Ruiz junto a Pablo Fernández, y doctor en informática, especializado en modelado y generación de código.

Recientemente se ha integrado dentro de la Iniciativa OpenAPI, en donde participa de forma activa en la TSC (Technical Steering Committee) y el BGB (Business Governance Board). Y se ha prestado para una larga entrevista donde repasamos esta tecnología.

Una de las cosas que más me llaman la atención de Pedro, es la claridad y sencillez con que contesta las preguntas técnicas de todo nivel que le voy lanzando durante esta hora larga de conversación.

Busca la forma de explicar conceptos muy complejos, para lograr que lleguen a la mayoría de los lectores sin perder, en ningún momento, la rigurosidad de una mente científica.

¿Qué es OpenAPI? Api Consumers

Es un estándar para definir contratos de Api. Los cuales describen la interfaz de una serie de servicios que vamos a poder consumir por medio de una signatura. Por ejemplo, saber que vamos a tener una operación de sumar que va a recibir dos números y que estos son del tipo “entero”.

Tecnologías previas, como CORBA o SOAP, han intentado estandarizar las operaciones RPC (Llamadas a procedimientos remotos) que satisfagan la necesidad de comunicar dos máquinas que están separadas entre sí; y que requieran conocer como una tiene que invocar a la otra, especificando qué tipo de mensajes se aceptan, y qué es lo que se va a devolver.

¿Qué ventaja tiene el enfoque de OpenApi en comparación con definir un API de modo informal?

Se puede exponer un servicio de manera informal, pero la comunicación de cómo acceder al mismo también lo será. Esta comunicación informal puede inducir o incluir equivocaciones al escribirla, describirla, o ser incompleta; siendo una documentación con muy poco valor para poder consumir el servicio, porque depende de que esté bien expresado y sea bien entendido.

Ese es el contrato en que hay que ponerse de acuerdo.

Si hacemos el esfuerzo de formalizar esa definición (contrato), podemos conseguir que una máquina también la aproveche para poder conectarse al servicio y, consumiendo la especificación OpenAPI, construir un Proxy de integración. Es decir, una clase que automáticamente se conecta al servicio.

¿Pero esto no lo hacía ya los WSDL? ¿Qué falló para que sean tecnologías residuales en la actualidad? Arquitectura SOA

CORBA y WSDL son tecnologías para comunicar servicios distribuidos. El paradigma SOA (Arquitectura orientada al servicio) es un estilo arquitectónico basado en la comunicación entre servicios distribuidos débilmente acoplados y altamente interoperables. SOA fue abrazado por la industria y los grandes fabricantes como Oracle, Microsoft, IBM, etc., los cuales se lanzaron a construir sus propias pilas de productos SOA que resultaron ser muy complejas y, en ocasiones, incompatibles entre sí.

Al final la complejidad del uso de la pila de productos SOA fue tal, que la industria abandonó la aplicación de los estándares más farragosos. Y con la llegada de los primeros smartphone y sus limitadas capacidades de cálculo y almacenamiento, migraron del XML al JSON (aunque el primero es mucho más extensible que el segundo) y de los Webservices (y sus sobres SOAP) a las comunicaciones REST.

¿Qué relación tiene Swagger con OpenAPI?

OpenAPI viene de Swagger.

A finales de la década pasada empezó a crecer la economía de las API’s, la cual indica que toda aplicación que quiera escalar y triunfar en el mercado debe incluir una Interfaz de Programación de Aplicaciones potente.

En 2011, Tony Tam crea el proyecto Swagger API para automatizar la documentación y la generación del SDK (framework de desarrollo) de clientes de sus API’s. Diseñando un formato muy sencillo para describir el interfaz, en JSON o YAML, pero lo suficientemente formal como para que las máquinas lo puedan utilizar para crear Proxys (para clientes) y Skeletons (para servidores).

El éxito de Swagger fue fulgurante, convirtiéndose en un estándar “de facto”, y siendo adquirido por la empresa SmartBear que ha liberado todo el proyecto añadiéndolo a la Linux Foundation y atrayendo a los actores más importantes en la industria como Microsoft, IBM, PayPal, Adobe, Google, SAP, etc.

Y dentro de la Linux Foundation está la Iniciativa OpenAPI que es un comité dentro de la Fundación Linux que rige la evolución de la especificación.

¿Por qué está siendo tan apoyado por los fabricantes?

Si bien Swagger ya era libre, SamrtBear lo adquirió y liberó para hacerlo realmente neutral y que los diferentes fabricantes pudieran desarrollar sus 'API Middleware' -productos que se colocan entre tu API y el cliente final-, que te dan servicios de autenticación, autorización, seguridad, identificación, gestión de pagos, entre otros.

En una API que soporte 100 endpoints, la complejidad viene al tener que configurar nuestra herramienta para cada uno de ellos. Sin embargo, al tener una definición del contrato OpenAPI, con un sistema de drag & drop podría configurar de modo automático la herramienta de forma muy sencilla.

Los fabricantes de Middelware son los primeros interesados en que haya un estándar abierto para todos. Y, como hay negocio, se han puesto de acuerdo en dicho estándar siendo este el incentivo que ha conseguido que todos estén convergiendo hacía OpenAPI; incluso los usuarios de RAML, otro framework para definir las API, que se ha integrado en el comité de la Fundación Linux.

“El objetivo de OpenAPI es construir un estándar en la definición de las API para humanos, pero haciendo hincapié en el interfaz para máquinas, facilitando que se configuren e integren de forma autónoma”

Pero no se circunscribe a los fabricantes, también actores tan importantes como la Banca o los gobiernos han entendido las ventajas de la estandarización en OpenAPI . Así Holanda se ha convertido en el primer estado que ha adoptado la definición para el desarrollo de sus aplicaciones.

¿Quién compone OpenAPI? Investigadores de ISA

Hay una representación por cada organización que es miembro de la iniciativa. España está presente por el Grupo de investigación de Ingeniería de software aplicada (ISA) de la Universidad de Sevilla, al igual que por la startup 42 Crunch dedicada a la seguridad y gestión de amenazas a aplicaciones y datos.

El Grupo ISA hace una labor de investigación, más que orientada al negocio, trabajando en métricas de SLA donde se determina la definición de nivel de servicio. El objetivo es proponer extensiones orientadas a la medición y definición de niveles de servicio dentro de los contratos OpenAPI, aplicando la investigación realizada en la implantación industrial.

NdE. Las ramificaciones e implantaciones de estas extensiones al estándar OpenAPI aporta un valor crítico en las capacidades de aplicación de los contratos entre los interfaces de integración. En ningún otro estándar se comprende de manera específica el soporte a la medición de la calidad del servicio.

Dentro de la iniciativa OpenAPI existen tres comités diferenciados:

  • El Comité Técnico, en donde se discute el estándar y se añaden extensiones. Se trabaja con reuniones semanales en donde se revisa el estado de los desarrollos.
  • Comité de Gobierno, en donde se revisa el estado de la iniciativa desde un punto de vista de gestión.
  • Comité de Marketing, donde se diseñan y ponen en marcha acciones de formación, difusión, visibilización, etc. Y que utiliza los fondos aportados por las organizaciones miembros para realizar los eventos o campañas.

Además, de un par de personas a tiempo completo en la Linux Foundation, dedicadas a OpenAPI.

¿Cuáles son los mayores impedimentos que te encuentras en el día a día al trabajar en los comités?

Hay que conciliar los intereses de muchos fabricantes, que cada uno quiere añadir sus propias funcionalidades, las cuales hay que discutir y acordar. Todas las cosas diseñadas por comité son un poquito más lentas que cuando swagger lo construían dos personas y añadían funcionalidad muy rápido, llevando el producto hacia donde querían.

Las cosas en comité van despacio

Lo bueno es que al estar integrado en la Linux Foundation se garantiza que todo lo que se aporta está libre de patentes y que todo el mundo lo va a poder utilizar sin restricciones.

Hay veces que nos gustaría sacar las cosas más rápido, pero es necesario priorizar los temas, y los procesos van un poquito más despacio. Es importante ser cautos con las publicaciones para dar tiempo que la industria implemente estos estándares.

Por ejemplo, aún hay muchos utilizando OpenApi 2.0 mientras esperaban herramientas en desarrollo para la versión 3.0, que lanzamos hace un año.

En resumen, las dificultades de trabajar en un comité no son mayores que las de cualquier proyecto distribuido. Además, la gente que los compone tiene un gran nivel y vienen con las reuniones muy bien preparadas.

¿Puedo trabajar en la versión 3.0 apuntando a un contrato 2.0? Openapi Versiones

En el cambio de versión ha habido ruptura de compatibilidad porque había que reorganizar el estándar e implicaba una mejora muy importante. Sin embargo, próximamente vamos a publicar la versión 3.1, y en esta no va a haber ningún tipo de ruptura ya que somos especialmente cuidadosos de añadir nuevas definiciones que sean interoperables con las versiones anteriores.

¿Yo, como una persona física puedo aportar a la iniciativa OpenAPI?

Si. La manera más normal es acceder al proyecto en GitHub de la especificación y dar de alta una Issue en donde describir al detalle la petición o la aportación que quieres añadir. El comité técnico semanalmente revisa el proyecto en GitHub y, aquellas que son interesantes de desarrollar, puede solicitarte que hagas una contribución (pull request) en donde definas la implementación técnica de la propuesta o abrir una nueva tarea interna para planificar su debate y construcción.

También en el proyecto en GitHub tenemos los documentos de cada una de las reuniones del comité para poder hacer un seguimiento de alguna propuesta o del trabajo realizado, así como del roadmap de la siguiente versión que se está “cocinando”.

La Fundación Linux garantiza el acceso libre y gratuito a los trabajos de la Iniciativa OpenAPI

Por ejemplo, en la futura versión 3.1 se describen los “Overlays” que permiten extender la descripción de la API, y que podrían valer para publicar la documentación de una misma interfaz en varios idiomas; o sistemas de encriptación y firmas digitales utilizando JWE (JSON Web Encryption).

Estando previsto hacer el anuncio de esta nueva versión el próximo 24 de septiembre en la conferencia “API Strategy & Practice”.

¿Qué aportaciones habéis hecho al estándar?

Pedro Molina 01

Desde la Universidad de Sevilla hemos propuesto un par de herramientas para el prototipado rápido de contratos con OpenAPI. Oas-generator y Oas-tools.

A titulo personal desarrollo una librería en TypeScript (openapi-ts) y otra en .Net CORE para la creación de contratos OpenApi 3.0.x, otra que construye definiciones 3.0 para Baucis (framework de construcción de APIs REST).

Además de publicaciones en el blog de la iniciativa, como el de “Tres escenarios comunes para aprovechar la especificación OpenAPI”, y la participación semanal en el comité técnico.

Más información | Iniciativa OpenAPI de la Fundación Linux, GitHub de OpenAPI, Página de la ISA en la Universidad de Sevilla

Middleware en Redux-mx

06/09/2018
Artículo original

La parte que yo creo es mas interesante en la librería Redux es la creación de Middlewares y de ese modo extender Redux mas allá de lo que el equipo de Redux nos pueden ofrecer en la librería.

Esta funcionalidad se la agregue a mi pequeño clon, ahora se puede definir Middlewares que reciban el store (estado) y las acciones que se han lanzado, el ejemplo mas común es hacer un logger de las acciones. Este el ejemplo de este Middleware:

package examples.simple.middlewares;

import mx.com.betotto.redux.Middleware;

public class LoggerMiddleware extends Middleware {

    public LoggerMiddleware() {
        this.middleware = store -> next -> action -> {
            System.out.println("Action dispatched:  " + action.toString());

            //System.out.println("State from Middleware:  " + store.getState());
            return next.apply(action);
        };
    }
}

Como se puede ver tiene una firma muy parecida a el logger que viene en la documentación de Redux

const logger = store => next => action => {
  console.log('dispatching', action)
  let result = next(action)
  console.log('next state', store.getState())
  return result
}

leer más

Desarrollo Web móvil: ¿Qué diferencia existe entre el Viewport y la resolución de pantalla de un dispositivo?

06/09/2018
Artículo original

El viewport de un dispositivo es el tamaño teórico que tiene la pantalla de dicho dispositivo, el cual no tiene por qué coincidir con la resolución real de la pantalla (de hecho no coincide casi nunca en dispositivos modernos). La resolución se refiere al número de píxeles que puede mostrar dicha pantalla.

Así por ejemplo, los primeros tablets iPad de Apple, el iPad 1 y el 2, tenían una resolución de pantalla de 1024x768 píxeles, y el tamaño por defecto de su viewport era exactamente el mismo (o sea, una ratio de pixels de 1x). Sin embargo, cuando lanzaron el iPad 3 que ya tenía una pantalla "retina", la resolución física de la misma era 2048x1536, mientras que el tamaño del viewport seguía siendo el mismo: 1024x768 (es decir, la mitad, y por tanto una ratio de píxeles de 2x).

La resolución se refiere al número de píxeles que puede mostrar dicha pantalla; mientras que el viewport es el tamaño en píxeles que simula el navegador móvil que tiene la pantalla cuando visualiza una página web.

Al ancho del viewport se le suele denominar ancho en píxeles CSS, ya que no son píxeles reales sino los que el navegador (y por lo tanto sus hojas de estilo) ven en la práctica de cara a diseñar el layout de la página.

De hecho, para ver la diferencia existente entre el ancho del viewport de un navegador y la resolución de pantalla solo hay que pensar en un entorno de escritorio convencional en el que, al contrario que en un dispositivo móvil, las ventanas se pueden redimensionar a voluntad y la diferencia entre ambos conceptos se hace muy evidente:

Lo que ocurre es que esto es tan natural para nosotros que no pensamos en ello siquiera. En el caso de los dispositivos móviles, al ser todas aplicaciones a pantalla completa, la cosa se complica porque el navegador simula tener un ancho en píxeles inferior al que realmente existe y puede visualizar la pantalla con el objeto de que todo se vea mucho mejor.

¿Qué quiere decir esto en la práctica?

Pues quiere decir que, en un dispositivo móvil, la pantalla realmente tiene capacidad para mostrar imágenes de 2048 píxeles de ancho y 1536 de alto. Y si abres una imagen de estas dimensiones la mostrará perfectamente. Sin embargo, al visualizar algo en el navegador móvil del dispositivo, el área disponible "simula" una resolución de pantalla menor, en este caso la mitad de la capacidad de resolución real, e indica a la página que su resolución es de 1024x768. Es decir, en este caso el viewport es menor (la mitad) que las dimensiones de la pantalla.

¿Por qué se hace esto?

Bueno, pues porque si se usase toda la capacidad de la pantalla para visualizar la página, se vería muy pequeña y no sería útil.

Imagínate por un momento un diseño de página web no-responsiva que tiene un ancho de 2048px, y que se ve de fábula en el monitor de un ordenador con resolución FullHD+ (o sea, 2160 píxeles de ancho, algo mayor). Algo así:

Si la visualizas en un ordenador con una pantalla de menor resolución, digamos 1280x1024, lo que ocurrirá es que le saldrán unas barras de desplazamiento para que puedas moverte y ver la página entera., algo así:

Una cosa muy incómoda, pero al menos podrás ver la página.

Ahora imagina que ves la misma página en la pantalla del iPad 3, pudiendo aprovechar toda la resolución que tiene y que soporta de sobra ese ancho. Es decir, imagina que el viewport y la resolución del iPad 3 tuvieran las mismas dimensiones. ¿Qué verías en ese caso?... Pues algo diminuto que no te permitiría leer nada sin hacer zoom. Algo así:

Con el concepto de viewport, es como si la pantalla del iPad 3, a efectos del navegador, tuviera menos resolución y las cosas se verán a un tamaño más recomendable y fácil de gestionar. En el caso de nuestra página hipotética se verá un trozo de la misma y podrás desplazarte para ver el resto, lo cual, como en el ordenador de poca resolución, es una cosa incómoda, pero podrás leer.

Obviamente en una página bien diseñada con Responsive Web Design (RWD), se visualizaría bien, pues se detectaría una resolución determinada (1024px de ancho) que haría que los contenidos se distribuyesen correctamente y que se viesen a un tamaño apropiado sin necesidad de hacer zoom. Esto es lo que experimentas cada vez que ves una página móvil bien diseñada en un tablet o teléfono, por ejemplo así:

Donde todo se ve a un tamaño adecuado y además se redistribuyen (e incuso ocultan) elementos para aprovechar mejor el espacio (aunque esto no tiene nada que ver con el viewport, sino con RWD).

Cambiar el ancho del viewport en un dispositivo móvil

Es posible indicar otro ancho diferente para el viewport al que tienen por defecto los dispositivos, utilizando la etiqueta "meta" de nombre viewport, que va en la cabecera de la página:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

En este caso, esta etiqueta indica al navegador que se quiere establecer el ancho del viewport al número de píxeles de ancho que realmente tiene la pantalla del dispositivo. Fijando el factor de escala en 1.0 se evita el redimensionamiento del contenido para que quepa en la pantalla, lo cual podría provocar que el texto fuese demasiado pequeño. Además se permite que el usuario cambie ese factor de escala libremente.  Esta es la configuración recomendada para todas las páginas web, salvo casos especiales.

Con esta etiqueta podríamos establecer también un ancho diferente al que tiene por defecto. Incluso un tamaño mayor que la resolución física de la pantalla. En ese hipotético caso, el viewport sería mayor que las dimensiones de la misma (algo poco recomendable). También, si existiese un dispositivo (hoy en día ya no los hay) cuya resolución física fuese inferior a las dimensiones declaradas para el viewport, el efecto sería el mismo.

En resumen: es importante tener claro que el concepto de viewport y de resolución de pantalla son independientes, uno puede ser mayor que el otro y viceversa, y que su relación determina cómo se visualizará un contenido web en la pantalla.

Servir sitios y aplicaciones web en Azure usando un archivo ZIP (Run From Package)

30/08/2018
Artículo original

Se trata de una (relativamente) nueva característica de Azure Web Apps que ha pasado inadvertida para la mayor parte de los usuarios de la nube de Microsoft y que, sin embargo, es muy interesante.

Cuando creamos una aplicación Web en Azure disponemos de una carpeta /site/wwwroot en la raíz que es la que alberga los archivos de nuestra aplicación. El despligue de la aplicación a esta carpeta se puede hacer de múltiples formas: copiando por FTP los archivos, haciendo un push a una rama de un repositorio Git en Gihub o en cualquier otro servicio de Git en la nube (incluyendo un propio repo local en el Azure Web site), e incluso desplegando desde un disco en la nube como Dropbox o OneDrive. Al final se trata tan solo de hacer llegar a esa carpeta los archivos pertinentes. A partir de ese momento el Sitio Web de Azure los ejecuta (si son de aplicaciones backend) o los sirve a Internet (en caso de archivos estáticos).

Desde mediados de febrero de este año 2018 existe una nueva opción muy interesante denominada Run From Package, y que no es ni más ni menos que servir nuestros archivos directamente desde un archivo ZIP que puede estar ubicado en cualquier sitio del mundo. Es decir, lo puedes compartir en tu Dropbox, un una release de Github, en otro servidor o en un Blob de Azure Storage de la misma zona (que es lo que recomienda Microsoft), pero con que sea accesible públicamente llega.

Lo que hace el servicio es montar el .zip en la carpeta /site/wwwroot, como si realmente estuvieran allí, y actúa con ellos como si los hubiésemos copiado mediante cualquier otro medio de despliegue. Espera que lo aclare mejor, que la sutileza igual no se pilla bien:

Azure Web Sites NO copia el zip, lo descomprime en esa carpeta y luego se pone a usarlo. No. Lo que hace es utilizar el ZIP directamente desde su ubicación. ¿Cuánto mola eso?

Aparte de molar mucho, esto tiene varias ventajas:

  • Atomicidad: cuando ejecutas un sitio web desde wwwroot tienes muchos archivos y carpetas y debes gestionarlos uno a uno. Si por ejemplo los copias por FTP (o con cualquier otro método), no se copian todos a la vez, sino uno a uno, por lo que la aplicación puede quedar en un estado indefinido mientras se están copiando, con una mezcla temporal y dinámica de archivos en la que algunos se han actualizado y otros están todavía con la versión antigua. Con Run From Package esto no ocurre y el despliegue de la aplicación se hace para todos los archivos a la vez, en el momento en el que se monta el ZIP. A la hora de desplegar no hay que copiar los archivos sino que el ZIP se monta y en el momento de hacerlo todos los archivos están disponibles a la vez.
  • Rapidez: especialmente en aplicaciones grandes, con muchos archivos. Dado que por debajo la app lee los archivos desde el ZIP a medida que los necesita (con una pequeña caché) no es necesario copiar o descomprimir miles de archivos, por lo que el despliegue es muy, muy rápido aunque haya muchos o sean grandes. Esto hace que además se inicien muy rápido también.
  • Versionamiento: si vas dejando los ZIPs de todas las versiones que vayas desplegando en sus ubicaciones originales, cambiar a una versión anterior cualquiera si algo va mal es tan fácil como apuntar de nuevo al archivo antiguo. Incluso podrías tener varios slots de la misma aplicación, cada uno apuntando a versiones diferentes de la aplicación.
  • Servir aplicaciones para otras personas/empresas: simplemente les pasas la ubicación del archivo y podrán tener la aplicación funcionando en unos segundos, como veremos enseguida. Si sacas una nueva versión, actualizas el ZIP y todo el mundo se actualiza automáticamente (aunque no lo verán hasta que se reinicie la Webapp en Azure, cosa que se hace periódicamente o que se puede forzar si los avisas: enseguida lo veremos). Cada app que "tire" del ZIP además podría configurar unos parámetros propios desde la interfaz de Azure para, por ejemplo, usar su propio almacenamiento externo o una clave de API que necesite la aplicación.

Estas aplicaciones ejecutadas desde un ZIP remoto también tienen sus limitaciones:

  • La principal limitación es que, dado que se ejecutan desde un ZIP remoto, son aplicaciones de solo lectura. Es decir, no se puede escribir a disco desde las aplicaciones. Esto, en realidad, es casi más una ventaja que una limitación ya que una app en Azure debería escribir la información en cualquier caso a almacenamiento externo a las Azure Webapps. Por ejemplo, si los usuarios suben archivos anotarás el nombre del archivo en una base de datos (o una tabla de Azure Storage) y el archivo en sí deberías guardarlo en un Blog de Azure Storage. Así que realmente no es un grave problema.
  • Solo funciona (al menos por el momento) en Web Apps bajo Windows. De todos modos puedes usar .NET, .NET Core, Node.js Python, Java, PHP... no es una limitación tampoco demasiado grave.

Bueno, ya está bien de hablar. Vamos a la práctica. Simplemente quédate con un dato: WEBSITE_RUN_FROM_ZIP.

Este es el nombre del parámetro de la Azure Web App que debes configurar para indicarle en dónde está el ZIP que quieres utilizar. Vas a la interfaz de tu Azure Web App en el portal de Azure, en el apartado de "Settings" creas este apartado, y listo.

Nota: hace unos días anunciaron en GitHub que, dado que la característica se llama "Run From Package" (Ejecutar Desde Paquete), en breve podrás usar también el ajuste WEBSITE_RUN_FROM_PACKAGE en vez del anterior, que es el que yo uso en el vídeo. Funcionarán ambos siempre, aunque no aclaran cuál tendrá preferencia en caso de definir ambos.

Te lo enseño en la práctica en funcionamiento, en el siguiente vídeo:

[youtube:FWnsZpbSJX8]

Aquí te dejo también algunos enlaces de interés:

¡Espero que te parezca útil!

Cómo sustituir GIFs animados por vídeo y ganar en el proceso

29/08/2018
Artículo original

Seamos realistas: los GIF son un vestigio del pasado. Nacieron en los años oscuros de la prehistoria de Internet (siglo pasado) cuando reproducir vídeo en un navegador no era más que un sueño. Este formato permite únicamente secuencias de imágenes de 256 colores, con muy poca calidad. Pero este no es su mayor problema. El verdadero handicap que presentan es que ocupan un montón. Vete por ejemplo a Giphy y elige un GIF animado cualquiera que tenga imágenes reales. Si miras su información, verás que ocupan una barbaridad:

En el ejemplo del vídeo anterior, a pesar de ser tan aparentemente simple, con fondo neutro y todo, la animación ocupa casi 4MB.

Lo increíble es que este formato vuelve a estar de moda. De hecho, está más presente que nunca y vemos GIFs animados en casi todas partes: Twitter, programas móviles de mensajería, aplicaciones de chat... Se han convertido casi en un lenguaje de comunicación propio.

Sin embargo no todo lo que se llama GIF es un GIF en realidad.

Por ejemplo, en Giphy las animaciones que se muestran son realmente vídeos aunque en origen se tratase de un gráfico en formato .gif. Y si subes un GIF animado a Twitter verás que la aplicación lo convierte en MP4 por detrás y es lo que se usa. ¿Por qué? Pues porque el ancho de banda cuesta dinero y usar esas atrocidades directamente sería gastar mucho más. Además, para los usuarios no es lo mismo tampoco descargar un archivo de varios megas que uno mucho más pequeño. Cuanto más pequeño, antes descarga y mejor parece funcionar la página. Finalmente, el reproducir un GIF es más costoso para el navegador que reproducir el vídeo equivalente, que consume menos CPU y, en algunos casos, puede incuso hacer uso directo de la GPU para decodificar vídeo MP4.

En definitiva: usar GIFs directamente no se justifica más que en algunos pocos casos.

¿En qué casos? Pues por ejemplo si las animaciones representan acciones cortas en una pantalla. Sin ir más lejos, yo mismo cuando tengo que mostrar algo rápido (unos pocos segundos) en algún programa, grabando mi pantalla, utilizo el formato GIF, optimizándolo. El motivo es que las interfaces de la mayor parte de los programas de ordenador usan muy pocos colores (por regla general llega con 16) y además usan bordes muy bien definidos: justo lo que va bien con GIF y mal con vídeo muy comprimido. Si usas el programa adecuado en muchos casos puede ser más efectivo el GIF que un vídeo. Pero en la mayor parte de los casos, no será así. El mejor programa que conozco es para Windows y se llama ScreenToGif. Graba genial, te deja editar y optimiza las animaciones mucho. Y encima es gratis, pero ¡no dejes de donarles si lo usas mucho!

¿Cómo sustituir GIFs con vídeos de la manera óptima?

En la mayor parte de los casos, como digo, es más recomendable utilizar un vídeo que un GIF, ya que ocupará mucho menos. Pero la gracia de los GIF es que se reproducen automáticamente y entran en bucle, cosa que, por defecto, los vídeos no hacen ¿cierto?

La buena noticia es que es muy fácil emular este comportamiento con un vídeo en HTML5. Vamos a verlo.

1.- Convertir el GIF a vídeo MP4

Lo primero es obtener una versión en vídeo del GIF original.

Si es una animación de Giphy es algo directo, ya que en el apartado "Media" te ofrece directamente el enlace directo al vídeo:

En el caso del vídeo de la chica danzarina del ejemplo, el MP4 de la animación ocupa tan solo 334KB. Esto es un orden de magnitud menos que el GIF original. Será el que utilicemos.

En caso de que tengas acceso al archivo .gif original y necesites convertirlo a .mp4 tienes varias opciones. El programa Screen2Gif que mencioné arriba tiene esta capacidad pero necesitarás instalar la biblioteca ffmpeg, que entre otras cosas instala los drivers necesarios para hacer esta conversión. De hecho puedes usar directamente ffmpeg para hacer la conversión en cualquier plataforma (Windows, Mac o Linux) ya que funciona en todas ellas. Tan solo has de lanzar este comando desde un terminal:

ffmpeg -i miAnimacion.gif miAnimacion.mp4

Esta es la conversión básica, pero ffmpeg tiene cantidad de parámetros que puedes configurar, así que si quieres investigar en la documentación puedes hacer que comprima mucho más todavía que lo que lo hace por defecto, y dependiendo del vídeo le irán mejor unos parámetros u otros.

Yo, de todos modos, para no complicarme la vida muchas veces suelo utilizar el servicio online de conversión de archivos CloudConvert, que es capaz de convertir casi cualquier cosa que le eches, y además tiene una capa gratuita generosa que para conversiones esporádicas te saldrá gratis (si haces conversiones más a menudo es muy barato y funciona genial: totalmente recomendado).

El formato MP4-H264 está soportado por todos los navegadores del mercado. En ese enlace te explica cómo funciona y qué capacidades tiene.

Existen otros formatos más modernos, como WebM, auspiciado por Google que comprime aún un poco más que MP4 y está soportado por los principales navegadores (Chrome, Opera y Firefox), pero que todavía puede darte problemas con navegadores más antiguos o con Safari, que en Mac necesita usar Quicktime con un plugin para darle soporte. Hoy por hoy puede ser una segunda fuente de vídeo tras la principal en MP4, pero yo no me casaría con él del todo, utilizando MP4 como formato universal.

2.- Incluir el vídeo en la página de la manera adecuada

Para que nuestro vídeo sea totalmente equivalente a un GIF convencional tiene que cumplir tres cosas:

  1. Debe reproducirse automáticamente en cuanto cargue la página
  2. Debe reproducirse de forma continua, en bucle
  3. No se puede parar ni controlar, ni tampoco poner a pantalla completa.

En realidad hay una cuarta condición, pero que es consecuencia de la primera: no puede reproducir audio. Y digo que es consecuencia de la primera porque para que un vídeo pueda reproducirse de manera automática los navegadores modernos obligan a que sea de manera silenciosa, para no molestar a los usuarios. Por ello para que se cumpla la primera condición el vídeo debe estar mudo. Esto no es un problema ya que los GIF no soportan audio, así que en cualquier caso si queremos simularlo no deben tener sonidos.

Para conseguir esto con una etiqueta <video> de HTML5 lo único que tenemos que poner es esto:

<video muted autoplay loop playsinline></video>

Del nombre de los atributos es fácil deducir para qué sirven:

  • muted: hace que, aunque el vídeo tuviera audio, no se reproduzca. Es necesario ponerlo o el navegador no lo reproducirá automáticamente.
  • autoplay: en cuanto el vídeo se carga, se empieza a reproducir. Solo funciona si el anterior está presente.
  • loop: ejecuta el vídeo en bucle, empezando de nuevo cuando llega al final. Igualito que un GIF.
  • playsinline: le indica al navegador que queremos que este vídeo se reproduzca siempre en la página, es decir, que no se pueda poner a pantalla completa.

Fíjate en que al no tener el atributo controls puesto lo que se consigue es que no se muestren los controles de reproducción, que están desactivados por defecto salvo que se le ponga este atributo.

Vale, solo queda ponerle la fuente de vídeo, que en este caso será la dirección pública en Internet en la que hayamos "colgado" el vídeo, para lo cual se usa el atributo src:

<video muted autoplay loop playsinline src="https://www.miservidor.com/media/miVideo.mp4">
</video>

En nuestro caso, el vídeo equivalente al GIF queda de la siguiente manera:

¿A que no se nota que es un vídeo en vez de un GIF?

La única forma de verlo (y de paso saltarse las restricciones) es pulsar con el botón secundario del ratón sobre éste, que muestra un menú que nos permite pararlo, activar los controles, etc...:

¡Espero que te resulte útil!

El developer feliz: qué buscamos y qué necesitamos

26/08/2018
Artículo original

Developer Feliz

Cuando preparaba “El Feliz Developer”, la charla para T3chFest que me animó a preparar un estudio sobre motivaciones profesionales en el sector IT, una de las cuestiones fundamentales en la investigación, era definir las necesidades más importantes de los trabajadores. El objetivo era reflexionar sobre qué cosas son las que buscamos, las que necesitamos, en nuestra vida y, sobre todo, también en el trabajo.

Hoy intentaremos analizar precisamente cuáles son nuestras necesidades, y por qué algunas son más importantes que otras dentro del entorno profesional.

¿Qué es lo que de verdad queremos?

Lo ideal antes de empezar a leer este artículo es que te sientes con una hoja de papel al lado. ¿Ya la tienes? Escribe en un lado cuáles son los factores que hacen que te sientas feliz en tu trabajo. Escribe en otro lado cuáles son los factores que podrían hacer que fueras infeliz en tu trabajo

Genial, ahora puede seguir leyendo. Pensar en este tipo de cosas sin conocer las clasificaciones teóricas, te permite ser mucho más sincero contigo mismo.

Los profesionales que respondieron a la encuesta de El Feliz Developer” dijeron que lo más valorado en su trabajo era, en este orden:

  • flexibilidad
  • salario,
  • buen ambiente
  • uso de las tecnologías más actuales.

Por otro lado, lo que más se echaba en falta era:

  • formación
  • salario acorde a las expectativas
  • uso de metodologías ágiles

La teoría de Herzberg: necesario, pero no suficiente para hacernos felices

¿Hasta qué punto piensas que tener una buena silla, la temperatura de la oficina, o una luz que no parpadee sobre ti te hace feliz?

Hay dos teorías, con sus matizaciones, claro, que nos ayudan a explicar muy bien cuáles son las necesidades y motivaciones que tenemos en el ambiente profesional.

Una de estas teorías es la de Herzberg, que analiza qué factores generan satisfacción, y qué factores generan insatisfacción. Lo realmente interesante de esta teoría, es que hay factores que ayudan a aumentar nuestra satisfacción, pero tienen muy poco efecto sobre la insatisfacción, y viceversa punto hay factores que cuando faltan causan insatisfacción, pero que estén presentes no garantiza la satisfacción de los trabajadores: son necesarios, pero no suficientes.

¿Hasta qué punto piensas que tener una buena silla, la temperatura de la oficina, o una luz que no parpadee sobre ti te hace feliz? No es algo que añadiríamos como algo que nos motivaría, pero sin embargo, si hace demasiado frío o calor, hay olor desagradable o ningún ascensor funciona, nos sentiriamos muy insatisfechos. Este tipo de reflexiones nos ayuda a valorar y entender la importancia de las “pequeñas” grandes cosas , y a comprender por qué desde la empresa es importante cuidar estos detalles, que muchas veces damos por supuesto.

¿Eres capaz de definir cuáles son los factores que deberían cumplirse, obligatorios si cambiaras de trabajo?

Maslow y la jerarquía de nuestras necesidades

Ahora, ponte delante de tu hoja de papel. ¿Eres capaz de definir cuáles son los factores que deberían cumplirse, obligatorios si cambiaras de trabajo? ¿Puedes definir por otro lado cuáles supondría un plus, pero son menos importantes para ti?

Muchos ya conoceréis la Pirámide de Maslow. Es nuestra segunda teoría: fue propuesta por Maslow en los años 40 que trata de jerarquizar las necesidades del ser humano: las ordena según su orden de prioridad. Estas necesidades están orientadas a la vida en general, y se han interpretado varias veces por diferentes autores.

Estas necesidades son básicas (las que nos permiten mantenernos vivos), seguridad, afiliación (como nos relacionamos) , reconocimiento (como nos perciben). Pueden trasladarse al entorno profesional, como vemos en la pirámide.

Piramide de Maslow adaptada al trabajo

Desde luego, y como podremos imaginar, este orden de necesidades puede cambiar: dependiendo de nuestra situación, valoramos más unas cosas que otras (después de una mala experiencia en un ambiente conflictivo, primaremos las necesidades de socialización o afiliación, si estamos en un momento en el que es muy necesario el crecimiento profesional por sentirnos encasillados, serán fundamentales las opciones de promoción al buscar un nuevo empleo.

Por ejemplo, a partir de cierta banda salarial. ¿Hay una diferencia real entre cobrar 80 u 85k al año?, el dinero tiene menos importancia en detrimento del tipo de trabajo, el clima laboral…. pero esto solo ocurre cuando ciertas bases están cubiertas

Es importante entender que las necesidades han de cubrirse primero desde la base e ir subiendo: no podemos hablar a alguien de que le vamos a dar entradas para ir al cines si le estamos pagando un salario ínfimo o no le damos herramientas mínimas para trabajar.

Por supuesto, en muchos casos, un problema social de afiliación puede convertirse en un problema de base: machismo, acoso, si afecta a la seguridad...

Cambiamos lo que somos, lo que necesitamos… y cómo influimos

Como curiosidad: fíjate en nuestra pirámide: las bases, en azul (básicas y seguridad) deben ser aseguradas por la empresa, es su responsabilidad. La parte verde es responsabilidad repartida, entre la empresa y nosotros (proceso de selección, relaciones informales) La cúspide depende más de nuestra propia percepción.

Y, una última observación. Vuelve a pensar en esos factores que hacen que te sientas bien en el trabajo. En tu día a día: la limpieza la seguridad… piensa en el trabajo de las personas que se esfuerzan por que tu base de la pirámide sea lo mejor posible. Quienes reparan tu ascensor, vacían tus papeleras, vigilan los accesos y se encargan de que el baño esté limpio. También tienen su propia pirámide, sus necesidades y sus motivaciones.

Éste puede ser también un buen ejercicio autoconocimiento. ¿Cuáles son los factores que has considerado necesarios (imprescindibles para un cambio)? ¿cuáles son los que has considerado motivadores (un plus)? ¿Qué puedes exigir a la organización para que tu pirámide mejore? ¿Cómo puedes afectar tú a la pirámide de los demás? ¿Qué soluciones de la pirámide aporta tu trabajo, y tu actitud?

Este tipo de reflexiones nos ayudan a conocer mejor cómo somos, cuáles son las necesidades que ahora no tenemos cubiertas, y cómo hemos evolucionado a lo largo de los años, tanto nosotros como nuestras motivaciones.

Foto | Raimond Spekking Video | El feliz developer | T3chFest 2018

GAMBADAS: engañar al GPS para enviar a tu coche autónomo directo contra el tráfico

24/08/2018
Artículo original


Foto de NESA by Makers en Unsplash

Cada día millones de personas utilizan el sistema global de posicionamiento americano, GPS. Todos los móviles llevan un sensor GPS incorporado que recibe señales de su constelación de satélites y mide desfases para determinar con precisión pasmosa la ubicación actual. Muchos coches también los incorporan, y en el futuro próximo los coches autónomos estarán al orden del día, y también lo usarán para apoyarse en sus datos de cara a la navegación.

Unos investigadores de Virginia Tech, la Universidad China de Ciencias Electrónicas y Tecnología y Microsoft Research han creado la prueba de concepto de un aparato que, pegado debajo de un coche puede engañar a los GPS cercanos para obligarles a cambiar la ruta y enviarte a otro lado o, directamente, meterte en una dirección prohibida en contra del tráfico, por ejemplo. El dispositivo está construido con Raspberry Pi, un dispositivo de radio que se puede definir con software llamado HackRF One, una antena y una batería. Invirtieron en total, debido al coste del HackRF One: 223 dólares (unos 190 euros).

El aparato se pega en los bajos de un coche que queremos atacar, que anula las señales del sistema GPS y emite unas propias simuladas que engañan al dispositivo receptor. Además utiliza ciertos algoritmos para simular rutas "fantasma" por las que quiere enviar al vehículo, pudiendo cambiar las sindicaciones que devuelve tu software de mapas. Gracias a esto el ataque se puede utilizar para enviarte a otro sitio, retrasar a un vehículo de emergencias o, en un caso extremo, provocar un accidente en un coche autónomo.

Este tipo de ataque funciona mejor en áreas urbanas, ya que hay muchas más posibilidades de cambiar rutas y, si son grandes ciudades, es más probable que el conductor no conozca los sitios por los que se mueve. Y mejora aún más si el atacante tiene una idea aproximada de a dónde se dirige el vehículo. Además de pegarse el aparato al fondo del coche, es posible realizar el ataque con éxito usando un dron que vuele por encima del vehículo.

Según los propios investigadores "la amenaza se volverá más realista a medida que los fabricantes de coche añadan capacidades de pilotaje automático a los coches, de modo que las personas estén menos involucradas en la conducción hasta el punto de no estarlo en absoluto cuando los coches autónomos estén en la carretera".

Este tipo de ataques se han venido advirtiendo desde hace años, e incluso hace un lustro se registró un ataque real de este estilo contra un súper-barco de lujo en alta mar. Pero ahora es mucho más accesible a cualquiera, y sobre todo, muy barato. Y cada vez hay más dependencia de este tipo de sistemas.

El estudio, de tan solo 18 páginas, se puede leer online, y contiene bastantes detalles sobre cómo armar el invento y su funcionamiento.

Sería interesante saber si los sistemas equivalentes a GPS, como el GLONASS ruso o el (esperemos que) inminente Galileo europeo, son vulnerables también a este tipo de ataques o no. La mayor parte de los móviles actuales suelen tener soporte también para estos, aunque no los usemos.

Diferentes configuraciones en Visual Studio para generar diferentes ediciones de una aplicación

20/08/2018
Artículo original

Si desarrollamos una aplicación con .NET que se comercializa en distintas ediciones (por ejemplo Standard y Professional), cada una de las cuales ofrece diferentes capacidades/características y diferentes precios, es interesante poder generar físicamente distintos .exe o .dll para cada edición. Por ejemplo, MiSuperApp-Standard.exe y MiSuperApp-PRO.exe.

Una opción muy poco apropiada es mantener dos proyectos diferentes para cada edición, o dos ramas en Git para gestionarlas.

Otra buena opción si no tenemos demasiadas ediciones distintas es la de crear diferentes configuraciones de compilación para poder generar físicamente ensamblados diferentes en cada caso.

Por defecto, cuando creamos un proyecto en Visual Studio solo tenemos dos configuraciones hechas: Debug y Release, que utilizamos respectivamente para desarrollar/depurar la aplicación y generar la versión que vamos a distribuir:

Lo primero que vamos a hacer es disponer de diferentes configuraciones para las diferentes ediciones. Para ello  pulsamos en la opción "Configuration Manager..." del menú de la figura anterior y nos aparecerá una ventana con la gestión de las configuraciones. Creamos una nueva configuración para cada edición de nuestro producto, tal y como muestro en esta animación:

En nuestro ejemplo creamos dos llamados "Standard" (que se ve en la animación anterior) y "Professional". Además eliminamos "Release" ya que no la necesitaremos y las otras dos las hemos copiado de ésta:

Ahora que ya tenemos las configuraciones, lo siguiente que debemos hacer es crear símbolos de compilación condicionada para dichas configuraciones. Esto nos va a permitir posteriormente incluir instrucciones para el compilador de modo que podamos excluir o incluir ciertos fragmentos de código dentro del ensamblado final (.exe o .dll que generemos).

Crear estos símbolos es muy sencillo. Solo es necesario pulsar con el botón derecho sobre el proyecto en el "Explorador de Soluciones" de Visual Studio e irnos a la pestaña "Build". En el desplegable de Configuración elegimos cada uno de las configuraciones nuevas que hemos creado y en el primer cuadro de texto escribimos, en mayúsculas preferiblemente, un nombre sencillo y corto con el que identificar cada una de ellas a la hora de compilar, por ejemplo, en nuestro caso hipotético "STD" y PRO", grabando a continuación. Lo vemos mejor en este mini-vídeo:

Ahora ya tenemos casi todo lo que necesitamos. Vamos a tocar nuestra súper-sencilla aplicación de ejemplo para que muestre por consola algo diferente en función de la configuración. Para ello haremos uso de pragmas condicionales de compilación, que nos permiten tomar decisiones en función de ciertas condiciones. Son líneas especiales que comienzan con una almohadilla. Por ejemplo, podemos escribir:

#if STD
//Código que sea...
#endif

y lo que está entre estos dos "pragmas" solo se compilará en caso de que se cumpla la condición: en este caso solo si estamos en el modo de configuración "Standard", ya que STD es el símbolo que hemos definido para este caso.

También podemos usar un #else:

#if STD
//Código que sea...
#else
//Código en caso de que no se cumpla
#endif

 En nuestro ejemplo podemos verlo en el siguiente vídeo corto:

Con esto ya tenemos mucho andado y conocemos lo básico de trabajar de esta manera.

De todos modos me gustaría comentar algo más que no es tan común:

Cómo generar un .exe o .dll de nombre diferente según la configuración

Puede que nos interese hacer esto y que, en el caso de nuestra hipotética aplicación de ejemplo, se llame de modo diferente según si es la edición estándar o la profesional, por ejemplo: MiApp-STD.exe y MiApp-PRO.exe respectivamente.

Para lograr esto no nos queda más remedio (al menos que yo sepa) que tocar directamente el archivo del proyecto de Visual Studio, es decir, el .csproj que tiene la información sobre el mismo.

Para ello debes cerrar el proyecto en Visual Studio, localizar el archivo .csproj, y abrirlo usando algún editor de texto (el propio Bloc de notas te vale, aunque yo prefiero usar Notepad++ que es mucho mejor y reconoce el archivo correctamente). Una vez abierto debes localizar los nodos <PropertyGroup> de cada una de tus configuraciones y añadirle un nuevo sub-nodo llamado <AssemblyName> que sirve para especificar el nombre exacto que queremos para el ejecutable o DLL final. Indicamos ahí el nombre que queramos, vamos a verlo:

Ahora ya podemos abrir el proyecto de nuevo y compilarlo usando las diferentes configuraciones. Obtendremos un ejecutable diferente según las indicaciones que hemos dado, con el nombre que nos interese. Veámoslo en un último vídeo corto:

Como podemos comprobar obtenemos exactamente lo que buscábamos.

Te dejo el proyecto de ejemplo en un ZIP (5 KB) para que puedas probarlo. Cambia la configuración del proyecto y genera el ejecutable correspondiente para poder probarlo.

¡Espero que te sea útil!

3 formas de inicializar colecciones Java a la hora de declararlas

20/08/2018
Artículo original


Foto por Aaron Burden en Unsplash

En muchos lenguajes, al definir una colección como un array o una lista podemos asignarle una sucesión de valores de forma que los contenga como elementos. En Java, podemos hacer esto con arrays básicos:

int[] miArray = new int[] {3, 1, 4};

Sin embargo, a la hora de inicializar una colección de objetos de una clase, la misma sintaxis no es aplicable. En su lugar, habitualmente debemos recurrir a los métodos que añaden elementos, como add en el caso de las clases con interfaz List:

List<Integer> miLista = new ArrayList<Integer>();
miLista.add(3);
miLista.add(1);
miLista.add(4);

En este post te enseño tres vías para conseguir introducir los elementos en la colección en menos código y con mayor legibilidad.

Métodos de utilidades

Una de las estrategias posibles para hacer más compacto este código es usar el método asList de la clase Arrays de herramientas para manipulación de vectores. Se trata de una solución muy simple que reduciría el código a la siguiente línea:

List<Integer> miLista = Arrays.asList(3, 1, 4);

Un detalle a tener en cuenta es que este método construye una lista de tamaño fijo, por lo que no se podrá ampliar. Para contar con esa posibilidad debemos realizar la conversión a una clase que implemente List:

List<Integer> miLista = new ArrayList<Integer>(Arrays.asList(3, 1, 4));

Inicialización de doble llave

Otra posibilidad es aprovechar un patrón de sintaxis conocida como la inicialización de doble llave. Esta consiste en abrir una llave que crea una subclase anónima, y una segunda llave que comienza un inicializador de instancia. Dentro de este inicializador podemos recurrir a los métodos del objeto que estamos definiendo de la siguiente forma:

List<Integer> miLista = new ArrayList<Integer>() {{ add(3); add(1); add(4); }};

Esta sintaxis es sorprendente y muy versátil, ya que no sólo se reduce a la funcionalidad de añadir elementos sino que se puede utilizar para realizar otras tareas de inicialización, como la definición de componentes de una interfaz de usuario. A pesar de esto, en muchos casos no es recomendada ya que la creación de una subclase anónima puede conllevar cierta sobrecarga.

Métodos factoría de Java 9

Una tercera opción que se ha introducido en Java 9 es el uso de métodos factoría ya incluidos en el lenguaje. Las interfaces List, Set y Map proporcionan un método of que nos permite hacer justo lo que necesitamos: especificar varios elementos a la hora de declarar una colección. El siguiente es un ejemplo de su uso:

List<Integer> miLista = List.of(3, 1, 4);

Esta opción no es totalmente equivalente a las anteriores ya que el método of construye colecciones inmutables. Para permitir modificar y añadir elementos, tendríamos que recurrir al constructor de la colección que deseemos:

List<Integer> miLista = new ArrayList<Integer>(List.of(3, 1, 4));

Espero que estos trucos te sean útiles para manejar pequeñas colecciones más fácilmente en Java.

Fuentes y más información:

SQL Server: cuáles son las diferencias entre @@identity y Scope_identity

14/08/2018
Artículo original


Foto de Kyle Glenn en Unsplash

Cuando insertamos un registro en una tabla de una base de datos, lo más habitual es que se genere automáticamente un nuevo identificador único para el nuevo registro, generalmente un autonumérico. Esto significa que empezamos en el 1 y para cada nuevo registro que añadimos se va aumentando de manera automática a 2, 3, 4... y así sucesivamente. Esto que parece una tontería, tiene muchas implicaciones ya que este identificador es el que vamos a utilizar luego para relacionar el nuevo registro con cualquier otra tabla de la base de datos que necesite utilizarlo. Por ejemplo, una factura y sus líneas de factura están relacionadas a partir del identificador de la cabecera. Cosas por el estilo...

El caso es que la generación de este autonumérico, que parece una tontería, es mucho más compleja de lo que parece ya que se debe tener en cuenta una cosa muy importante: la simultaneidad. Cuando tú haces pruebas en tu equipo de desarrollo, añadir nuevos registros es muy fácil: solo estás tú. Pero en un sistema real en el que pueden estar entrando miles de usuarios a la vez y añadiendo registros en las mismas tablas, el sistema debe asegurar que la secuencia se cumple sin dejar huecos y que no se producen bloqueos importantes.

Una manera ingenua de obtener el autonumérico de un registro que acabas de insertar sería simplemente obtener el máximo de esos números justo a continuación de hacer el INSERT correspondiente. Pero en un sistema en producción no te funcionará con garantías salvo que provoques un bloqueo, ya que mucha gente puede estar introduciendo datos a la vez y entre que insertas el tuyo y lees el máximo puede haberse insertado otro. Es un problema peliagudo.

Cada sistema gestor de base de datos relacionales (SGBDR) que hay en el mercado aborda el problema con su propia filosofía. Ya os hemos explicado aquí cómo obtener el último autonumérico insertado en los más utilizados: Oracle, MySQL y SQL Server.

En el caso de SQL Server explicábamos que la forma de hacerlo era utilizando la instrucción SCOPE_IDENTITY(). Puedes repasarlo en el enlace anterior. Sin embargo SQL Server ofrece al menos 3 formas de obtener el último ID insertado. Aunque puedan parecer iguales, no son equivalentes y conocer sus diferencias es muy importante:

  • @@Identity: devuelve el último ID en la misma conexión.
  • Scope_identity(): la que recomendamos, devuelve el último ID creado en la misma conexión y el mismo contexto (de ahí su nombre). En este caso el contexto se refiere a la consulta o procedimiento almacenado actual.
  • ident_current(nombre): devuelve el último ID de la tabla que le indiquemos (el que haya en ese momento)

En la mayor parte de los casos @@identity y scope_identity() se comportan igual, pero no siempre es así.

Por ejemplo, si tenemos un disparador (trigger) en nuestra tabla y lanzamos una consulta de inserción que genera un nuevo registro y por lo tanto un nuevo ID, si el trigger a su vez genera otro registro en otra tabla (y probablemente otro ID en ésta), en esta situación @@identity nos devolverá el ID del registro que ha insertado el disparador, no el ID de la tabla que hemos actualizado (lo cual no es lo que queremos casi nunca), ya que te devuelve el último que se haya generado en esa conexión, tal y comentábamos en la lista anterior. Sin embargo, en este ejemplo, scope_identity() nos devuelve el identificador que esperábamos (el de la inserción en nuestra tabla) ya que siempre devuelve el del contexto actual, que en este caso es nuestra consulta de inserción.

Este es el motivo de que normalmente se recomiende el uso de scope_identity().

¡Espero que te resulte útil!

Página Anterior Página Siguiente