Uso del patrón de complemento en una base de código modularizada | de Josef Raska | marzo 2023

Contenidos
La modularización se ha convertido en una parte esencial del desarrollo móvil a gran escala, pero no es fácil. Uno de los objetivos de la modularización efectiva es la retención módulos independientes y el Gráfico de módulo plano. El uso de interfaces de complementos en los módulos es una de las técnicas más efectivas para lograr esto y obtener el resultado deseado. Ventajas. Veamos cómo usarlo.
Imagen de Tania MT con ❤A menudo nos enfrentamos a un escenario común durante la modularización: un solo módulo tiene que depender y componer muchas otras funciones. Imagine que el inicio de la aplicación inicializa diferentes partes de la aplicación; en esta situación, el código de inicio tiene que acceder a muchas funciones. El enfoque típico es hacer que nuestra función dependa de todos los módulos relevantes para hacer referencia al código. Esto puede estar bien cuando dependemos de muy pocos módulos, pero causa varios problemas una vez que crecen las dependencias.
- Acoplamiento: Una función depende de muchas otras.
- complejidad: Agregación de dependencias en un módulo.
- Diagrama del módulo: Una vez que tenemos más de estas funciones de agregación, el gráfico del módulo se vuelve mucho más complejo y podemos terminar con una red de dependencias que es difícil de administrar (por qué es importante).
El problema: la altura del gráfico crece y los módulos están estrechamente acoplados. Hay muchas situaciones en las que necesita muchos módulos para contribuir a la lógica común donde los complementos brindan una solución. Algunos ejemplos:
- Lanzamiento de la aplicación: Muchos módulos requieren algún tipo de inicialización y deben conectarse al método Application.onCreate o en algún otro punto del ciclo de vida.
- Iniciar sesión o cerrar sesión: Varias partes de la aplicación deben configurarse o limpiarse cuando el usuario inicia o cierra sesión.
- manejo de empujeNota: Normalmente, un módulo es el punto de entrada para recibir mensajes push; sin embargo, es posible que varios módulos deseen recibir diferentes tipos de mensajes.
- manejo enlaces profundos: Similar a push, un módulo sirve como punto de entrada mientras que muchos módulos tienen que procesar diferentes enlaces profundos.
- característica especial interruptores: es posible que un módulo desee declarar diferentes alternancias, pero la aplicación puede tener un único extremo de alternancia para todos los módulos.
- Encabezados HTTP: Diferentes módulos quieren configurar encabezados comunes para la aplicación.
La solución general implica una colección de complementos que se ensamblan en módulos, recopilados manualmente o mediante inyección de dependencia como Dagger. Usaremos un complemento de inicio de sesión con Dagger como ejemplo, pero el mismo concepto se puede implementar a través de otros enfoques para pasar dependencias.Ejemplo de complemento: ejemplo de inicio de sesión.
- Un módulo de funciones define una interfaz de complemento pública y espera recibir una colección de instancias que implementan la interfaz. Imaginemos un módulo :login-api que proporciona una interfaz que se usa en muchos módulos.
Interfaz LoginPlugin {fun onLogin(usuario: Usuario)fun onLogout()}2. El módulo :login usa los complementos como una colección. Clase LoginLogic @Inject Constructor (val loginPlugins: @JvmSuppressWildcards Set
¿Por qué es esto poderoso?
- El módulo :login está completamente desacoplado del resto de la aplicación y no sabe nada sobre tematización.
- Podemos agregar o quitar lógica según los módulos que incluyamos. Esto es útil cuando tiene varias aplicaciones, quiere aplicaciones que solo contengan parte del código base para un desarrollo rápido o para aplicaciones instantáneas.
- Podemos proporcionar varios complementos para nuestras pruebas que podemos usar para verificar la lógica.
- Podemos lograr funciones completamente aisladas sin modificar el módulo, solo complementos.
ejemplos
Este concepto definitivamente no es nuevo y podemos encontrar muchos ejemplos existentes. Nada es perfecto y las interfaces de los complementos también tienen sus propios inconvenientes que debemos tener en cuenta para evitar que nos afecten.
- Faltan los complementos necesarios: Es fácil olvidarse de agregar un complemento del que depende la aplicación o enlazarlo incorrectamente. La aplicación compila y funciona bien, pero perderíamos funciones, lo que resultaría en un comportamiento errático. La solución es usar pruebas de integración y verificar que las funciones se comportan como se esperaba.
- Manejo de errores: Puede ser tentador envolver la ejecución del complemento en un intento de captura, pero no tenemos forma de saber qué lógica dentro de la abstracción del complemento está arrojando errores. La ejecución incompleta de los complementos puede generar un estado inconsistente. La solución depende del caso de uso, pero la recomendación general es que el complemento específico maneje el arrojable y se recupere. Si el complemento no puede manejar el error por sí mismo, simplemente deberíamos pasar el elemento descartable y no tratar de manejarlo en el nivel de colección de complementos.
- Dependencias entre complementos: Es posible que sea necesario ejecutar un grupo de complementos en un orden específico y existirán dependencias implícitas. La solución es establecer una prioridad y luego, después de insertar, usar la anotación @IntoMap Dagger para ordenar los complementos por prioridad, o usar una enumeración de implementaciones conocidas como clave de prioridad. Esto pasaría algo de conocimiento de implementación a la declaración del complemento como un compromiso, pero puede ser efectivo cuando se requiere un orden preciso de los complementos.
- Complementos de bajo rendimiento: La ejecución del complemento podría volverse lenta si hay muchos complementos o si un complemento está haciendo algo costoso. Porque el propietario de la interfaz del complemento no tiene control ni visibilidad sobre las implementaciones de los complementos que contribuyen. La solución está monitoreando las métricas de ejecución por complemento en partes críticas como el lanzamiento de la aplicación para identificar posibles cuellos de botella.
La modularización y aplanamiento del gráfico modular es difícil y por lo tanto requiere la introducción de ciertos patrones de modularización. El enfoque basado en complementos es uno de esos patrones, y su aplicación puede ayudar a lograr los beneficios deseados de la modularización y una base de código altamente modular. ¿Utiliza complementos en su proyecto u otros enfoques de modularización? Deja que otros lo sepan en los comentarios. ¡Diviértete modularizando!