Usando buenas prácticas

En el artículo anterior aprendimos a hacer un formulario muy simple. Vimos que funcionaba pero, al final del artículo comentamos que era «tosco». En realidad, el uso de buenas prácticas de programación, así como de las prestaciones de TypeScript, nos permiten hacer lo mismo con un código más limpio, mantenible y escalable.

En este artículo vamos a aprender técnicas que nos permitirán hacer nuestro formulario de usuarios de una forma más acorde con las directrices actuales de programación, lo que, antes de que te des cuenta, redundará en tu propio beneficio en muchos aspectos.

Ten en cuenta que un código limpio, mantenible y escalable es bueno para tí, según crezca tu proyecto, y para otros miembros de tu equipo o terceros desarrolladores que tengan que actuar sobre él. Y, si pensamos en el plano profesional, un código bien escrito te abrirá más puertas. Por lo tanto, vale la pena el esfuerzo que ahora dediques a familiarizarte con estas técnicas. Además, una vez interiorizadas, verás que te cuesta más esfuerzo hacerlo mal que hacerlo bien. Vamos a ello.

MONTANDO UNA CLASE

El formulario que hicimos en el artículo anterior parece el típico de una pantalla de login. Sin embargo, en este ejemplo vamos a considerarlo desde la perspectiva de que podría ser un formulario para dar de alta usuarios en nuestra web. Vale. Sólo dos datos, como el nombre de usuario y la clave no son, en modo alguno, la ficha de un usuario. Necesitaríamos otros datos como nombre real, email confirmación de clave, etc. Sin embargo, vamos a mantener sólo los dos campos que ya conocemos, para centrarnos más en la operativa. Que los árboles no nos impidan ver el bosque. Lo que sí le añadiremos es un identificador para uso interno de la aplicación. En seguida llegamos a eso.

Una vez que ya tenemos decidida la estructura de la ficha de los usuarios, tenemos que considerar que el usuario será un objeto, perteneciente a una clase. Por lo tanto, debemos crear una clase para el objeto. ¿Cómo y dónde creamos al clase?

Cuando vamos a usar clases en nuestra aplicación es razonable pensar que tales clases deberán estar disponibles no sólo desde un componente específico, sino desde varios componentes (tal vez situados, incluso, en diversos módulos). Por lo tanto, la ubicación de las clases debería ser alcanzable fácilmente desde cualquier punto de la aplicación. Lo habitual es crear una carpeta genérica para albergar las clases, dentro de la raíz del proyecto, es decir, src/app/. En esa ubicación crearemos un directorio al que podemos llamar, por ejemplo, my-classes, o darle un nombre usando el prefijo de la aplicación. Yo he optado por esta última opción, y lo he llamado amf-classes.

A continuación, dentro de ese directorio, vamos a crear una clase para los objetos que representen a los usuarios. La vamos a llamar, por seguir con la tónica de usar el prefijo de la aplicación, AmfUser. En la terminal de VSC tecleamos lo siguiente:

ng g class amf-classes/AmfUser

Tras unos segundos, la terminal nos responde:

create src/app/amf-classes/amf-user.ts (25 bytes)

Abrimos el archivo que se acaba de crear y vemos la estructura básica, vacía, de la clase:

Ahora tenemos que declarar las propiedades y métodos que necesitemos. De momento, crearemos los que necesitemos a priori, y, si luego nos hacen falta más, ya los iremos añadiendo. Así pues, nuestra clase queda, de momento, así:

Vamos a ver lo que hemos incluido. Empezamos por las líneas 2, 3 y 4. En ellas se definen las tres propiedades que, en principio, van a tener los objetos de esta clase (id, username y password). Las variables las declaramos privadas (private) para que no sean accesibles directamente desde fuera de la clase, sino que haya que llegar a ellas a través de métodos setter y getter. Esto no es nada nuevo. La encapsulación es una buena práctica de programación en cualquier entorno o lenguaje, como ya sabes.

En las líneas de la 6 a la 10 se declara el constructor. Como sabes, este método se ejecuta, de forma automática, cada vez que se crea un nuevo objeto. En esta clase, el constructor es muy simple. Tan sólo le asigna un identificador único al usuario. Esto es porque el identificador debe asignarse automáticamente, de forma transparente al usuario. Ocurre un poco como cuando usamos bases de datos relacionales, del tipo de MySQL, y declaramos un campo como clave primaria autoincrementable. Sin embargo, en TypeScript no contamos con una función específica para generar un identificador único, al estilo de la combinación de uniqueid y mda5 en PHP, por ejemplo. Por esa razón, hemos tenido que crear una función específica para este fin. Lo hemos hecho con el método uniqueId(), declarado entre las líneas 32 y 38. No vamos a entrar en detalles, pero jugamos con una combinación de Date.now() y Math.random(), para generar un identificador que podemos estar razonablemente seguros de que será único. En principio, podría parecer que nos basta con el uso de Date.now(), porque nos devuelve un valor distinto cada milisegundo. Sin embargo, con la velocidad de proceso de los ordenadores actuales, y si nuestra aplicación tuviera múltiples concurrencias simultáneas, podría darse el caso de que dos o más usuarios compartieran identificador. Con este método estamos «casi» seguros de que eso no va a suceder. Y por «casi» entendemos «todo lo seguros que se puede estar». Sólo comentar que este método lo hemos declarado como privado, porque sólo vamos a necesitar acceder a él desde dentro de la clase (en concreto, dentro del constructor). Desde fuera no nos va a hacer falta.

Por lo demás, el constructor sólo asigna cadenas vacías a las otras propiedades. Esto también es una buena práctica de programación. Cuando se crea un objeto, es bueno asignarle valores por defecto a las propiedades, para que no queden como undefined. De esta forma, tipificamos la estructura del nuevo objeto.

El resto de la clase son los métodos setter y getter que comentábamos más arriba.

EL COMPONENTE PARA EL FORMULARIO

Vamos a crear un formulario en un componente nuevo, para conservar el del artículo anterior, a fin de poder ir comparando los ejercicios que hacemos. Para ello, empezamos generando un nuevo componente, dentro del módulo MyFormsModule, así:

ng g c my-forms/form02

La terminal nos responde con:

create src/app/my-forms/form02/form02.component.html (25 bytes)
create src/app/my-forms/form02/form02.component.spec.ts (628 bytes)
create src/app/my-forms/form02/form02.component.ts (269 bytes)
create src/app/my-forms/form02/form02.component.css (0 bytes)
update src/app/my-forms/my-forms.module.ts (454 bytes)

Vemos que la lógica del módulo (my-forms.module.ts) se ha modificado para reconocer el nuevo componente, así:

Observa las líneas resaltadas, para ver como ahora están declarados los dos componentes (el que teníamos de antes y el que acabamos de crear).

El siguiente paso de la preparación es importar la clase que hemos creado en la lógica del componente donde la vamos a usar (form02.component.ts), así:

En la línea resaltada, vemos como hacemos esto.

Vamos a hacer que el nuevo componente sea accesible desde el menú. Todavía no lo tenemos montado, pero no importa. Lo dejamos accesible, y luego ya lo montaremos. En la barra de navegación (commons/navbar.component.html) tenemos que añadirle un enlace en el submenú de formularios, así:

Observa el nuevo enlace en las líneas resaltadas. No tiene nada de especial.

Cómo el módulo de los formularios se carga en diferido, debemos añadir la ruta en el enrutador interno de dicho módulo (my-forms-routing.module.ts), así:

Y ya está el entorno preparado. Ahora vamos a «currarnos» el formulario.

MONTAR EL FORMULARIO

Ahora que ya tenemos la clase para manejar los objetos que representarán a los usuarios, vamos a replantear la lógica del componente del formulario. El archivo, ya lo sabes, claro, es form02.component.ts:

Observa la primera línea resaltada (la 2). En ella ves como se importa la clase AmfUser, que hemos creado anteriormente. Es necesario importarla, para poder usarla en el componente.

En la siguiente línea resaltada (la 10), se crea un objeto de la clase AmfUser. Como sabes, por el constructor de la clase, a este objeto ya se le asigna un identificador (propiedad id) único.

Luego encontramos el método createUser(), entre las líneas 18 y 21. Es similar al del ejemplo anterior, pero hay algunas leves mejoras. En primer lugar, ya no recibe dos parámetros, si no sólo uno. Este es el formulario en conjunto, en lugar de los campos individuales. Dentro del método se accede a cada campo como un elemento indexado, de forma que ya sabemos que el formulario se recibe como un arreglo. Así, el primer campo (con el índoce 0) contiene el primer campo del formulario (el del nombre de usuario) y el segundo (con el índice 1) contiene el segundo campo del formulario (el de la contraseña). La propiedad value de estos campos es asignada a las correspondientes propiedades del objeto mediante el método setter empleado para cada una.

Esto implica también algunos retoques en la vista (form02.component.html):

En primer lugar, observa la línea 3, donde se abre el formulario. Esta vez, le hemos asignado un identificador, al estilo de Angular, es decir, precedido con el signo #. Luego usaremos ese identificador para enviar el formulario.

En las líneas 5 y 9 vemos que a los campos les hemos dado el valor de las propiedades username y password del objeto AmfUser. Como el objeto está recién creado, estas son cadenas vacías, por lo que en los campos se muestran los placeholders. Sin embargo, lo hemos echo así para que veas la sintaxis. Como las propiedades las definimos como privadas en la clase AmfUser, no las referenciamos directamente, sino a través del método getter correspondiente. Este uso de métodos getter los ves también en el condicional de la línea 17, y en la obtención de la propiedad id del usuario en la línea 19.

Ahora observa la línea 12, donde hacemos el binding de eventos. Como ves, esta vez sólo pasamos un argumento, que es el identificador que le asignamos al formulario. Por lo tanto, como respuesta a la pulsación del botón, se pasa a la lógica el formulario como un todo. Como ya sabemos, es dentro del TypeScript donde se extraen los datos elemento a elemento.

CONCLUYENDO

En este artículo hemos aprendido otro modo de manejar y pasar los datos de un formulario. Lo hemos mejorado bastante, desde el momento en que hemos creado una clase para gestionar los usuarios como objetos. Sin embargo, los formularios pueden mejorarse aún bastante. En el próximo artículo seguiremos trabajando en esto, ya que aún es mucho lo que podemos hacer. La aplicación, en su estado actual, te la puedes bajar en este enlace.

   

Deja un comentario