Un CRUD atomizado (V). Algunas mejoras.

En este artículo vamos a introducir algunas mejoras simples, pero de gran impacto en el funcionamiento final del CRUD.

Por una parte, nos ocuparemos de la cuestión programática, tratando de lograr el mayor desacoplamiento posible, a fin de aumentar la mantenibilidad y escalabilidad de nuestro CRUD. Esto es algo que, a ojos inexpertos, parecerá una pérdida de tiempo y un aumento de código. Sin embargo, a la larga nos reportará un gran beneficio.

ATENCIÓN. Recuerda siempre que programar para «salir del paso», es decir, para cubrir exclusivamente las necesidades mínimas actuales, sólo sirve para hipotecar el futuro de la aplicación, acumulando deuda técnica. Y cuando ese futuro llegue (y llegará, no te quepa duda, antes de lo que piensas), pagar esa hipoteca te puede costar decenas o cientos de veces más tiempo y recursos que si hubieras planificado bien desde el principio. Si piensas que ahora «no tienes tiempo» para hacer bien las cosas, recuerda que mañana tendrás que sacar «de donde sea» tiempo para hacerlas dos veces (o diez, o veinte). Esta es una lección que yo tuve que aprender «por la vía dura» hace años y espero que tú no tengas que experimentarlo.

En otro orden de cosas, en el próximo artículo, retocaremos la aplicación para mejorar la experiencia del usuario, lo que, sin duda, es extremadamente importante en el desarrollo web actual.

EL EMPAQUETADO DE DATOS

En nuestro módulo MembersModule y, más concretamente, en el MemberFormComponent, tenemos un método que recoge el objeto que contiene los datos de un miembro, así como su avatar, y lo empaqueta todo en un objeto FormData para enviarlo a la correspondiente API. Seguro que lo has visto revisando el código. Es el método buildDataPack():

Dado que el uso de los objetos FormData es muy cómodo y práctico, usaremos esta técnica muy a menudo para pasar paquetes completos de datos de un sitio a otro. Por lo tanto, la construcción de un FormData debería ser un servicio que pudiéramos inyectar donde lo deseemos, y solo tengamos que consumirlo donde sea necesario. No sé si te acuerdas que, cuando preparamos la base de esta aplicación, en el primer artículo de esta sección (te dejo aquí el enlace), creamos dos servicios: el HttpConnectService, que hemos estado usando para conectar con las APIS, y el DataPackService que, hasta ahora, no hemos tocado. Pues bien. Ha llegado la hora de usarlo.

EL DataPackService

El archivo data-pack.service.ts lo vamos a modificar así:

Como ves, le hemos creado un único método, llamado pack(), que recibe una matriz con los datos que debe empaquetar en un objeto FormData. Esta matriz también contiene los nombres con los que dichos elementos deben ser empaquetados (en seguida lo veremos). Monta el objeto FormData y lo devuelve a la lógica del componente que haya consumido el servicio.

Quiero llamar tu atención sobre lo que parece un comentario extraño en la línea resaltada (la 11). Parece un comentario, porque va precedido de //. La construcción for...in de JavaScript es vista con «malos ojos» por el linter de TypeScript de Angular. El linter es el mecanismo que nos avisa cuando TypeScript tiene algún error. Es una ayuda muy útil. Sin embargo, en ocasiones, detecta como errores sintaxis que son perfectamente válidas en JavaScript, y que funcionan sin ningún problema. No queremos que nos muestre errores que, realmente, no lo son. Con este comentario, hacemos que el linter «ignore» el error que «cree» que hay en la línea siguiente.

LA LÓGICA DEL COMPONENTE

Ahora tenemos que modificar la lógica del componente (member-form.component.ts) para que inyecte y consuma este servicio. Para ello, por supuesto, el primer paso es importarlo. Lo hacemos en la siguiente línea:

import { DataPackService } from '../services/data-pack.service';

El siguiente paso es incluirlo en la clase del mismo modo que hemos hecho con HttpConnectService y con ActivatedRoute, es decir, incorporándolo a la firma del constructor, así:

Y ahora modificamos el método buildDataPack(), de modo que coja los datos, se los envíe al servicio, y recupere lo que este le entrega, así:

Y ya está. De este modo, cualquier otro componente de MembersModule que pueda necesitar este servicio en el futuro lo podrá inyectar y consumir de la misma forma. Y si no encontramso con la necesidad de modificar la construcción del objeto FormData en algún momento, sólo tendremos que modificarla en el servicio, y habrá quedado modificada en todos los componentes que lo usen.

MEJORANDO AÚN MÁS

Lo que acabamos de ver es, no cabe duda, una importante mejora. Teniendo un solo componente en un sólo módulo que necesita este servicio, no parece relevante. Sin embargo, en el furturo podremos tener, en este módulo, más componentes que necesiten este servicio. Y más aún. Al ser una funcionalidad tan versátil, es muy probable que, si nuestra aplicación crece, debamos contar con este servicio en otros módulo. Por ejemplo, podría incluir un módulo para un almacén de productos, con su propio CRUD, dentro de la misma aplicación.

En realidad, con esa visión de futuro, no deberíamos haber creado nuestro servicio con:

ng g service members/services/DataPack

si no con:

ng g service services/DataPack

De este modo, podríamos hacerlo global a la aplicación. Lo hicimos así pensando, exclusivamente, en el módulo de miembros… y en como corregir esto ahora, antes de que sea demasiado tarde. Vamos a ver las modificaciones que necesitamos para que el servicio esté disponible para toda la aplicación.

En primer lugar, creamos un servicio DataPackService con la línea que acabamos de ver, es decir:

ng g service services/DataPack

En el archivo src/app/services/data-pack.service.ts copiamos el código de src/app/members/services/data-pack.services.ts.  A continuación, eliminamos src/app/members/services/data-pack.services.tssrc/app/members/services/data-pack.services.spec.ts.

Lo siguiente es cambiar la provisión del servicio. Si recuerdas el artículo que hemos mencionado antes, el servicio lo proveíamos en member.module.ts. Ahora lo quitamos de ahí y, como lo queremos disponible para toda la aplicación, lo vamos a proveer en app.module.ts. Observa, cuando te lo descargues, el código de ambos ficheros.

CONCLUYENDO

En este artículo hemos aprendido una mejora programática muy importante, ya que nos permite mayor escalabilidad en el futuro. Quizá la funcionalidad de construir el FormData no te parezca lo suficientemente relevante como para el esfuerzo que hemos hecho (vale, tampoco ha sido tanto). Sin embargo, lo que hemos aprendido sobre previsión de futuro ha valido la pena. La aplicación, en su estado actual, te la puedes bajar en este enlace.

   

Deja un comentario