Nuestra aplicación esta a dieta: Dynamic Features — Resultados y siguientes pasos
Fin de la serie sobre Dynamic Features, y les contamos los primeros resultados logrados, y en qué estamos trabajando ahora.
Bienvenidos nuevamente, ¿cómo están? Este será el último post de nuestra serie de historias incorporando Dynamic Features, recuerden que para un mejor entendimiento les recomendamos que realicen la lectura de las dos historias anteriores y así llevarse la historia completa.
Dentro de nuestra primer lectura vimos la definición de Dynamic Features, qué podemos lograr con esta herramienta, qué tipos de instalaciones dinámicas nos ofrece Google entre otras cosas. Por otro lado en nuestra segunda historia vimos cómo aplicamos Dynamic Features en Mercado Libre, qué cambios tuvimos a nivel de arquitectura, análisis sobre puntos generales como navegaciones externas, manejo de dependencias y cómo conviven entre los módulos dinámicos y la aplicación base, diferentes modos de compilación con assemble y bundle, cuándo y cómo sabemos cuando un módulo debería ser dinámico.
A quienes llegaron hasta este último post nos queda agradecerles y esperamos que hayan podido llevarse algún aprendizaje sobre esta experiencia que fuimos contando y que tiene como termino este artículo en cuestión, dicho esto, comencemos.
¿Qué resultados obtuvimos en esta primera experiencia con un módulo en producción?
Lo primero que pudimos verificar fue el peso que redujimos al tener este pequeño módulo como módulo dinámico. Aprendimos que dentro de la store de Google podemos ver, en la sección de bundles, el peso de descarga de la aplicación Base y el peso de descarga asignado al módulo dinámico.
Si bien eran pocos KB, nuestro enfoque estaba en ver la estabilidad de este módulo bajo el uso de los usuarios finales y poder recopilar de la experiencia de los mismos los posibles errores que pudieran tener dentro de todo el flujo de descarga e instalación que codeamos dentro de nuestro wrapper.
En conjunto con esto pudimos comenzar a ver como cada vez teníamos más y más tracks referenciados a los diferentes estados de la descarga e instalación del módulo y la experiencia de UX que definimos la fuimos cambiando y adaptando al uso.
En un principio manejamos un mensaje donde mostramos el porcentaje de descarga mientras el usuario esperaba para comenzar el flujo dinámico, mientras que luego lo fuimos adaptando ya que al pesar tan poco la descarga era casi inmediata y el porcentaje casi que pasaba volando de 0 a 100.
A partir de acá comenzamos a analizar internamente dentro de nuestras aplicaciones qué módulos cumplían con los criterios definidos para ser un módulo dinámico, y comenzamos a juntarnos con los equipos para contarles sobre esta iniciativa haciendo énfasis siempre en darle la mejor experiencia posible a los usuarios finales, entonces:
¿Cuáles fueron nuestros siguientes pasos y el resultado general?
Lo primero que hicimos fue avanzar con varias POCs en los diferentes tipos de instalaciones, pero con foco en el tipo de descarga en install time, la cual no requiere de grandes cambios ni migraciones sobre los módulos en cuestión, y nos permiten definir cierto tipo de filtros entre los cuales nos enfocamos principalmente en los filtros por país.
Como sabrán, en nuestras aplicaciones existen diferentes configuraciones dependiendo del país en el que se encuentre el usuario y debido a esto, hay muchas funcionalidades que están apagadas para ciertos países, pero el código que se baja el usuario desde el store es el mismo para todos.
Esto quiere decir que mi empaquetado tiene features dentro que como usuario de un país X no puedo acceder, pero ese mismo feature genera peso de descarga e instalación en mi empaquetado.
Por eso, la ganancia de tener módulos con el tipo de instalación install time nos daba un buen beneficio de forma rápida y sin mucho esfuerzo ya que no requiere grandes cambios dentro del módulo que será dinámico en cuestión.
Luego de realizar varias POCs con este feature, llevamos a producción aún más equipos que cumplian con los requerimientos para ser módulos dinámicos.
Terminamos el año 2021 habiendo reducido en un 8% el peso de descarga de nuestras aplicaciones de Mercado Libre y Mercado Pago ya que principalmente trabajamos con módulos compartidos entre apps.
En paralelo con los análisis para ver qué módulos deberíamos incluir en esta nueva herramienta, necesitábamos poner mucho foco en la experiencia de nuestros desarrolladores al momento de probar los flujos, principalmente en los que ahora son dinámicos.
Conociendo Meli Store: nuestra tienda interna
Por si no lo sabían, dentro de Mercado Libre tenemos una tienda de aplicaciones interna llamada Meli Store, tal cual existe hoy en dia PlayStore y AppStore, la cual nos permite principalmente compartir nuestro desarrollo en etapas tempranas con cualquier sector de la compañía con el objetivo de mejorar nuestras pruebas y mostrar resultados.
Para contarles la adaptación que tuvimos que hacer sobre esta herramienta una vez que salimos con Dynamic Feature a producción, comenzaremos por contarles sobre la necesidad.
A modo de resumen del uso de Meli Store, es una tienda que nos permite subir apps a un storage interno donde quedan disponibles para consumirse dentro de una app interna y que cualquier persona de Mercado Libre pueda instalarla, entonces…
¿Cuál fue la problemática con Dynamic Features y nuestras pruebas con apks?
La principal problemática que surgió es que para el correcto funcionamiento de los módulos dinámicos necesitamos que el empaquetado se genere como un .aab, un Android App Bundle, ya que de lo contrario, en el empaquetado .apk como el módulo no forma parte de la app base lo deja excluido y al tratar de acceder a estos módulos el flujo se rompe.
Para poder integrarnos con Dynamic Features primero tuvimos que darle soporte a poder subir empaquetados .aab
Luego de poder darle soporte al formato .aab avanzamos con una cuenta de Google oficial para comenzar a tratar de integrarnos con Internal App Sharing.
Esta fue la api de Google a la cual nos integramos, creando el token necesario.
¿Qué es Internal App Sharing?
El uso compartido de aplicaciones internas es la última progresión en las herramientas de desarrollo de PlayStore. Le permite cargar una aplicación y, a cambio, recibir una URL. Esta URL se puede compartir y le permite instalar la aplicación en su dispositivo.
Existen algunas medidas de seguridad. Puede restringir quién puede cargar aplicaciones para compartir aplicaciones internas. También puede limitar quién puede descargarlos.
Si quieren saber más sobre internal sharing pueden acceder a los siguientes Links:
Sobre esta herramienta está nuestro foco para integrarnos desde nuestra Meli Store y poder compartir el uso de nuestros empaquetados con los módulos dinámicos dentro.
¿Cómo comunicamos nuestro backend con Internal App Sharing?
Para esto utilizamos Fastlane a través de sus actions, acá la guía que seguimos con la documentación oficial.
Y como último paso lo que hicimos fue crear una variante de nuestra app productiva como lo es un mds (mds: es un buildtype que nos permite generar un empaquetado con ciertas configuraciones que luego publicamos en nuestro Meli Store), registrando su applicationId como parte de una nueva aplicación dentro de nuestra cuenta de PlayStore y con esto ya estaríamos en condiciones para probar dynamic feature sin que afecte a producción.
Como resultado gracias a la integración que realizamos ahora podemos acceder a cada empaquetado de nuestra aplicación interna y accionar sobre la url que nos provee Internal App Sharing y de esta forma estamos comunicados directamente con PlayStore para descargar nuestro empaquetado como .aab dentro de la nueva aplicación para MDS que creamos en la misma Store.
Cabe destacar que para esto fue necesario expandir la arquitectura que teníamos definida para nuestro cliente al momento de generar estos empaquetados, y requirió muchas pruebas a nivel de nuestra Store, por todo este esfuerzo quisiera hacer una mención al gran equipo que formó esta iniciativa y que logró llevar esto al siguiente nivel dando una experiencia integrada a las herramientas que ya teníamos de forma súper escalable.
¿Cómo seguimos a partir de acá?
Estaremos sumando algunas métricas de performance a lo que ya tenemos para poder medir el tiempo de descarga de los módulos dinámicos entre otros datos que nos pueden ayudar a entender sobre la experiencia de los usuarios.
Principalmente lo que buscamos lograr con todo este trabajo fue generar conciencia en los equipos de que esta es una buena herramienta para sumar a mantener el peso de la app controlado siempre y cuando aplique usarla bajo los conceptos que ya definimos al principio.
Luego de realizar varias comunicaciones al respecto hoy en día la iniciativa funciona relativamente sola, donde nuestra participación ya es a nivel de acompañamiento a los equipos que necesiten algún tipo de soporte, o mejorando nuestras documentaciones.
En paralelo siempre mejorando las métricas que manejamos y dando visibilidad de las mismas, manteniéndonos actualizados con respecto a las versiones de play core que va sacando Google, pero ya sin trabajos activos con respecto a migraciones, sino que esto ya se trasladó a los equipos.
Es muy importante lograr transmitir el entendimiento de que cada equipo que aporta a nuestras aplicaciones nativas deben velar por ella, tanto en estabilidad como en peso, fue un desafío también este punto de nuestro lado para generar esa conciencia como equipo de arquitectura pero hoy en dia estamos en un punto donde los equipos vienen solos a consultar sobre la herramienta y se integran sumamente fácil.
Podemos decir que ya tenemos una herramienta con buena estabilidad, con buena adopción y que nos permite impactar buenos resultados a nivel de peso de la app pensando en los usuarios finales y sus experiencias que funciona casi independiente.
Agradecimiento
Si nos leíste hasta el final, te agradecemos por el tiempo invertido y esperamos que puedas sacar el mejor provecho de nuestra experiencia sobre el proceso de integración de Dynamic Features dentro de nuestras aplicaciones de Mercado Libre y Mercado Pago.
¡Muchas gracias!