Optimización de las acciones del usuario con el patrón de comando: una guía práctica | de Saldi Sourabh | marzo 2023
Foto de Glenn Carstens-Peters en UnsplashUn aspecto importante de la creación de una experiencia de usuario atractiva es el manejo de las acciones realizadas por los usuarios y la presentación del «estado correcto» en función de la acción. En el pasado, cuando trabajábamos con sistemas de visualización más antiguos, teníamos bastante uno general Aceptación Habilidad para exponer datos en vivo o estados desde el modelo de vista, observarlos en actividades o fragmentos y actuar sobre ellos para generar un nuevo estado de IU o algunos efectos secundarios Lambdas para las acciones del usuario Es común usar lambdas para representar cada acción que un usuario realiza en una pantalla. Por ejemplo, considere el siguiente ejemplo. MyModelScreen(items = item.data,onSave = viewModel::addMyModel,modifier = modifier)Aquí pasamos onSave = viewModel::addMyModel, que funciona bien. Con la creciente aceptación de la composición del jetpack y las IU declarativas, a menudo observamos la elevación del estado y lambda -Las funciones están dispersas por todas partes. A medida que crece el código, se vuelve cada vez más complejo y caótico. Si observamos una pantalla más compleja (por ejemplo, en mi caso): estaba trabajando en una pantalla de pago que implica múltiples acciones, incluida la selección de la fecha de entrega, el ingreso de notas de pedido, la gestión de artículos y acciones como agregar, actualizar o eliminar artículos y el capacidad de cancelar o realizar un pedido, necesitaríamos pasar una gran cantidad de funciones de Lambda. En mi caso serían al menos 20 funciones Lambda diferentes. Imaginemos que necesitábamos agregar más acciones en esta pantalla. El código podría parecerse a esto, que funciona perfectamente y se ejecuta sin problemas. onDeleteClicked,onList = viewModel::onListClicked,modifier = modificador) Esto solo crecería a medida que sigamos agregando nuevas funcionalidades. Separar el estado y los eventos con una comprensión clara puede mejorar la legibilidad, el mantenimiento y la capacidad de prueba del código.Explorando los beneficios del patrón de comando para optimizar pantallas complejasEsto me impulsó a usar los principios del patrón de comando para abordar este problema. Tal como se define, este patrón implica la encapsulación de una solicitud como un objeto, lo que permite una mayor flexibilidad en términos de parametrización de clientes con diferentes solicitudes, organización de solicitudes en colas o registros y soporte para operaciones de deshacer.términos básicos antes de continuar:Recipiente: El objeto que recibe y ejecuta el comando (ViewModel en nuestro caso).llamador: El objeto que envía el comando al destinatario. (botones, etc)objeto de comando: El comando mismo que implementa el método de ejecución (ver más abajo, por ejemplo, AddCommand) contiene toda la información necesaria. para hacer la accióncliente: La aplicación o componente que sabe sobre el receptor, invocador, etc. (corresponde aproximadamente a nuestra actividad).Paso 1: configure el receptor de comandos y los comandos como se muestra a continuaciónEl patrón de comando encapsula una solicitud en un objeto que nos permite almacenar el comando y pasarlo a un método y devolver el comando como cualquier otro objeto. Comenzamos definiendo un receptor de comandos, que sirve como contrato para todas las acciones disponibles para el usuario para la pantalla dada. Luego vamos al comando en sí, que ejecuta un método, todas las acciones en esta pantalla implementan ese método. Escriba un receptor de comandos y una implementación para todos los comandos (acciones) permitidos para los usuarios en la pantalla dada.Paso 2: actualizar los comandos de ejecución de ViewModelDebido a que ViewModel implementa el contrato CommandReceiver, también implementa acciones para todos los comandos.Paso 3: elimine todas las lambdas para acciones y envíelas al procesador de comandos.//BeforeMyModelScreen(items = items.data,onSave = viewModel::onSaveClicked,onAdd = viewModel::onAddClicked,onUpdate = viewModel::onTextUpdate,onDelete = viewModel::onDeleteClicked,onList = viewModel::onListClicked,modifier = modificador)/ /AfterMyModelCommandScreen(items = items.data,modifier = modificador,commandProcessor = viewModel::processCommand)Paso 4: Comandos de la pantalla a ViewModel (¡patrón de comandos en acción!).Ahora pasamos los comandos como objetos al destinatario del comando de ejecución. Si bien puede parecer tentador usar esto en todos los componentes, se recomienda que solo lo use para elementos componibles a nivel de pantalla (que están cerca del baúl). Para el diseño a nivel de componente, este enfoque se presta a la reutilización, y preferiríamos que los componentes no manipularan directamente el estado de la pantalla. Aquí está el enlace al repositorio de GitHub donde puedes verlo en acción. ¡Gracias por leer!