Desarrollos nativos o híbridos: ¿se acabarán comiendo los nativos a los invasores de tecnología híbrida? ¿O serán los nativos los que acaben en una reserva, como pasó en los EE.UU.?

Este choque de civilizaciones, que se desarrolla de forma inmisericorde en nuestros bolsillos y en nuestros corazones, está muy lejos de llegar a su fin.

Para tratar de resolverlo tenemos, en la esquina derecha, con 75kg de peso y múltiples aplicaciones híbridas a sus espaldas a Arturo Batanero, arquitecto front-end y siempre a punto de salirse de la autovía al ver el cartel de “Córdoba”, preguntándose si está bien escrito.

Y en la esquina izquierda, con 77 Kg de peso y un montón de aplicaciones nativas desplegadas, tenemos a Miguel Sesma, desarrollador Android e iOS, artesano del software y siempre probando lo nuevo.

Ahora el árbitro sobre el ring eres tú. ¿Se ganará el combate por puntos? ¿O será por KO? ¡Vota!

Arturo Batanero

Arturo Batanero

Entendiendo por aplicación nativa la desarrollada con el SDK de cada plataforma, una aplicación híbrida añade, por definición, un cierto nivel de indirección entre su código fuente y el ejecutable con el que interactúa el usuario, que no existe o es más ligero en la nativa.

Miguel, estarás de acuerdo conmigo en que, desde el punto de vista de rendimiento, la aplicación nativa siempre tendrá un extra de ventaja, el cual puede ser clave para la percepción de calidad de la experiencia de usuario, dado que conseguir rapidez de respuesta y mover el UI a 60fps es una condición necesaria.

Y, sin embargo, es indudable la tendencia que venimos viendo en los últimos años y que seguirá así en los próximos: los desarrollos híbridos multiplataforma irán comiéndole cada vez más cuota de mercado a los nativos, al punto de convertirlos en minoritarios.

¿Por qué va a ser así?

Bueno, todos sabemos que ya ha pasado anteriormente: en el entorno de escritorio, gracias a que el incremento progresivo de la potencia del hardware permitió la existencia de Java, vimos cómo era posible realizar de forma efectiva aplicaciones que ya no eran “nativas”, sino compiladas a un código intermedio y ejecutadas por una máquina virtual, mandando en consecuencia a los programadores de C, C++ y ensamblador nativos, sino a una reserva, si reduciendo bastante su cuota de mercado (un nicho privilegiado, por cierto).

Tú, al igual que yo, sabes que en la actualidad ya hay aplicaciones híbridas (en el sentido del artículo, de utilizar tecnología Web) para escritorio que sustituyen de forma efectiva a aplicaciones hechas en Java o C++, incluyendo tipos de aplicaciones exigentes, como clientes de redes sociales o entornos de desarrollo (¿cuántos saben que el cliente Slack o Visual Studio Code son en realidad aplicaciones híbridas?).

Mi apuesta es que en el entorno móvil previsiblemente acabará sucediendo lo mismo: se seguirá reduciendo la diferencia de rendimiento entre híbridas y nativas, según continúe aumentando la potencia del hardware y mejoren las implementaciones de las máquinas virtuales JS y del DOM local.

Siempre existirá esa diferencia de rendimiento, pero se irá volviendo cada vez más irrelevante a la hora de escoger tecnología, como llevamos observando los que estamos en esto ya unos años.

De dónde venimos

Las aplicaciones híbridas de primera generación hacían uso de un navegador (WebView) local o importado, que era presentado al usuario a toda pantalla y que, mediante HTML+CSS+JS, simulaba el UI nativo de cada plataforma.

Es el enfoque de Phonegap, Cordova en plataformas móviles o de Electron o NW.js en desktop (estos añaden un Node.js al navegador, para construir el ejecutable integrando ambos).

Obviamente, este planteamiento está limitado por la calidad de la implementación del navegador, que si bien en desktop es rápido (el ejemplo de antes, Visual Studio Code, está hecha en Electron y es indistinguible de una aplicación nativa) en el entorno móvil aún exige ser estratégico con lo que implementas, requiriendo siempre de un esfuerzo extra de optimización para acercarte a los 60fps.

Hacia dónde vamos

La nueva tendencia en aplicaciones híbridas es saltarse el DOM del navegador y utilizar directamente componentes nativos, orquestados desde una máquina virtual JavaScript, que es quien ejecuta el programa JS.

Ya no se trata de un WebView a toda pantalla. Ahora tenemos un UI formado por controles nativos de Android o iOS, configurados y posicionados mediante CSS y un SGML que recuerda a HTML, y que son controlados desde una máquina virtual JS (V8 en Android y el motor nativo en iOS) que es quien corre el programa, interactúa con el OS subyacente y abstrae las diferencias entre las diferentes plataformas, entre otras cosas.

Es el enfoque de NativeScript o React Native, todavía en sus inicios, como bien dices Miguel, pero en proceso rápido de maduración.

Con ellas se pueden montar aplicaciones (ver en Android o iOS) que, por poner un ejemplo, muevan una lista de cientos/miles de fotos a 60pfs como una nativa... porque son nativas en ese sentido.

Ofrecen lo mejor de ambos mundos: unir la experiencia de usuario nativa con la experiencia de desarrollo Web.

Si además la aplicación {NS} está desarrollada en Angular, se pueden incorporar todas sus ventajas: gracias a su separación radical de vistas y modelos te permite correr la misma aplicación en nativo y en web (has sido un chico malo aquí, Miguel) sólo ajustando las vistas, así como correr el framework y la app en uno o múltiples hilos de ejecución, dejando el hilo principal sólo para manejar el UI y tratar con el OS subyacente.

Y a la hora de hacer esto último, las cosas también mejoran mucho: en NativeScript, por ejemplo, ya no estamos limitados, como en Cordova, a plugins que deben ser programados para cada plataforma y así poder hacer uso de APIs nativas.

Ahora puedes llamar directamente a cualquier función del OS, gracias a un proxy de conversión de tipos que, si bien añade un nivel de indirección, te permite acceder a la totalidad de la funcionalidad de cada plataforma.

Ya no necesitas que un programador nativo te haga un plugin para conseguirlo. Los plugins sólo serían necesarios ya para integrar, por ejemplo, librerías de código nativo preexistentes, no para hacer uso del OS.

Aparte, el equipo de NativeScript ha desarrollado una capa de abstracción de las diferentes plataformas. Te permite, por ejemplo, acceder a un fichero local del mismo modo en todos los OS, pero que si quieres abrirlo con el API nativo, lo puedes hacer.

¿Código nativo? ¿seguro?

En Android, el código ‘nativo’ tampoco es que lo sea tanto. En sus primeras versiones, el código Java se compilaba ‘Just in Time’ en bytecodes sobre la máquina virtual Dalvik, no siendo tan diferente de la compilación JIT del código JS sobre una máquina virtual como V8.

Desde luego no conceptualmente y, eliminando el obstáculo del DOM, cada vez menos en rendimiento. Y si no te lo crees, mira las prestaciones de Node en el servidor, donde no existe el DOM.

Ahora con ART, en lugar de Dalvik, el código se compila en tiempo de desarrollo, que, a costa de un mayor tamaño, gana en velocidad, pero vamos, nativo, nativo, tampoco es.

iOS, en cambio, sí que hace una compilación de bajo nivel, motivo por el que se permiten usar procesadores menos potentes y con menores requerimientos de memoria, en parte gracias a que controlan el hardware sobre el que corre todo.

Por ello, una aplicación Objective-C o Swift sí que me parece verdaderamente “nativa” en comparación a una aplicación Android en Java o en Kotlin (que, por cierto, Miguel, me alegro de que sigan el modelo de TypeScript).

Clash of Clans

La evolución del hardware y de las tecnologías Web (WebGL será el siguiente salto en móvil, accediendo directamente a la GPU como ya hacemos en desktop) seguirán reduciendo la ventaja de rendimiento de las nativas.

Por el contrario, las ventajas de las híbridas se mantendrán igual que ahora:

  • Coste de desarrollo: tratándose de desarrollos híbridos multiplataforma, el coste siempre será inferior y, según las circunstancias, muy inferior, según aumentemos el número de plataformas de distribución y/o el tamaño del proyecto.
  • Una aplicación híbrida podría distribuirse potencialmente en iOS, Android, Windows Phone, MacOS, Windows y Linux con esencialmente la misma base de código, el mismo equipo de desarrolladores y con una menor necesidad de coordinación, al ser un solo equipo.
  • Tiempo de desarrollo: el “time to market” para las aplicaciones híbridas es inherentemente más reducido que el de las nativas.
  • Puestos a resolver la misma funcionalidad (porque esquivando fácilmente el gancho que me lanzas, Miguel, se pueden realizar el mismo tipo de aplicaciones si están basadas en controles estándar, que son la mayoría) con tecnologías Web el tiempo de desarrollo resulta ser casi siempre menor.
  • Coherencia y cohesión de funcionamiento: podrá y deberá haber diferencias de adaptación entre plataformas a nivel de vistas, en términos MVC, pero a nivel de modelo la aplicación será sólo una, lo que significará una velocidad de avance similar por plataformas y una resolución de bugs integrada, porque habrá una sola base de código y un único equipo trabajando, no varios.
  • Actualizaciones indoloras: una aplicación híbrida puede, si así se desea, ser actualizada sin tener que pasar de nuevo por la tienda de aplicaciones. Con una nativa no te libras de pasar por un nuevo proceso de aprobación que, especialmente con Apple (aunque vaya mejorando con el tiempo), nunca se podrá comparar en tiempos y costes a tener tú mismo el control de lo que llega a los usuarios.

En definitiva, si se trata de afrontar un desarrollo que:

  • Sea multiplataforma.
  • Que se pueda construir con controles nativos estándar.
  • Donde el coste sea un factor clave.
  • Donde el tiempo de desarrollo también sea fundamental.

Entonces, si no ya en el presente, en el futuro próximo la elección tecnológica será mayoritariamente híbrida.

El desarrollo nativo seguirá siendo necesario donde se necesite ese punto extra de rendimiento y de cercanía al hardware, pero si las aplicaciones deben cumplir los requerimientos anteriores, serán mayoritariamente híbridas.

Mucho me temo que los nativos aquí también acabarán en la reserva… aunque siempre podrán abrir un casino y vivir como reyes.

Miguel Sesma

Miguel Sesma

Arturo, actualmente más de la mitad de la interacción digital del usuario con la empresa se genera desde dispositivos móviles. Es por ello que la imagen de empresa y la fidelización de los clientes depende de la calidad de las apps.

Las aplicaciones nativas se desarrollan en Objective C o Swift en iOS y Java o Kotlin en Android. Disponer de Swift y Kotlin nos permite una programación utilizando paradigmas de última generación, como la programación funcional o la garantía y robustez que proporciona el que sean lenguajes fuertemente tipados con null-safety. Arturo, Typescript se pensó para que Javascript pudiera tener tipos estáticos :)

Acceso a la plataforma

Las apps nativas permiten el uso de las funciones avanzadas de cada plataforma, sacan provecho de los procesadores gráficos y exprimen cada funcionalidad a un nivel al que un plugin de una app híbrida no puede acercarse.

Ejemplo: el plugin de cámara de React Native soporta 12 propiedades y unos ocho métodos mientras la cámara de Android son decenas de clases con centenares de métodos y propiedades.

Las apps nativas, al no necesitar plugins que tardan tiempo en ser desarrollados, pueden usar las últimas características de la plataforma tan pronto como estén disponibles. Recordemos que Apple actualiza iOS en dispositivos antiguos y Android utiliza librerías de compatibilidad para que versiones anteriores soporten las nuevas funciones.

Aun existiendo plugins para plataformas híbridas que cubren la mayoría de las funcionalidades del dispositivo, las funciones más evolucionadas, técnicas o modernas quedarán fuera de nuestro alcance y la flexibilidad de uso siempre será inferior al API nativa.

Por supuesto podremos escribir nuestros propios plugins, pero se precisarán programadores nativos para ello. El acceso a código nativo tampoco es posible más que a través de un plugin que ralentiza cada llamada, el proxy que comentas, Arturo.

Rendimiento

La calidad percibida comienza con el rendimiento, Swift compila a código máquina a través de LLVM y Kotlin lo hace a través de JVM y ART además de poder utilizar C / C++ cuando sea necesario. Ambas plataformas aprovechan las funciones de los componentes de la UI: así UITableView o RecyclerView pueden mostrar listas con transiciones complejas, animaciones avanzadas y gran suavidad de desplazamiento consumiendo mucha menos memoria.

Esto es precisamente el mayor problema de las apps híbridas: en el caso de las que se ejecutan en una Webview (Phonegap, Ionic, etc.) el rendimiento depende mucho de la calidad de ésta, rendimiento que es muy variable dependiendo no solo de la plataforma, sino del dispositivo y la versión del sistema operativo. En las que se ejecutan en su propia máquina virtual Javascript (React Native, Nativescript...), el enorme peso de esta máquina hace que el consumo de memoria y recursos las desaconsejan en dispositivos de gama baja o media.

Ya sabemos que Javascript no es especialmente eficaz manejando la UX: como ejemplo, uno de los usos habituales de una app es mostrar listas. Una lista nativa renderiza solo lo que sale por pantalla, una lista web renderiza todos los elementos lo que puede ser lento si son muchos. Pare evitarlo se puede utilizar Lazy Load, pero seguirá lejos del rendimiento nativo.

Arturo, tú mismo comentas cómo se solucionan los problemas de las aplicaciones híbridas: haciéndolas más nativas. React Native y Nativescript utilizan componentes de UX nativos para intentar mejorar el rendimiento. Y aunque es cierto que solucionan problemas como el de las listas que comentaba, introducen otros nuevos: no podemos hacer la aplicación web con ellas.

Podremos generar apps para las plataformas que dispongan de sus propios entornos gráficos (iOS, Android, Windows Phone), pero al no estar basadas en HTML, sino como bien dices, Arturo, en un SGML que recuerda a HTML no generan código para el browser.

Existen algunas librerías que intentan solventar esto, pero su funcionamiento es limitado y problemático. El uso de componentes UX creados con un lenguaje propio nos ata a un framework concreto, ¡lo contrario de la universalidad multiplataforma que buscábamos!

En las apps nativas podremos crear tantos hilos de ejecución como deseemos, se soportan las coroutines y por supuesto podemos utilizar servicios para realizar trabajo en background: programar tareas a determinadas horas, terminar el trabajo en curso aunque el usuario apague la pantalla, ejecutar música en background…

En las híbridas no se soportan servicios de sistema y las tareas en segundo plano están limitadas al acceso a la red, ¡y eso en el mejor de los casos! Nativescript ejecuta todo el código en el hilo de la UI aunque permite usar una worker thread de manera muy limitada. React Native soporta HeadLessJs , un equivalente a servicios con menos funcionalidad, y solo se permite en Android. Está lejos de ser equivalente, y lo sabes.

Conseguir que estas aplicaciones se comporten como realmente nativas supone bastante trabajo de desarrolladores nativos, optimizando código y plugins, reduciendo la ventaja económica de programar una vez para ambas plataformas.

Otros aspectos que tener en cuenta

Por resumir otras ventajas de las apps nativas:

  • Trabajar en nativo permite el desarrollo para todo tipo de dispositivos como Wearables (Apple Watch, Android Wear), TV o, Coches (Android Auto, Apple Car).
  • Proporcionan una mayor seguridad. El uso de plugins y Javascript en las aplicaciones híbridas introduce nuevas capas de complejidad susceptibles de ser atacadas.
  • Mejoran la duración de la batería. El código está optimizado para la arquitectura, hace un uso más adecuado de los distintos núcleos de CPU/GPU y necesita menos capas de software para ejecutarse.
  • Permiten utilizar las funciones de accesibilidad nativas, especialmente buenas en iOS. Nos abre a todos nuestros clientes y mejora nuestra imagen corporativa.

En cuanto al entorno de desarrollo, los IDE para apps nativas son muy avanzados, especialmente el caso de Android Studio, basado en IntelliJ Idea. XCode también es un IDE potente. Ambos permiten el diseño de la UI mediante herramientas de arrastrar y soltar.

A la hora de realizar debugging facilitan mucho la tarea al desarrollador. Se puede debugear el código desde el IDE línea por línea o con breakpoints condicionales. Disponen de herramientas avanzadas de profiling que muestran en tiempo real los consumos de CPU, memoria y red y ambas plataformas facilitan la ejecución de test unitarios y funcionales.

Para desarrollar apps híbridas tenemos IDEs como WebStorm (de pago) o Visual Studio (según versiones) y otros con menos prestaciones tipo Visual Studio code, Atom, etc. que están bien, y utilidades y plugins para generar UI o profiles. Pero ninguna de estas herramientas alcanza la especialización y el “Integrated development environment” de los nativos.

Las librerías de analíticas, acceso a mBaaS (Firebase, AWS, Azure…), Marketing y Crash reporting disponen de SDKs optimizados para Android e iOS que se encargan de automatizar la toma de datos como las navegaciones entre pantallas, ejecuciones o logs de crash y mandarlos a la nube en background ocultando las complejidades al programador.

La actualización de una app nativa en los Stores no es el dolor que pretendes dibujarnos, Arturo: en Android son unos minutos y Apple ha mejorado mucho y ha prometido bajar de días a horas en los próximos meses.

La publicación en un entorno profesional incluye la revisión por parte de Apple o Google (que ha mejorado mucho en esto) de las aplicaciones, garantizando su compatibilidad y seguridad. Saltarse esto inyectando nuevo Javascript en las apps de los usuarios no parece muy buena idea.

La sincronización en la implementación de características entre los diferentes equipos de apps nativas suele ser una de las causas esgrimidas a favor de la unificación híbrida. Es importante que sea el scrum y no cada tecnología quien marque el ritmo de implementación. En un entorno de apps híbridas también tendremos que sincronizar las apps con la web, diseñadores, etc.

¿Vale la pena ahorrar un pequeño porcentaje en el software?

Un proyecto de una app tipo incluye muchos perfiles: Product Owner, Scrum Master, diseñadores de UX, arquitectos, desarrolladores backend, devops… Utilizar aplicaciones Javascript para unificar el Browser, Android e iOS supone un ahorro porcentual pequeño, mucho menor aún si usamos React Native o NativeScript que no nos servirán para el Browser.

Abaratar en la calidad de la app a cambio de dar una peor imagen al cliente y perder su fidelidad no es rentable a medio plazo. En el largo probablemente tengamos que gastar más dinero.

Hay un lugar para las tecnologías híbridas. Algunas partes de la app pueden requerir cambios muy frecuentes o mostrar contenido desarrollado para la web. En estos casos añadir algo de código React o una WebView a nuestra aplicación puede optimizar los recursos sin reducir la calidad general.

En apps muy pequeñas puede tener sentido hacer una versión híbrida de una web existente y si nuestra inversión en código Javascript para las reglas de negocio es muy grande podemos plantearnos una app parcialmente React Native, Facebook lo hace, Arturo, y ya sabemos cómo gasta batería. Pero si partimos de cero para hacer la app de la empresa y queremos que tenga futuro, desde mi punto de vista, el camino a seguir es nativo.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.